Merge "Update cect_hf4_6_22_interruptedPowerOn and cect_hf4_6_23_interruptedStandby"
diff --git a/OWNERS b/OWNERS
index 8771ccd..adb9461 100644
--- a/OWNERS
+++ b/OWNERS
@@ -12,6 +12,6 @@
 
 # Android EngProd Approvers
 wenshan@google.com
-guangzhu@google.com
-jdesprez@google.com
+guangzhu@google.com #{LAST_RESORT_SUGGESTION}
+jdesprez@google.com #{LAST_RESORT_SUGGESTION}
 normancheung@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index e357e8f..2001b7b 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5445,6 +5445,7 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_audio" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.hdmi.cec" />
             <meta-data android:name="display_mode" android:value="multi_display_mode" />
             <meta-data android:name="ApiTest"
                 android:value="android.media.AudioDescriptor#getStandard|
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
index cf88726..00ad35c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
@@ -1,2 +1,5 @@
 # Bug template url: https://b.corp.google.com/issues/new?component=100560&template=63204
-file:platform/frameworks/base:/core/java/android/app/admin/EnterprisePlatform_OWNERS
\ No newline at end of file
+file:platform/frameworks/base:/core/java/android/app/admin/EnterprisePlatform_OWNERS
+
+# Bug component: 801321 = per-file Screenshot*.java
+per-file Screenshot*.java = mrenouf@google.com, mrcasey@google.com
\ No newline at end of file
diff --git a/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java b/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
index c5cd4dd..20fbc4f 100644
--- a/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
+++ b/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
@@ -155,6 +155,7 @@
         } catch (MirroredTypesException e) {
             return e.getTypeMirrors().stream()
                     .map(t -> (TypeElement) types.asElement(t))
+                    .sorted()
                     .collect(Collectors.toList());
         }
         throw new AssertionError("Could not extract classes from annotation");
@@ -830,10 +831,12 @@
         }
     }
 
-    private Set<ExecutableElement> getMethods(TypeElement interfaceClass, Elements elements) {
+    private List<ExecutableElement> getMethods(TypeElement interfaceClass, Elements elements) {
         Map<String, ExecutableElement> methods = new HashMap<>();
         getMethods(methods, interfaceClass, elements);
-        return new HashSet<>(methods.values());
+        ArrayList<ExecutableElement> methodList = new ArrayList<>(methods.values());
+        methodList.sort((e1, e2) -> Integer.compare(e1.getSimpleName().hashCode(), e2.getSimpleName().hashCode()));
+        return methodList;
     }
 
     private void getMethods(Map<String, ExecutableElement> methods, TypeElement interfaceClass,
diff --git a/common/device-side/device-info/Android.bp b/common/device-side/device-info/Android.bp
index a3e618b..6729ed2 100644
--- a/common/device-side/device-info/Android.bp
+++ b/common/device-side/device-info/Android.bp
@@ -29,11 +29,14 @@
         "compatibility-device-util-axt",
         "cts_window_jetpack_utils",
         "junit",
+        "android-key-attestation",
+        "Nene",
     ],
-
     libs: [
         "android.test.base",
     ],
 
     sdk_version: "test_current",
+    min_sdk_version: "21",
+    dxflags: ["--multi-dex"],
 }
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java
new file mode 100644
index 0000000..f0f5c62
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import static android.security.keystore.KeyProperties.DIGEST_SHA256;
+import static android.security.keystore.KeyProperties.KEY_ALGORITHM_EC;
+import static android.security.keystore.KeyProperties.PURPOSE_SIGN;
+import static android.security.keystore.KeyProperties.PURPOSE_VERIFY;
+
+import static com.android.bedstead.nene.packages.CommonPackages.FEATURE_DEVICE_ID_ATTESTATION;
+
+import static com.google.android.attestation.ParsedAttestationRecord.createParsedAttestationRecord;
+
+import static org.junit.Assert.assertTrue;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.content.pm.PackageManager;
+import android.security.keystore.DeviceIdAttestationException;
+import android.security.keystore.KeyGenParameterSpec;
+import android.util.Log;
+
+import com.android.compatibility.common.util.DeviceInfoStore;
+
+import com.google.android.attestation.AuthorizationList;
+import com.google.android.attestation.ParsedAttestationRecord;
+import com.google.android.attestation.RootOfTrust;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.spec.ECGenParameterSpec;
+import java.util.Base64;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Feature Keystore Attestation device info collector. Collector collects information from the
+ * device's KeyMint implementation as reflected by the data in the key attestation record. These
+ * will be collected across devices and do not collect and PII outside of the device information.
+ */
+public final class KeystoreAttestationDeviceInfo extends DeviceInfo {
+    private static final String LOG_TAG = "KeystoreAttestationDeviceInfo";
+    private static final String TEST_ALIAS_KEYSTORE = "testKeystore";
+    private static final String TEST_ALIAS_STRONG_BOX = "testStrongBox";
+    private static final byte[] CHALLENGE = "challenge".getBytes();
+
+    @Override
+    protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+        collectKeystoreAttestation(store);
+        if (getContext()
+                .getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_STRONGBOX_KEYSTORE)) {
+            collectStrongBoxAttestation(store);
+        }
+    }
+
+    private void generateKeyPair(String algorithm, KeyGenParameterSpec spec)
+            throws NoSuchAlgorithmException,
+                    NoSuchProviderException,
+                    InvalidAlgorithmParameterException {
+        KeyPairGenerator keyPairGenerator =
+                KeyPairGenerator.getInstance(algorithm, "AndroidKeyStore");
+        keyPairGenerator.initialize(spec);
+        KeyPair kp = keyPairGenerator.generateKeyPair();
+
+        if (kp == null) {
+            Log.e(LOG_TAG, "Key generation failed");
+            return;
+        }
+    }
+
+    private void collectKeystoreAttestation(DeviceInfoStore localStore) throws Exception {
+        KeyStore mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+        mKeyStore.load(null);
+        mKeyStore.deleteEntry(TEST_ALIAS_KEYSTORE);
+
+        localStore.startGroup("keymint_key_attestation");
+        loadCertAndCollectAttestation(mKeyStore, localStore, TEST_ALIAS_KEYSTORE, false);
+        localStore.endGroup();
+    }
+
+    private void collectStrongBoxAttestation(DeviceInfoStore localStore) throws Exception {
+        KeyStore mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+        mKeyStore.load(null);
+        mKeyStore.deleteEntry(TEST_ALIAS_STRONG_BOX);
+
+        localStore.startGroup("strong_box_key_attestation");
+        loadCertAndCollectAttestation(mKeyStore, localStore, TEST_ALIAS_STRONG_BOX, true);
+        localStore.endGroup();
+    }
+
+    private void loadCertAndCollectAttestation(
+            KeyStore keystore,
+            DeviceInfoStore localStore,
+            String testAlias,
+            boolean isStrongBoxBacked)
+            throws Exception {
+        Objects.requireNonNull(keystore);
+        KeyGenParameterSpec spec =
+                new KeyGenParameterSpec.Builder(testAlias, PURPOSE_SIGN | PURPOSE_VERIFY)
+                        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+                        .setDigests(DIGEST_SHA256)
+                        .setDevicePropertiesAttestationIncluded(
+                                getContext()
+                                        .getPackageManager()
+                                        .hasSystemFeature(FEATURE_DEVICE_ID_ATTESTATION))
+                        .setAttestationChallenge(CHALLENGE)
+                        .setIsStrongBoxBacked(isStrongBoxBacked)
+                        .build();
+
+        generateKeyPair(KEY_ALGORITHM_EC, spec);
+
+        Certificate[] certificates = keystore.getCertificateChain(testAlias);
+        assertTrue(certificates.length >= 1);
+
+        final X509Certificate attestationCert = (X509Certificate) certificates[0];
+        final AuthorizationList keyDetailsList;
+
+        ParsedAttestationRecord parsedAttestationRecord =
+                createParsedAttestationRecord(attestationCert);
+
+        keyDetailsList = parsedAttestationRecord.teeEnforced;
+
+        collectStoredInformation(localStore, keyDetailsList);
+    }
+
+    private static void collectStoredInformation(
+            DeviceInfoStore localStore, AuthorizationList keyDetailsList)
+            throws DeviceIdAttestationException, IOException {
+        if (keyDetailsList.rootOfTrust.isPresent()) {
+            collectRootOfTrust(keyDetailsList.rootOfTrust, localStore);
+        }
+        if (keyDetailsList.osVersion.isPresent()) {
+            localStore.addResult("os_version", keyDetailsList.osVersion.get());
+        }
+        if (keyDetailsList.osPatchLevel.isPresent()) {
+            localStore.addResult("patch_level", keyDetailsList.osPatchLevel.get());
+        }
+        if (keyDetailsList.attestationIdBrand.isPresent()) {
+            localStore.addResult(
+                    "id_brand", new String(keyDetailsList.attestationIdBrand.get(), UTF_8));
+        }
+        if (keyDetailsList.attestationIdDevice.isPresent()) {
+            localStore.addResult(
+                    "id_device", new String(keyDetailsList.attestationIdDevice.get(), UTF_8));
+        }
+        if (keyDetailsList.attestationIdProduct.isPresent()) {
+            localStore.addResult(
+                    "id_product", new String(keyDetailsList.attestationIdProduct.get(), UTF_8));
+        }
+        if (keyDetailsList.attestationIdManufacturer.isPresent()) {
+            localStore.addResult(
+                    "build_manufacturer",
+                    new String(keyDetailsList.attestationIdManufacturer.get(), UTF_8));
+        }
+        if (keyDetailsList.attestationIdModel.isPresent()) {
+            localStore.addResult(
+                    "build_model", new String(keyDetailsList.attestationIdModel.get(), UTF_8));
+        }
+        if (keyDetailsList.vendorPatchLevel.isPresent()) {
+            localStore.addResult("vendor_patch_level", keyDetailsList.vendorPatchLevel.get());
+        }
+        if (keyDetailsList.bootPatchLevel.isPresent()) {
+            localStore.addResult("boot_patch_level", keyDetailsList.bootPatchLevel.get());
+        }
+    }
+
+    private static void collectRootOfTrust(
+            Optional<RootOfTrust> rootOfTrust, DeviceInfoStore localStore) throws IOException {
+        if (rootOfTrust.isPresent()) {
+            localStore.addResult(
+                    "verified_boot_key",
+                    Base64.getEncoder().encodeToString(rootOfTrust.get().verifiedBootKey));
+            localStore.addResult("device_locked", rootOfTrust.get().deviceLocked);
+            localStore.addResult("verified_boot_state", rootOfTrust.get().verifiedBootState.name());
+            localStore.addResult(
+                    "verified_boot_hash",
+                    Base64.getEncoder().encodeToString(rootOfTrust.get().verifiedBootHash));
+        }
+    }
+}
diff --git a/common/device-side/util-axt/Android.bp b/common/device-side/util-axt/Android.bp
index d07fe3d..68f7637 100644
--- a/common/device-side/util-axt/Android.bp
+++ b/common/device-side/util-axt/Android.bp
@@ -19,6 +19,8 @@
 java_defaults {
     name: "compatibility-device-util-axt-default",
     sdk_version: "test_current",
+    min_sdk_version: "21",
+    dxflags: ["--multi-dex"],
 
     srcs: [
         "src/**/*.java",
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
index 2e17a8c..209ce99 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
@@ -1,6 +1,9 @@
 per-file AmMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
 per-file AnrMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
 per-file BaseDefaultPermissionGrantPolicyTest.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
+per-file CtsKeyEventUtil.java = file:platform/cts:/tests/tests/widget/OWNERS
+per-file CtsMouseUtil.java = file:platform/cts:/tests/tests/widget/OWNERS
+per-file CtsTouchUtils.java = file:platform/cts:/tests/tests/widget/OWNERS
 per-file ReadElf.java = enh@google.com
 per-file *Settings*.java = felipeal@google.com
 per-file User*Helper*.java = felipeal@google.com
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index d02dc42..c76b5aa 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -342,105 +342,10 @@
     // TODO: b/223837004
     private static final ImmutableSet<String> BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST =
         ImmutableSet.of(
-                // Already duplicate in BCP.
-                "Landroid/hidl/base/V1_0/DebugInfo;",
-                "Landroid/hidl/base/V1_0/IBase;",
                 // /apex/com.android.btservices/javalib/framework-bluetooth.jar
-                "Lcom/android/bluetooth/x/android/sysprop/AdbProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/ApkVerityProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/BluetoothProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/CarProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/ContactsProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/CryptoProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/DeviceProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/DisplayProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/HdmiProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/HypervisorProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/InputProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/MediaProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/NetworkProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/OtaProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/PowerProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/SetupWizardProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/SocProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/TelephonyProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/TraceProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/VndkProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/VoldProperties;",
-                "Lcom/android/bluetooth/x/android/sysprop/WifiProperties;",
                 "Lcom/android/bluetooth/x/com/android/modules/utils/ISynchronousResultReceiver;",
                 "Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver-IA;",
                 "Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver;",
-                // /system/framework/services.jar
-                "Landroid/net/DataStallReportParcelable;",
-                "Landroid/net/DhcpResultsParcelable;",
-                "Landroid/net/IIpMemoryStore;",
-                "Landroid/net/IIpMemoryStoreCallbacks;",
-                "Landroid/net/INetworkMonitor;",
-                "Landroid/net/INetworkMonitorCallbacks;",
-                "Landroid/net/INetworkStackConnector;",
-                "Landroid/net/INetworkStackStatusCallback;",
-                "Landroid/net/InformationElementParcelable;",
-                "Landroid/net/InitialConfigurationParcelable;",
-                "Landroid/net/IpMemoryStoreClient;",
-                "Landroid/net/Layer2InformationParcelable;",
-                "Landroid/net/Layer2PacketParcelable;",
-                "Landroid/net/NattKeepalivePacketDataParcelable;",
-                "Landroid/net/NetworkFactory;",
-                "Landroid/net/NetworkFactoryShim;",
-                "Landroid/net/NetworkMonitorManager;",
-                "Landroid/net/NetworkTestResultParcelable;",
-                "Landroid/net/PrivateDnsConfigParcel;",
-                "Landroid/net/ProvisioningConfigurationParcelable;",
-                "Landroid/net/ScanResultInfoParcelable;",
-                "Landroid/net/TcpKeepalivePacketDataParcelable;",
-                "Landroid/net/dhcp/DhcpLeaseParcelable;",
-                "Landroid/net/dhcp/DhcpServingParamsParcel;",
-                "Landroid/net/dhcp/IDhcpEventCallbacks;",
-                "Landroid/net/dhcp/IDhcpServer;",
-                "Landroid/net/dhcp/IDhcpServerCallbacks;",
-                "Landroid/net/ip/IIpClient;",
-                "Landroid/net/ip/IIpClientCallbacks;",
-                "Landroid/net/ip/IpClientCallbacks;",
-                "Landroid/net/ip/IpClientManager;",
-                "Landroid/net/ip/IpClientUtil;",
-                "Landroid/net/ipmemorystore/Blob;",
-                "Landroid/net/ipmemorystore/IOnBlobRetrievedListener;",
-                "Landroid/net/ipmemorystore/IOnL2KeyResponseListener;",
-                "Landroid/net/ipmemorystore/IOnNetworkAttributesRetrievedListener;",
-                "Landroid/net/ipmemorystore/IOnSameL3NetworkResponseListener;",
-                "Landroid/net/ipmemorystore/IOnStatusAndCountListener;",
-                "Landroid/net/ipmemorystore/IOnStatusListener;",
-                "Landroid/net/ipmemorystore/NetworkAttributes;",
-                "Landroid/net/ipmemorystore/NetworkAttributesParcelable;",
-                "Landroid/net/ipmemorystore/OnBlobRetrievedListener;",
-                "Landroid/net/ipmemorystore/OnDeleteStatusListener;",
-                "Landroid/net/ipmemorystore/OnL2KeyResponseListener;",
-                "Landroid/net/ipmemorystore/OnNetworkAttributesRetrievedListener;",
-                "Landroid/net/ipmemorystore/OnSameL3NetworkResponseListener;",
-                "Landroid/net/ipmemorystore/OnStatusListener;",
-                "Landroid/net/ipmemorystore/SameL3NetworkResponse;",
-                "Landroid/net/ipmemorystore/SameL3NetworkResponseParcelable;",
-                "Landroid/net/ipmemorystore/Status;",
-                "Landroid/net/ipmemorystore/StatusParcelable;",
-                "Landroid/net/networkstack/NetworkStackClientBase;",
-                "Landroid/net/networkstack/aidl/NetworkMonitorParameters;",
-                "Landroid/net/networkstack/aidl/dhcp/DhcpOption;",
-                "Landroid/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable;",
-                "Landroid/net/networkstack/aidl/ip/ReachabilityLossReason;",
-                "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirk;",
-                "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable;",
-                "Landroid/net/shared/InitialConfiguration;",
-                "Landroid/net/shared/IpConfigurationParcelableUtil;",
-                "Landroid/net/shared/Layer2Information;",
-                "Landroid/net/shared/ParcelableUtil;",
-                "Landroid/net/shared/PrivateDnsConfig;",
-                "Landroid/net/shared/ProvisioningConfiguration;",
-                "Landroid/net/util/KeepalivePacketDataUtil;",
-                "Landroid/net/IpMemoryStore;",
-                "Landroid/net/NetworkFactoryLegacyImpl;",
-                "Landroid/net/networkstack/ModuleNetworkStackClient;",
-                "Landroid/net/NetworkFactoryImpl;",
                 // /system/framework/framework.jar
                 "Landroid/bluetooth/BluetoothProtoEnums;",
                 "Landroid/bluetooth/a2dp/BluetoothA2dpProtoEnums;",
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
index 173a6da..4226251 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
@@ -52,6 +52,9 @@
                     installResult);
 
             getDevice().executeShellCommand("am start -W " + TEST_PKG);
+            // Currently "wait for launch" doesn't actually wait for the frame to be finished
+            // So do a little sleep to let things stabilize
+            Thread.sleep(500);
 
             String frameinfo = mDevice.executeShellCommand("dumpsys gfxinfo " +
                     TEST_PKG + " framestats");
diff --git a/hostsidetests/gwp_asan/Android.bp b/hostsidetests/gwp_asan/Android.bp
index 2b938eb..14b7205 100644
--- a/hostsidetests/gwp_asan/Android.bp
+++ b/hostsidetests/gwp_asan/Android.bp
@@ -30,6 +30,7 @@
     ],
     data: [
         ":CtsGwpAsanEnabled",
+        ":CtsGwpAsanRecoverable",
     ],
 }
 
@@ -49,5 +50,5 @@
         "general-tests",
     ],
     jni_libs: ["libgwp_asan_cts_library_jni"],
-    sdk_version: "current",
+    sdk_version: "test_current",
 }
diff --git a/hostsidetests/gwp_asan/common/Android.bp b/hostsidetests/gwp_asan/common/Android.bp
index 30a086b..caf2f07 100644
--- a/hostsidetests/gwp_asan/common/Android.bp
+++ b/hostsidetests/gwp_asan/common/Android.bp
@@ -19,12 +19,12 @@
 java_library {
     name: "gwp_asan_cts_common",
     srcs: ["android/**/*.java"],
-    sdk_version: "current",
     static_libs: [
-        "ctstestrunner-axt",
         "androidx.test.rules",
         "androidx.test.core",
         "androidx.test.ext.junit",
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
     ],
 }
 
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
index 802f829..1b63808 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
@@ -23,6 +23,9 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.DropBoxReceiver;
+
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,8 +51,49 @@
     @Test
     public void testEnablement() throws Exception {
         TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
-        activity.callActivity(GwpAsanEnabledActivity.class);
-        activity.callActivity(GwpAsanDefaultActivity.class);
-        activity.callActivity(GwpAsanDisabledActivity.class);
+        activity.callActivityAndCheckSuccess(
+                GwpAsanEnabledActivity.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+        activity.callActivityAndCheckSuccess(
+                GwpAsanDefaultActivity.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+        activity.callActivityAndCheckSuccess(
+                GwpAsanDisabledActivity.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
+    }
+
+    @Test
+    public void testCrashToDropboxRecoverableEnabled() throws Exception {
+        TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+        activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
+        Assert.assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxRecoverableDefault() throws Exception {
+        TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+        DropBoxReceiver receiver =
+                Utils.getDropboxReceiver(
+                        mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
+        // Ensure the recoverable mode recovers, and returns success.
+        activity.callActivityAndCheckSuccess(
+                GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
+        Assert.assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxEnabled() throws Exception {
+        TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+        activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
+        Assert.assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxDefault() throws Exception {
+        TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
+        // Inherits from the app-wide property, which was `gwpAsanMode=always`. So, this should
+        // crash.
+        activity.callActivity(GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
+        Assert.assertTrue(receiver.await());
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
index 227377c..c67f569 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
@@ -23,15 +23,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        try {
-            if (Utils.isGwpAsanEnabled()) {
-                setResult(Utils.TEST_SUCCESS);
-            } else {
-                setResult(Utils.TEST_FAILURE);
-            }
-        } catch (Exception e) {
-            setResult(Utils.TEST_FAILURE);
-        }
+        setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
         finish();
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
index 84a44b0..dcff09a 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
@@ -32,16 +32,9 @@
 
     public class LocalBinder extends Binder {
         @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
-                try {
-                    reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
-                } catch (Exception e) {
-                    reply.writeInt(-1);
-                }
-                return true;
-            }
-            return false;
+        public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+            reply.writeInt(Utils.runTest(testId));
+            return true;
         }
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
index d87b541..4d3443b 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
@@ -23,15 +23,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        try {
-            if (Utils.isGwpAsanDisabled()) {
-                setResult(Utils.TEST_SUCCESS);
-            } else {
-                setResult(Utils.TEST_FAILURE);
-            }
-        } catch (Exception e) {
-            setResult(Utils.TEST_FAILURE);
-        }
+        setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
         finish();
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
index 2e7f18c..19eeedd 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
@@ -32,16 +32,9 @@
 
     public class LocalBinder extends Binder {
         @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == Utils.SERVICE_IS_GWP_ASAN_DISABLED) {
-                try {
-                    reply.writeInt(Utils.isGwpAsanDisabled() ? 1 : 0);
-                } catch (Exception e) {
-                    reply.writeInt(-1);
-                }
-                return true;
-            }
-            return false;
+        public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+            reply.writeInt(Utils.runTest(testId));
+            return true;
         }
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
index 6bdeed8..4d2658b 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
@@ -23,15 +23,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        try {
-            if (Utils.isGwpAsanEnabled()) {
-                setResult(Utils.TEST_SUCCESS);
-            } else {
-                setResult(Utils.TEST_FAILURE);
-            }
-        } catch (Exception e) {
-            setResult(Utils.TEST_FAILURE);
-        }
+        setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
         finish();
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
index f195480..1d1a1f7 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
@@ -32,16 +32,9 @@
 
     public class LocalBinder extends Binder {
         @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
-            if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
-                try {
-                    reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
-                } catch (Exception e) {
-                    reply.writeInt(-1);
-                }
-                return true;
-            }
-            return false;
+        public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+            reply.writeInt(Utils.runTest(testId));
+            return true;
         }
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
index f4ec2be..817acbc 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
@@ -18,8 +18,10 @@
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -27,6 +29,9 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.rule.ServiceTestRule;
 
+import com.android.compatibility.common.util.DropBoxReceiver;
+
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,26 +39,63 @@
 @RunWith(AndroidJUnit4.class)
 public class GwpAsanServiceTest {
     @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
+    private Context mContext;
 
-    private boolean runService(Class<?> cls, int testNum) throws Exception {
+    @Before
+    public void setUp() throws Exception {
+        mContext = getApplicationContext();
+    }
+
+    private void runServiceAndCheckSuccess(Class<?> cls, int testNum) throws Exception {
         Intent serviceIntent = new Intent(getApplicationContext(), cls);
         IBinder binder = mServiceRule.bindService(serviceIntent);
-        final Parcel request = Parcel.obtain();
         final Parcel reply = Parcel.obtain();
-        if (!binder.transact(testNum, request, reply, 0)) {
+        if (!binder.transact(testNum, Parcel.obtain(), reply, 0)) {
             throw new Exception();
         }
-        int res = reply.readInt();
-        if (res < 0) {
-            throw new Exception();
-        }
-        return res != 0;
+        assertEquals(reply.readInt(), Utils.TEST_SUCCESS);
+    }
+
+    private void runService(Class<?> cls, int testNum) throws Exception {
+        Intent serviceIntent = new Intent(getApplicationContext(), cls);
+        IBinder binder = mServiceRule.bindService(serviceIntent);
+        binder.transact(testNum, Parcel.obtain(), Parcel.obtain(), IBinder.FLAG_ONEWAY);
     }
 
     @Test
     public void testEnablement() throws Exception {
-        assertTrue(runService(GwpAsanEnabledService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
-        assertTrue(runService(GwpAsanDefaultService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
-        assertTrue(runService(GwpAsanDisabledService.class, Utils.SERVICE_IS_GWP_ASAN_DISABLED));
+        runServiceAndCheckSuccess(GwpAsanEnabledService.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+        runServiceAndCheckSuccess(GwpAsanDefaultService.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+        runServiceAndCheckSuccess(GwpAsanDisabledService.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
+    }
+
+    @Test
+    public void testCrashToDropboxEnabled() throws Exception {
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+        runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
+        assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxDefault() throws Exception {
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
+        runService(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
+        assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxRecoverableEnabled() throws Exception {
+        DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+        runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
+        assertTrue(receiver.await());
+    }
+
+    @Test
+    public void testCrashToDropboxRecoverableDefault() throws Exception {
+        DropBoxReceiver receiver =
+                Utils.getDropboxReceiver(
+                        mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
+        runServiceAndCheckSuccess(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
+        assertTrue(receiver.await());
     }
 }
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
index 95c8ecc..bdcfd73 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
@@ -17,7 +17,6 @@
 package android.cts.gwp_asan;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
@@ -41,14 +40,27 @@
         }
     }
 
-    public void callActivity(Class<?> cls) throws Exception {
+    public void callActivity(Class<?> cls, int testId) throws Exception {
+        Thread thread =
+                new Thread() {
+                    @Override
+                    public void run() {
+                        Intent intent = new Intent(getApplicationContext(), cls);
+                        intent.putExtra("testId", testId);
+                        startActivity(intent);
+                    }
+                };
+        thread.start();
+    }
+
+    public void callActivityAndCheckSuccess(Class<?> cls, int testId) throws Exception {
         Thread thread =
                 new Thread() {
                     @Override
                     public void run() {
                         try {
-                            Context context = getApplicationContext();
-                            Intent intent = new Intent(context, cls);
+                            Intent intent = new Intent(getApplicationContext(), cls);
+                            intent.putExtra("testId", testId);
                             startActivityForResult(intent, 0);
 
                             synchronized (mFinishEvent) {
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
index cf08537..b2ed1e3 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
@@ -18,8 +18,11 @@
 
 import android.app.Activity;
 import android.app.Application;
+import android.content.Context;
 import android.util.Log;
 
+import com.android.compatibility.common.util.DropBoxReceiver;
+
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
@@ -32,15 +35,17 @@
     public static final int TEST_SUCCESS = Activity.RESULT_FIRST_USER + 100;
     public static final int TEST_FAILURE = Activity.RESULT_FIRST_USER + 101;
 
-    public static final int SERVICE_IS_GWP_ASAN_ENABLED = 42;
-    public static final int SERVICE_IS_GWP_ASAN_DISABLED = 43;
+    public static final int TEST_IS_GWP_ASAN_ENABLED = 42;
+    public static final int TEST_IS_GWP_ASAN_DISABLED = 43;
+    public static final int TEST_USE_AFTER_FREE = 44;
 
-    // Check that GWP-ASan is enabled by allocating a whole bunch of heap
-    // pointers and making sure one of them is a GWP-ASan allocation (by
-    // comparing with /proc/self/maps).
+    public static final String DROPBOX_TAG = "data_app_native_crash";
+    public static final String DROPBOX_RECOVERABLE_TAG = "data_app_native_recoverable_crash";
+
+    // Check that GWP-ASan is enabled by allocating a whole bunch of heap pointers and making sure
+    // one of them is a GWP-ASan allocation (by comparing with /proc/self/maps).
     public static native boolean isGwpAsanEnabled();
-    // Check that GWP-ASan is disabled by ensuring there's no GWP-ASan mappings
-    // in /proc/self/maps.
+    // Check that GWP-ASan is disabled by ensuring there's no GWP-ASan mappings in /proc/self/maps.
     public static boolean isGwpAsanDisabled() throws IOException {
         try (FileReader fr = new FileReader("/proc/self/maps");
                 BufferedReader reader = new BufferedReader(fr)) {
@@ -55,4 +60,44 @@
         }
         return true;
     }
+
+    // Trigger a GWP-ASan instrumented use-after-free. This should always trigger a GWP-ASan report
+    // if it's enabled. In non-recoverable mode (i.e. gwpAsanMode=always), then this will crash the
+    // app with SEGV. In recoverable mode (i.e. gwpAsanMode=default), then this won't crash, but
+    // should still trigger all the dropbox/debuggerd entries.
+    public static native void instrumentedUseAfterFree();
+
+    public static int runTest(int testId) {
+        try {
+            if (testId == TEST_IS_GWP_ASAN_ENABLED) {
+                return Utils.isGwpAsanEnabled() ? Utils.TEST_SUCCESS : Utils.TEST_FAILURE;
+            }
+            if (testId == TEST_IS_GWP_ASAN_DISABLED) {
+                return Utils.isGwpAsanDisabled() ? Utils.TEST_SUCCESS : Utils.TEST_FAILURE;
+            }
+            if (testId == TEST_USE_AFTER_FREE) {
+                Utils.instrumentedUseAfterFree();
+                return Utils.TEST_SUCCESS;
+            }
+        } catch (Exception e) {
+            return Utils.TEST_FAILURE;
+        }
+        return Utils.TEST_FAILURE;
+    }
+
+    public static DropBoxReceiver getDropboxReceiver(
+            Context context, String processNameSuffix, String crashTag) {
+        return new DropBoxReceiver(
+                context,
+                crashTag,
+                context.getPackageName() + ":" + processNameSuffix,
+                "SEGV_ACCERR",
+                "Cause: [GWP-ASan]: Use After Free",
+                "deallocated by",
+                "backtrace:");
+    }
+
+    public static DropBoxReceiver getDropboxReceiver(Context context, String processNameSuffix) {
+        return getDropboxReceiver(context, processNameSuffix, DROPBOX_TAG);
+    }
 }
diff --git a/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
index f7d0176..5a5aa81 100644
--- a/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
+++ b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
@@ -91,3 +91,14 @@
     std::unique_ptr<char[]> gwp_asan_ptr = get_gwp_asan_pointer();
     return gwp_asan_ptr.get() == nullptr ? JNI_FALSE : JNI_TRUE;
 }
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_cts_gwp_1asan_Utils_instrumentedUseAfterFree(JNIEnv*) {
+    char* volatile p = nullptr;
+    {
+        std::unique_ptr<char[]> gwp_asan_ptr = get_gwp_asan_pointer();
+        p = gwp_asan_ptr.get();
+    }
+    if (!p) return;
+    __attribute__((unused)) volatile char c = *p;
+}
diff --git a/hostsidetests/gwp_asan/enabled/Android.bp b/hostsidetests/gwp_asan/enabled/Android.bp
index df592d2..b5a0b9f 100644
--- a/hostsidetests/gwp_asan/enabled/Android.bp
+++ b/hostsidetests/gwp_asan/enabled/Android.bp
@@ -19,8 +19,5 @@
 android_test_helper_app {
     name: "CtsGwpAsanEnabled",
     defaults: ["cts_gwp_asan_app_defaults"],
-    srcs: [
-        "src/**/*.java",
-    ],
     use_embedded_native_libs: false,
 }
diff --git a/hostsidetests/gwp_asan/enabled/AndroidManifest.xml b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
index 414d0c5..96f510e 100644
--- a/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
+++ b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
@@ -18,6 +18,10 @@
           package="android.cts.gwp_asan"
           android:targetSandboxVersion="2">
 
+  <!-- Needed for DropBoxManager.getNextEntry(...) -->
+  <uses-permission android:name="android.permission.READ_LOGS"/>
+  <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+
   <uses-sdk android:targetSdkVersion="30" />
   <application android:debuggable="true"
                android:extractNativeLibs="true"
diff --git a/hostsidetests/gwp_asan/recoverable/Android.bp b/hostsidetests/gwp_asan/recoverable/Android.bp
new file mode 100644
index 0000000..466944f
--- /dev/null
+++ b/hostsidetests/gwp_asan/recoverable/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsGwpAsanRecoverable",
+    defaults: ["cts_gwp_asan_app_defaults"],
+    use_embedded_native_libs: false,
+}
diff --git a/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml b/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml
new file mode 100644
index 0000000..ab0c632
--- /dev/null
+++ b/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.cts.gwp_asan"
+          android:targetSandboxVersion="2">
+
+  <!-- Needed for DropBoxManager.getNextEntry(...) -->
+  <uses-permission android:name="android.permission.READ_LOGS"/>
+  <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+
+  <uses-sdk android:targetSdkVersion="30" />
+  <application android:debuggable="true"
+               android:extractNativeLibs="true">
+    <processes>
+      <process />
+      <process android:process=":gwp_asan_enabled"
+               android:gwpAsanMode="always" />
+      <process android:process=":gwp_asan_disabled"
+               android:gwpAsanMode="never" />
+      <process android:process=":gwp_asan_default" />
+    </processes>
+
+    <uses-library android:name="android.test.runner" />
+
+    <activity android:name=".TestActivityLauncher" />
+    <activity android:name=".GwpAsanActivityTest" />
+
+    <activity android:name=".GwpAsanEnabledActivity"
+              android:process=":gwp_asan_enabled" />
+    <activity android:name=".GwpAsanDisabledActivity"
+              android:process=":gwp_asan_disabled" />
+    <activity android:name=".GwpAsanDefaultActivity"
+              android:process=":gwp_asan_default" />
+
+    <service android:name=".GwpAsanEnabledService"
+             android:process=":gwp_asan_enabled" />
+    <service android:name=".GwpAsanDisabledService"
+             android:process=":gwp_asan_disabled" />
+    <service android:name=".GwpAsanDefaultService"
+             android:process=":gwp_asan_default" />
+  </application>
+
+  <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                   android:targetPackage="android.cts.gwp_asan"
+                   android:label="CTS tests of GWP-ASan" />
+</manifest>
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
index 012a2ba..0ee8380 100644
--- a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
@@ -16,31 +16,16 @@
 
 package android.cts.gwp_asan;
 
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 
-import org.junit.After;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class EnabledTest extends BaseHostJUnit4Test {
-    private static final String TEST_APK = "CtsGwpAsanEnabled.apk";
-    private static final String TEST_PKG = "android.cts.gwp_asan";
-    private ITestDevice mDevice;
-
-    @Before
-    public void setUp() throws Exception {
-        mDevice = getDevice();
-        installPackage(TEST_APK, new String[0]);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        uninstallPackage(mDevice, TEST_PKG);
+public class EnabledTest extends GwpAsanBaseTest {
+    protected String getTestApk() {
+        return "CtsGwpAsanEnabled.apk";
     }
 
     @Test
@@ -50,4 +35,20 @@
         Assert.assertTrue(
                 runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testEnablement"));
     }
+
+    @Test
+    public void testCrashToDropbox() throws Exception {
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testCrashToDropboxEnabled"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testCrashToDropboxDefault"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testCrashToDropboxEnabled"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testCrashToDropboxDefault"));
+    }
 }
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java
new file mode 100644
index 0000000..2935af3
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.gwp_asan;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public abstract class GwpAsanBaseTest extends BaseHostJUnit4Test {
+    protected static final String TEST_PKG = "android.cts.gwp_asan";
+    protected ITestDevice mDevice;
+
+    protected abstract String getTestApk();
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = getDevice();
+        installPackage(getTestApk(), new String[0]);
+
+        // Reset the rate-limiting counters inside DropBoxManager, which only allows up to six
+        // dropbox entries with the same {process name + entry tag} within any 10 minute period. We
+        // can run the full suite right now without hitting the limit, but running the tests
+        // multiple times runs into the limit. See
+        // `services/core/java/com/android/server/am/DropboxRateLimiter.java` for more information.
+        mDevice.executeShellCommand("am reset-dropbox-rate-limiter");
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        uninstallPackage(mDevice, TEST_PKG);
+    }
+}
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
new file mode 100644
index 0000000..08f9186
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.gwp_asan;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class RecoverableTest extends GwpAsanBaseTest {
+    private static final String PROCESS_SAMPLING_SYSPROP = "libc.debug.gwp_asan.process_sampling.";
+
+    protected String getTestApk() {
+        return "CtsGwpAsanRecoverable.apk";
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        // Recoverable mode uses process sampling, which only enables GWP-ASan a fraction of the
+        // time (to preserve system-wide memory overhead). Make sure that our test app doesn't use
+        // process sampling, and enables GWP-ASan, when requested, every time. Note: We don't set
+        // the property on the ":gwp_asan_disabled" subprocess, because libc will enable GWP-ASan
+        // because a GWP-ASan property was overwritten.
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "1");
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "1");
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "1");
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "");
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "");
+        mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "");
+    }
+
+    @Test
+    public void testGwpAsanRecoverable() throws Exception {
+        Assert.assertTrue(
+                runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testEnablement"));
+        Assert.assertTrue(
+                runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testEnablement"));
+    }
+
+    @Test
+    public void testCrashToDropboxRecoverable() throws Exception {
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG,
+                        TEST_PKG + ".GwpAsanActivityTest",
+                        "testCrashToDropboxRecoverableEnabled"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG,
+                        TEST_PKG + ".GwpAsanActivityTest",
+                        "testCrashToDropboxRecoverableDefault"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG,
+                        TEST_PKG + ".GwpAsanServiceTest",
+                        "testCrashToDropboxRecoverableEnabled"));
+        Assert.assertTrue(
+                runDeviceTests(
+                        TEST_PKG,
+                        TEST_PKG + ".GwpAsanServiceTest",
+                        "testCrashToDropboxRecoverableDefault"));
+    }
+}
diff --git a/hostsidetests/incident/AndroidTest.xml b/hostsidetests/incident/AndroidTest.xml
index 727277d..73be7b4 100644
--- a/hostsidetests/incident/AndroidTest.xml
+++ b/hostsidetests/incident/AndroidTest.xml
@@ -20,9 +20,6 @@
     <option name="config-descriptor:metadata" key="parameter" value="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.SwitchUserTargetPreparer">
-        <option name="user-type" value="system" />
-    </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsIncidentHostTestCases.jar" />
     </test>
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index 772e9a9..5323edf 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -52,6 +52,7 @@
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
+import android.media.MediaDrm;
 import android.media.MediaPlayer;
 import android.net.ConnectivityManager;
 import android.net.Network;
@@ -95,6 +96,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
@@ -1199,4 +1201,22 @@
 
         assertNotNull(session);
     }
+
+    @Test
+    public void testMediaDrmAtoms() throws Exception {
+        UUID clearKeyUuid = new UUID(0xe2719d58a985b3c9L, 0x781ab030af78d30eL);
+        byte[] sid = null;
+        try (MediaDrm drm = new MediaDrm(clearKeyUuid)) {
+            drm.setPropertyString("drmErrorTest", "lostState");
+            for (int i = 0; i < 2; i++) {
+                sid = drm.openSession();
+                Assert.assertNotNull("null session id", sid);
+                try {
+                    drm.closeSession(sid);
+                } catch (MediaDrm.MediaDrmStateException e) {
+                    Log.d(TAG, "expected for lost state");
+                }
+            }
+        }
+    }
 }
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java
new file mode 100644
index 0000000..d752fa3
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.statsdatom.media;
+
+import static android.media.drm.Enums.DrmScheme.CLEAR_KEY_DASH_IF;
+import static android.media.drm.Enums.IDrmFrontend.IDRM_JNI;
+import static android.media.drm.Enums.SecurityLevel.SECURITY_LEVEL_MAX;
+import static android.media.drm.Enums.SecurityLevel.SECURITY_LEVEL_SW_SECURE_CRYPTO;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.cts.statsdatom.lib.AtomTestUtils;
+import android.cts.statsdatom.lib.ConfigUtils;
+import android.cts.statsdatom.lib.DeviceUtils;
+import android.cts.statsdatom.lib.ReportUtils;
+
+import com.android.os.AtomsProto;
+import com.android.os.StatsLog;
+import com.android.os.media.MediaDrmAtoms;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class MediaDrmAtomTests extends DeviceTestCase implements IBuildReceiver {
+
+    private IBuildInfo mCtsBuild;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertThat(mCtsBuild).isNotNull();
+        // Put a delay to give statsd enough time to remove previous configs and
+        // reports, as well as install the test app.
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.installTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_APK,
+                DeviceUtils.STATSD_ATOM_TEST_PKG, mCtsBuild);
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.uninstallTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG);
+        super.tearDown();
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    public void testMediaDrmAtom() throws Throwable {
+        // Upload the config.
+        ConfigUtils.uploadConfigForPushedAtoms(getDevice(),
+                DeviceUtils.STATSD_ATOM_TEST_PKG,
+                new int[]{
+                        AtomsProto.Atom.MEDIA_DRM_CREATED_FIELD_NUMBER,
+                        AtomsProto.Atom.MEDIA_DRM_ERRORED_FIELD_NUMBER,
+                        AtomsProto.Atom.MEDIA_DRM_SESSION_OPENED_FIELD_NUMBER
+                });
+        // Trigger AtomTests.
+        DeviceUtils.runDeviceTests(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, ".AtomTests",
+                "testMediaDrmAtoms");
+        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+        assertThat(data.size()).isAtLeast(1);
+
+        List<MediaDrmAtoms.MediaDrmCreated> createdList = new ArrayList<>();
+        List<MediaDrmAtoms.MediaDrmSessionOpened> openedList = new ArrayList<>();
+        List<MediaDrmAtoms.MediaDrmErrored> erroredList = new ArrayList<>();
+        int testAppUid = DeviceUtils.getStatsdTestAppUid(getDevice());
+
+        for (StatsLog.EventMetricData event : data) {
+            MediaDrmAtoms.MediaDrmCreated created = event.getAtom().getMediaDrmCreated();
+            MediaDrmAtoms.MediaDrmSessionOpened opened = event.getAtom().getMediaDrmSessionOpened();
+            MediaDrmAtoms.MediaDrmErrored errored = event.getAtom().getMediaDrmErrored();
+
+            if (created != null && created.getUid() == testAppUid) {
+                createdList.add(created);
+            }
+
+            if (opened != null && opened.getUid() == testAppUid) {
+                openedList.add(opened);
+            }
+
+            if (errored != null && errored.getUid() == testAppUid) {
+                erroredList.add(errored);
+            }
+        }
+        UUID clearKeyUuid = new UUID(0xe2719d58a985b3c9L, 0x781ab030af78d30eL);
+        // verify the events
+        assertThat(createdList.size()).isEqualTo(1);
+        assertThat(createdList.get(0).getScheme()).isEqualTo(CLEAR_KEY_DASH_IF);
+        assertThat(createdList.get(0).getUuidMsb())
+                .isEqualTo(clearKeyUuid.getMostSignificantBits());
+        assertThat(createdList.get(0).getUuidLsb())
+                .isEqualTo(clearKeyUuid.getLeastSignificantBits());
+        assertThat(createdList.get(0).getFrontend()).isEqualTo(IDRM_JNI);
+        assertThat(createdList.get(0).getVersion()).isNotEmpty();
+        assertThat(openedList.size()).isEqualTo(2);
+        assertThat(openedList.get(0).getObjectNonce()).isNotEmpty();
+        assertThat(openedList.get(0).getRequestedSecurityLevel()).isEqualTo(SECURITY_LEVEL_MAX);
+        assertThat(openedList.get(0).getOpenedSecurityLevel()).isEqualTo(
+                SECURITY_LEVEL_SW_SECURE_CRYPTO);
+        // TODO : to add check for erroredlist, cdm_error and error_code
+    }
+}
diff --git a/tests/autofillservice/res/layout/scrollable_login_activity.xml b/tests/autofillservice/res/layout/scrollable_login_activity.xml
new file mode 100644
index 0000000..dfa5227
--- /dev/null
+++ b/tests/autofillservice/res/layout/scrollable_login_activity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:orientation="vertical" >
+
+    <ScrollView android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <include layout="@layout/login_activity" />
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 7f5e8d3..e8a58bd 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -542,10 +542,9 @@
         // It works fine for portrait but for the platforms that the default orientation
         // is landscape, e.g. automotive. Depending on the height of the IME, the ID_LOGIN
         // button may not be visible.
-        // In order to avoid that,
-        // generate back key event to hide IME before pressing ID_LOGIN button.
-        mUiBot.pressBack();
 
+        // In order to avoid that, scroll until the ID_LOGIN button appears.
+        mUiBot.scrollToTextObject(ID_LOGIN);
         mUiBot.selectByRelativeId(ID_LOGIN);
         mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
index 4cab12c..ca91090 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
@@ -41,7 +41,7 @@
         Log.i(TAG, "onCreate(" + savedInstanceState + ")");
         super.onCreate(savedInstanceState);
 
-        setContentView(R.layout.login_activity);
+        setContentView(R.layout.scrollable_login_activity);
 
         findViewById(R.id.login).setOnClickListener((v) -> finish());
 
diff --git a/tests/camera/TEST_MAPPING b/tests/camera/TEST_MAPPING
new file mode 100644
index 0000000..683f34c
--- /dev/null
+++ b/tests/camera/TEST_MAPPING
@@ -0,0 +1,113 @@
+{
+  "kernel-presubmit": [
+    {
+      "name": "CtsCameraTestCases",
+      "options": [
+        {
+          // b/209623644 Unfit for Cuttlefish. Permanently excluded from presubmit.
+          "exclude-filter": "android.hardware.cts.CameraGLTest#testCameraToSurfaceTextureMetadata"
+        },
+        {
+          // b/204295528 Unsuitable for CF. Permanently excluded from presubmit.
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testBasicVideoStabilizationRecording"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testSupportedVideoSizes"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testVideoPreviewSurfaceSharing"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testBasicRecording"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testRecordingFramerateLowToHigh"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testRecordingFromPersistentSurface"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testVideoSnapshot"
+        },
+        {
+          // TODO(b/264226747)
+          "exclude-filter": "android.hardware.camera2.cts.CameraManagerTest#testCameraManagerListenerCallbacks"
+        },
+        {
+          // TODO(b/275072581)
+          "exclude-filter": "android.hardware.camera2.cts.CaptureRequestTest#testFocusDistanceControl"
+        },
+        {
+          // TODO(b/273837507)
+          "exclude-filter": "android.hardware.camera2.cts.DngCreatorTest#testRaw16JpegConsistency"
+        },
+        {
+          // TODO(b/275072024)
+          "exclude-filter": "android.hardware.camera2.cts.ExtendedCameraCharacteristicsTest#testLandscapeToPortraitOverride"
+        },
+        {
+          // TODO(b/274666525)
+          "exclude-filter": "android.hardware.camera2.cts.ImageReaderTest#testLongProcessingRepeatingFlexibleYuv"
+        },
+        {
+          // TODO(b/230479954)
+          "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testIntermediateSurfaceRecording"
+        },
+        {
+          // TODO(b/266222245)
+          "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAeAndAfCausality"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testBasicTriggerSequence"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAeThenAfTrigger"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAfThenAeTrigger"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testSimultaneousTriggers"
+        },
+        {
+          // TODO(b/269815708)
+          "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testAeCompensation"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testBasicRawZslCapture"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testPreviewPersistence"
+        },
+        {
+          "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testStillPreviewCombination"
+        },
+        {
+          // TODO(b/269968837)
+          "exclude-filter": "android.hardware.cts.CameraTest#testFocusDistances"
+        },
+        {
+          // TODO(b/262491831)
+          "exclude-filter": "android.hardware.cts.CameraTest#testMustPlayShutterSound"
+        },
+        {
+          "exclude-filter": "android.hardware.cts.CameraTest#testPreviewCallbackWithBuffer"
+        },
+        {
+          "exclude-filter": "android.hardware.cts.CameraTest#testPreviewPictureSizesCombination"
+        },
+        {
+          "exclude-filter": "android.hardware.cts.CameraTest#testTakePicture"
+        },
+        {
+          // TODO(b/269968837)
+          "exclude-filter": "android.hardware.cts.CameraTest#testVideoSnapshot"
+        },
+        {
+          // TODO(b/267597879)
+          "exclude-filter": "android.hardware.multiprocess.camera.cts.CameraEvictionTest#testCamera2AccessCallbackInSplitMode"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index 55eae8c..81173bb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -361,6 +361,7 @@
 
         final Rect keepClearRect = new Rect(0, 0, 25, 25);
         final View v = createTestViewInActivity(activity, keepClearRect);
+        final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
         mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
         assertSameElementsEventually(Arrays.asList(keepClearRect),
                 () -> getKeepClearRectsForActivity(activity));
@@ -372,15 +373,16 @@
         assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
                 () -> getKeepClearRectsForActivity(activity));
 
-        final List<Rect> expectedRectsInScreenSpace =
-                getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName());
-        assertSameElementsEventually(expectedRectsInScreenSpace,
+        final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+        expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+        expectedRectsOnDisplay.addAll(
+                getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName()));
+        assertSameElementsEventually(expectedRectsOnDisplay,
                 () -> getKeepClearRectsOnDefaultDisplay());
 
         activity.finishAndRemoveTask();
-        assertTrue(Collections.disjoint(
-                expectedRectsInScreenSpace,
-                getKeepClearRectsOnDefaultDisplay()));
+        assertSameElementsEventually(prevKeepClearRectsOnDisplay,
+                () -> getKeepClearRectsOnDefaultDisplay());
     }
 
     @Test
@@ -419,6 +421,7 @@
 
         final Rect viewBounds = new Rect(0, 0, 25, 25);
         final View v1 = createTestViewInActivity(activity1, viewBounds);
+        final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
         mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
         assertSameElementsEventually(Arrays.asList(viewBounds),
                 () -> getKeepClearRectsForActivity(activity1));
@@ -438,8 +441,12 @@
         mWmState.assertVisibility(activity2.getComponentName(), true);
 
         // Since both activities are fullscreen, WM only takes the keep clear areas from the top one
-        assertSameElementsEventually(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
-                activity2.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
+        final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+        expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+        expectedRectsOnDisplay.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
+                activity2.getComponentName()));
+        assertSameElementsEventually(expectedRectsOnDisplay,
+                () -> getKeepClearRectsOnDefaultDisplay());
     }
 
     @Test
@@ -449,15 +456,24 @@
         translucentTestSession.launchTestActivityOnDisplaySync(
                 TranslucentTestActivity.class, DEFAULT_DISPLAY);
         final TestActivity activity1 = translucentTestSession.getActivity();
-
         final Rect viewBounds = new Rect(0, 0, 25, 25);
         final View v1 = createTestViewInActivity(activity1, viewBounds);
+        final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
         translucentTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
-        assertSameElementsEventually(getRectsInScreenSpace(Arrays.asList(viewBounds),
-                activity1.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
 
+        // Add keep-clear rects in the activity
+        final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+        expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+        expectedRectsOnDisplay.addAll(getRectsInScreenSpace(Arrays.asList(viewBounds),
+                activity1.getComponentName()));
+        assertSameElementsEventually(expectedRectsOnDisplay,
+                () -> getKeepClearRectsOnDefaultDisplay());
+
+        // Start an opaque activity on top
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
         final TestActivity activity2 = mTestSession.getActivity();
+
+        // Add keep-clear rects in the opaque activity
         final View v2 = createTestViewInActivity(activity2);
         mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
         assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
@@ -466,8 +482,13 @@
         mWmState.waitAndAssertVisibilityGone(activity1.getComponentName());
         mWmState.assertVisibility(activity2.getComponentName(), true);
 
-        assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
-                () -> getKeepClearRectsForActivity(activity2));
+        // Only the opaque activity's keep-clear areas should be reported on the display
+        expectedRectsOnDisplay.clear();
+        expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+        expectedRectsOnDisplay.addAll(getRectsInScreenSpace(
+                    TEST_KEEP_CLEAR_RECTS, activity2.getComponentName()));
+        assertSameElementsEventually(expectedRectsOnDisplay,
+                () -> getKeepClearRectsOnDefaultDisplay());
     }
 
     @Test
@@ -475,30 +496,15 @@
         assumeTrue("Skipping test: no split multi-window support",
                 supportsSplitScreenMultiWindow());
 
-        final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
-                .setUseInstrumentation()
-                .setIntentExtra(extra -> {
-                    extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
-                            new ArrayList(TEST_KEEP_CLEAR_RECTS));
-                })
-                .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY);
+        startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+                KEEP_CLEAR_RECTS_ACTIVITY2, Collections.emptyList(), Collections.emptyList());
+        final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
 
-        final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
-                .setUseInstrumentation()
-                .setIntentExtra(extra -> {
-                    extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
-                            new ArrayList(TEST_KEEP_CLEAR_RECTS_2));
-                })
-                .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY2);
+        removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY).mTaskId);
+        removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY2).mTaskId);
 
-        launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
-
-        waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY, KEEP_CLEAR_RECTS_ACTIVITY
-                + " must be resumed");
-        waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY2, KEEP_CLEAR_RECTS_ACTIVITY2
-                + " must be resumed");
-        mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY, true);
-        mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY2, true);
+        startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+                KEEP_CLEAR_RECTS_ACTIVITY2, TEST_KEEP_CLEAR_RECTS, TEST_KEEP_CLEAR_RECTS_2);
 
         assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
                 () -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY));
@@ -506,11 +512,38 @@
                 () -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY2));
 
         final List<Rect> expected = new ArrayList();
+        expected.addAll(prevKeepClearRectsOnDisplay);
         expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, KEEP_CLEAR_RECTS_ACTIVITY));
         expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS_2, KEEP_CLEAR_RECTS_ACTIVITY2));
         assertSameElementsEventually(expected, () -> getKeepClearRectsOnDefaultDisplay());
     }
 
+    private void startKeepClearActivitiesInSplitscreen(ComponentName activity1,
+            ComponentName activity2, List<Rect> keepClearRects1, List<Rect> keepClearRects2) {
+        final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
+                .setUseInstrumentation()
+                .setTargetActivity(activity1)
+                .setIntentExtra(extra -> {
+                    extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+                            new ArrayList(keepClearRects1));
+                });
+
+        final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
+                .setUseInstrumentation()
+                .setTargetActivity(activity2)
+                .setIntentExtra(extra -> {
+                    extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+                            new ArrayList(keepClearRects2));
+                });
+
+        launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
+
+        waitAndAssertResumedActivity(activity1, activity1 + " must be resumed");
+        waitAndAssertResumedActivity(activity2, activity2 + " must be resumed");
+        mWmState.assertVisibility(activity1, true);
+        mWmState.assertVisibility(activity2, true);
+    }
+
     @Test
     public void testUnrestrictedKeepClearRects() throws Exception {
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
@@ -547,6 +580,7 @@
         mTestSession.runOnMainSyncAndWait(() -> {
             activity.addView(newView, params);
         });
+        waitForIdle();
         return newView;
     }
 
@@ -607,7 +641,8 @@
 
     private static <T> void assertSameElementsEventually(List<T> expected, Callable<List<T>> actual)
             throws Exception {
-        PollingCheck.check("Lists do not have the same elements.",
+        PollingCheck.check("Lists do not have the same elements."
+                + "Expected=" + expected + ", actual=" + actual.call(),
                 SAME_ELEMENT_ASSERTION_TIMEOUT,
                 () -> hasSameElements(expected, actual.call()));
     }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
index 59a1a2b..198e4b3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
@@ -17,6 +17,7 @@
 package android.server.wm;
 
 import static android.server.wm.WindowManagerTestBase.startActivity;
+import static android.view.WindowInsets.Type.captionBar;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -85,6 +86,9 @@
 
     @Test
     public void testSetDisablePreviewScreenshots() throws Exception {
+        final View decor = mActivity.getWindow().getDecorView();
+        final int captionBarHeight = decor.getRootWindowInsets().getInsets(captionBar()).top;
+
         BitmapPixelChecker pixelChecker = new BitmapPixelChecker(PixelColor.RED);
 
         int retries = 0;
@@ -93,7 +97,8 @@
             Bitmap bitmap = mWindowManager.snapshotTaskForRecents(mActivity.getTaskId());
             if (bitmap != null) {
                 int expectedMatching =
-                        bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED;
+                        bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED
+                                - (captionBarHeight * decor.getWidth());
                 Rect boundToCheck = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
                 int matchingPixels = pixelChecker.getNumMatchingPixels(bitmap, boundToCheck);
                 matchesPixels = matchingPixels >= expectedMatching;
diff --git a/tests/media/AndroidManifest.xml b/tests/media/AndroidManifest.xml
index 3a97bbe..0a1f5e0 100644
--- a/tests/media/AndroidManifest.xml
+++ b/tests/media/AndroidManifest.xml
@@ -23,6 +23,7 @@
 
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.CAMERA" />
 
     <application
         android:requestLegacyExternalStorage="true"
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index b1ccc46..4aafdb2 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -26,6 +26,11 @@
 import static org.junit.Assert.fail;
 
 import android.content.Context;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.display.DisplayManager;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
@@ -57,6 +62,7 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -65,6 +71,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 /**
  * This class comprises of routines that are generic to media codec component trying and testing.
@@ -115,6 +122,7 @@
             SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
                     >= Build.VERSION_CODES.TIRAMISU;
     public static final boolean IS_HDR_EDITING_SUPPORTED;
+    public static final boolean IS_HDR_CAPTURE_SUPPORTED;
     private static final String LOG_TAG = CodecTestBase.class.getSimpleName();
 
     public static final ArrayList<String> HDR_INFO_IN_BITSTREAM_CODECS = new ArrayList<>();
@@ -191,6 +199,26 @@
             AACObjectLD, AACObjectELD, AACObjectXHE};
     public static final Context CONTEXT =
             InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+    public static final int MAX_DISPLAY_HEIGHT_CURRENT =
+            Arrays.stream(CONTEXT.getSystemService(DisplayManager.class).getDisplays())
+                    .map(Display::getSupportedModes)
+                    .flatMap(Stream::of)
+                    .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+                    .orElseThrow(() -> new RuntimeException("Failed to determine max height"))
+                    .getPhysicalHeight();
+    public static final int MAX_DISPLAY_WIDTH_CURRENT =
+            Arrays.stream(CONTEXT.getSystemService(DisplayManager.class).getDisplays())
+                    .map(Display::getSupportedModes)
+                    .flatMap(Stream::of)
+                    .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+                    .orElseThrow(() -> new RuntimeException("Failed to determine max height"))
+                    .getPhysicalWidth();
+    public static final int MAX_DISPLAY_WIDTH_LAND =
+            Math.max(MAX_DISPLAY_WIDTH_CURRENT, MAX_DISPLAY_HEIGHT_CURRENT);
+    public static final int MAX_DISPLAY_HEIGHT_LAND =
+            Math.min(MAX_DISPLAY_WIDTH_CURRENT, MAX_DISPLAY_HEIGHT_CURRENT);
+
     public static String mediaTypeSelKeys;
     public static String codecPrefix;
     public static String mediaTypePrefix;
@@ -199,6 +227,10 @@
         CODEC_ALL, // All codecs must support
         CODEC_ANY, // At least one codec must support
         CODEC_DEFAULT, // Default codec must support
+        CODEC_HW, // If the component is hardware, then it must support
+        CODEC_SHOULD, // Codec support is optional, but recommended
+        CODEC_HW_RECOMMENDED, // Codec support is optional, but strongly recommended if component
+        // is hardware accelerated
         CODEC_OPTIONAL; // Codec support is optional
 
         public static String toString(SupportClass supportRequirements) {
@@ -209,6 +241,12 @@
                     return "CODEC_ANY";
                 case CODEC_DEFAULT:
                     return "CODEC_DEFAULT";
+                case CODEC_HW:
+                    return "CODEC_HW";
+                case CODEC_SHOULD:
+                    return "CODEC_SHOULD";
+                case CODEC_HW_RECOMMENDED:
+                    return "CODEC_HW_RECOMMENDED";
                 case CODEC_OPTIONAL:
                     return "CODEC_OPTIONAL";
                 default:
@@ -280,6 +318,7 @@
     static {
         MEDIA_CODEC_LIST_ALL = new MediaCodecList(MediaCodecList.ALL_CODECS);
         MEDIA_CODEC_LIST_REGULAR = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        IS_HDR_CAPTURE_SUPPORTED = isHDRCaptureSupported();
         IS_HDR_EDITING_SUPPORTED = isHDREditingSupported();
         CODEC_SEL_KEY_MEDIA_TYPE_MAP.put("vp8", MediaFormat.MIMETYPE_VIDEO_VP8);
         CODEC_SEL_KEY_MEDIA_TYPE_MAP.put("vp9", MediaFormat.MIMETYPE_VIDEO_VP9);
@@ -435,6 +474,23 @@
                                 + "for mediaType : " + mediaType + " formats: " + formats);
                     }
                     break;
+                case CODEC_HW:
+                    if (isHardwareAcceleratedCodec(codecName)) {
+                        fail("format(s) not supported by codec: " + codecName + " for mediaType : "
+                                + mediaType + " formats: " + formats);
+                    }
+                    break;
+                case CODEC_SHOULD:
+                    Assume.assumeTrue(String.format("format(s) not supported by codec: %s for"
+                            + " mediaType : %s. It is recommended to support it",
+                            codecName, mediaType), false);
+                    break;
+                case CODEC_HW_RECOMMENDED:
+                    Assume.assumeTrue(String.format(
+                            "format(s) not supported by codec: %s for mediaType : %s. It is %s "
+                                    + "recommended to support it", codecName, mediaType,
+                            isHardwareAcceleratedCodec(codecName) ? "strongly" : ""), false);
+                    break;
                 case CODEC_OPTIONAL:
                 default:
                     // the later assumeTrue() ensures we skip the test for unsupported codecs
@@ -455,6 +511,31 @@
         return isSupported;
     }
 
+    public static boolean isHDRCaptureSupported() {
+        // If the device supports HDR, hlg support should always return true
+        if (!MediaUtils.hasCamera()) return false;
+        CameraManager cm = CONTEXT.getSystemService(CameraManager.class);
+        try {
+            String[] cameraIds = cm.getCameraIdList();
+            for (String id : cameraIds) {
+                CameraCharacteristics ch = cm.getCameraCharacteristics(id);
+                int[] caps = ch.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+                if (IntStream.of(caps).anyMatch(x -> x
+                        == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT)) {
+                    Set<Long> profiles =
+                            ch.get(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES)
+                                    .getSupportedProfiles();
+                    if (profiles.contains(DynamicRangeProfiles.HLG10)) return true;
+                }
+            }
+        } catch (CameraAccessException e) {
+            Log.e(LOG_TAG, "encountered " + e.getMessage()
+                    + " marking hdr capture to be available to catch your attention");
+            return true;
+        }
+        return false;
+    }
+
     public static boolean isHDREditingSupported() {
         for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
             if (!codecInfo.isEncoder()) {
@@ -508,7 +589,7 @@
     public static boolean canDisplaySupportHDRContent() {
         DisplayManager displayManager = CONTEXT.getSystemService(DisplayManager.class);
         return displayManager.getDisplay(Display.DEFAULT_DISPLAY).getHdrCapabilities()
-                .getSupportedHdrTypes().length != 0;
+                .getSupportedHdrTypes().length > 0;
     }
 
     public static boolean areFormatsSupported(String name, String mediaType,
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 799aa72..8162e55 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -19,6 +19,7 @@
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ALL;
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ANY;
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_DEFAULT;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
@@ -34,6 +35,7 @@
 
 import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Assume;
 import org.junit.Test;
@@ -86,6 +88,7 @@
     private static final String MEDIA_TYPE_VORBIS = MediaFormat.MIMETYPE_AUDIO_VORBIS;
     private static final String MEDIA_TYPE_OPUS = MediaFormat.MIMETYPE_AUDIO_OPUS;
     private static final String MEDIA_TYPE_MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
+    private static final String MEDIA_TYPE_H263 = MediaFormat.MIMETYPE_VIDEO_H263;
     private static final String MEDIA_TYPE_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
     private static final String MEDIA_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
     private static final String MEDIA_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
@@ -126,6 +129,7 @@
         // mediaType, array list of test files (underlying elementary stream is same, except they
         // are placed in different containers), ref file, rms error, checksum, sample rate,
         // channel count, width, height, SupportClass
+        // TODO(b/275171549) Add tests as per TV multimedia requirements in 2.3.2
         final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
                 // vp9 test vectors with no-show frames signalled in alternate ways
                 {MEDIA_TYPE_VP9, new String[]{"bbb_340x280_768kbps_30fps_vp9.webm",
@@ -151,19 +155,10 @@
                 {MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
                         "bbb_2ch_44kHz_s16le.raw", 104.089027f, -1L, 44100, 2, -1, -1, CODEC_ALL},
 
-                // vp9 test vectors with AQ mode enabled
-                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
-                        null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ALL},
-                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
-                        null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ALL},
-                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
-                        null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ALL},
-                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
-                        null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ALL},
-
                 // video test vectors of non standard sizes
                 {MEDIA_TYPE_MPEG2, new String[]{"bbb_642x642_2mbps_30fps_mpeg2.mp4"},
-                        null, -1.0f, -1L, -1, -1, 642, 642, CODEC_ANY},
+                        null, -1.0f, -1L, -1, -1, 642, 642,
+                        MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
                 {MEDIA_TYPE_AVC, new String[]{"bbb_642x642_1mbps_30fps_avc.mp4"},
                         null, -1.0f, 3947092788L, -1, -1, 642, 642, CODEC_ANY},
                 {MEDIA_TYPE_VP8, new String[]{"bbb_642x642_1mbps_30fps_vp8.webm"},
@@ -177,6 +172,62 @@
                 {MEDIA_TYPE_MPEG4, new String[]{"bbb_130x130_192kbps_15fps_mpeg4.mp4"},
                         null, -1.0f, -1L, -1, -1, 130, 130, CODEC_ANY},
 
+                // video test vectors covering cdd requirements
+                // @CddTest(requirement="5.3.1/C-1-1")
+                {MEDIA_TYPE_MPEG2, new String[]{"bbb_1920x1080_mpeg2_main_high.mp4"}, null, -1.0f,
+                        -1L, -1, -1, 1920, 1080, MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
+
+                // @CddTest(requirement="5.3.2/C-1-1")
+                {MEDIA_TYPE_H263, new String[]{"bbb_352x288_384kbps_30fps_h263_baseline_l3.mp4"},
+                        null, -1.0f, -1L, -1, -1, 352, 288, CODEC_ALL},
+                {MEDIA_TYPE_H263, new String[]{"bbb_176x144_125kbps_15fps_h263_baseline_l45.mkv"},
+                        null, -1.0f, -1L, -1, -1, 176, 144, CODEC_ALL},
+
+                // @CddTest(requirement="5.3.3/C-1-1")
+                {MEDIA_TYPE_MPEG4, new String[]{"bbb_352x288_384kbps_30fps_mpeg4_simple_l3.mp4"},
+                        null, -1.0f, -1L, -1, -1, 352, 288, CODEC_ALL},
+
+                // @CddTest(requirements={"5.3.4/C-1-1", "5.3.4/C-1-2", "5.3.4/C-2-1"})
+                {MEDIA_TYPE_AVC, new String[]{"bbb_320x240_30fps_avc_baseline_l13.mp4"}, null,
+                        -1.0f, 2227756491L, -1, -1, 320, 240, CODEC_ALL},
+                {MEDIA_TYPE_AVC, new String[]{"bbb_320x240_30fps_avc_main_l31.mp4"}, null, -1.0f,
+                        3167475817L, -1, -1, 320, 240, CODEC_ALL},
+                {MEDIA_TYPE_AVC, new String[]{"bbb_720x480_30fps_avc_baseline_l30.mp4"}, null,
+                        -1.0f, 256699624L, -1, -1, 720, 480, CODEC_ALL},
+                {MEDIA_TYPE_AVC, new String[]{"bbb_720x480_30fps_avc_main_l31.mp4"}, null, -1.0f,
+                        1729385096L, -1, -1, 720, 480, CODEC_ALL},
+                // 5.3.4/C-1-2 mandates 720p support for avc decoders, hence this is being tested
+                // without any resolution check unlike the higher resolution tests for other codecs
+                {MEDIA_TYPE_AVC, new String[]{"bbb_1280x720_30fps_avc_baseline_l31.mp4"}, null,
+                        -1.0f, 4290313980L, -1, -1, 1280, 720, CODEC_ALL},
+                {MEDIA_TYPE_AVC, new String[]{"bbb_1280x720_30fps_avc_main_l31.mp4"}, null, -1.0f,
+                        3895426718L, -1, -1, 1280, 720, CODEC_ALL},
+
+                // @CddTest(requirement="5.3.5/C-1-1")
+                {MEDIA_TYPE_HEVC, new String[]{"bbb_352x288_30fps_hevc_main_l2.mp4"}, null, -1.0f,
+                        40958220L, -1, -1, 352, 288, CODEC_ALL},
+                {MEDIA_TYPE_HEVC, new String[]{"bbb_720x480_30fps_hevc_main_l3.mp4"}, null, -1.0f,
+                        3167173427L, -1, -1, 720, 480, CODEC_ALL},
+
+                // @CddTest(requirement="5.3.6/C-1-1")
+                {MEDIA_TYPE_VP8, new String[]{"bbb_320x180_30fps_vp8.mkv"}, null, -1.0f,
+                        434981332L, -1, -1, 320, 180, CODEC_ALL},
+                {MEDIA_TYPE_VP8, new String[]{"bbb_640x360_512kbps_30fps_vp8.webm"}, null, -1.0f,
+                        1625674868L, -1, -1, 640, 360, CODEC_ALL},
+
+                // @CddTest(requirement="5.3.7/C-1-1")
+                {MEDIA_TYPE_VP9, new String[]{"bbb_320x180_30fps_vp9.mkv"}, null, -1.0f,
+                        2746035687L, -1, -1, 320, 180, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_640x360_512kbps_30fps_vp9.webm"}, null, -1.0f,
+                        2974952943L, -1, -1, 640, 360, CODEC_ALL},
+
+                // @CddTest(requirement="5.3.9/C-1-1")
+                {MEDIA_TYPE_AV1, new String[]{"cosmat_720x480_30fps_av1_10bit.mkv"}, null,
+                        -1.0f, 2380523095L, -1, -1, 720, 480, CODEC_ALL},
+                {MEDIA_TYPE_AV1, new String[]{"bbb_720x480_30fps_av1.mkv"}, null, -1.0f,
+                        3229978305L, -1, -1, 720, 480, CODEC_ALL},
+
+
                 // audio test vectors covering cdd sec 5.1.3
                 // amrnb
                 {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
@@ -630,6 +681,76 @@
                             CODEC_ALL},
             }));
         }
+
+        // video test vectors covering cdd requirements
+        if (MAX_DISPLAY_HEIGHT_LAND >= 2160) {
+            exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+                    // @CddTest(requirements={"5.3.5/C-1-2", "5.3.5/C-2-1"})
+                    {MEDIA_TYPE_HEVC, new String[]{"bbb_3840x2160_30fps_hevc_main_l50.mp4"}, null,
+                            -1.0f, 2312004815L, -1, -1, 3840, 2160, CODEC_ANY},
+                    {MEDIA_TYPE_VP8, new String[]{"bbb_3840x2160_30fps_vp8.mkv"}, null, -1.0f,
+                            632639587L, -1, -1, 3840, 2160, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_3840x2160_30fps_vp9.mkv"}, null, -1.0f,
+                            279585450L, -1, -1, 3840, 2160, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.9/C-2-2"})
+                    {MEDIA_TYPE_AV1, new String[]{"bbb_3840x2160_30fps_av1.mkv"}, null, -1.0f,
+                            100543644L, -1, -1, 3840, 2160, CODEC_ANY},
+                    {MEDIA_TYPE_AV1, new String[]{"cosmat_3840x2160_30fps_av1_10bit.mkv"}, null,
+                            -1.0f, 4214931794L, -1, -1, 3840, 2160, CODEC_ANY},
+            }));
+        }
+        if (MAX_DISPLAY_HEIGHT_LAND >= 1080) {
+            exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+                    // @CddTest(requirement="5.3.4/C-2-2")
+                    {MEDIA_TYPE_AVC, new String[]{"bbb_1920x1080_avc_baseline_l40.mp4"}, null,
+                            -1.0f, 1332773556L, -1, -1, 1920, 1080, CODEC_ANY},
+                    {MEDIA_TYPE_AVC, new String[]{"bbb_1920x1080_avc_main_l40.mp4"}, null, -1.0f,
+                            2656846432L, -1, -1, 1920, 1080, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.5/C-1-2", "5.3.5/C-2-1"})
+                    {MEDIA_TYPE_HEVC, new String[]{"bbb_1920x1080_hevc_main_l40.mp4"}, null,
+                            -1.0f, 3214459078L, -1, -1, 1920, 1080, CODEC_ANY},
+                    // @CddTest(requirement="5.3.6/C-2-2")
+                    {MEDIA_TYPE_VP8, new String[]{"bbb_1920x1080_30fps_vp8.mkv"}, null, -1.0f,
+                            2302247702L, -1, -1, 1920, 1080, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1920x1080_vp9_main_l40.mkv"}, null, -1.0f,
+                            2637993192L, -1, -1, 1920, 1080, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.9/C-2-2"})
+                    {MEDIA_TYPE_AV1, new String[]{"bbb_1920x1080_30fps_av1.mkv"}, null, -1.0f,
+                            3428220318L, -1, -1, 1920, 1080, CODEC_ANY},
+                    {MEDIA_TYPE_AV1, new String[]{"cosmat_1920x1080_30fps_av1_10bit.mkv"}, null,
+                            -1.0f, 3477727836L, -1, -1, 1920, 1080, CODEC_ANY},
+            }));
+        }
+        if (MAX_DISPLAY_HEIGHT_LAND >= 720) {
+            exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+                    // @CddTest(requirement="5.3.5/C-1-2")
+                    {MEDIA_TYPE_HEVC, new String[]{"bbb_1280x720_1mbps_30fps_hevc_nob.mp4"},
+                            null, -1.0f, 3576783828L, -1, -1, 1280, 720, CODEC_ANY},
+                    // @CddTest(requirement="5.3.6/C-2-1")
+                    {MEDIA_TYPE_VP8, new String[]{"bbb_1280x720_30fps_vp8.mkv"}, null, -1.0f,
+                            2390565854L, -1, -1, 1280, 720, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"}, null,
+                            -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ANY},
+                    // @CddTest(requirements={"5.3.9/C-2-1"})
+                    {MEDIA_TYPE_AV1, new String[]{"bbb_1280x720_1mbps_30fps_av1.webm"}, null, -1.0f,
+                            4202081555L, -1, -1, 1280, 720, CODEC_ANY},
+                    {MEDIA_TYPE_AV1, new String[]{"cosmat_1280x720_24fps_1200kbps_av1_10bit.mkv"},
+                            null, -1.0f, 2039973562L, -1, -1, 1280, 720, CODEC_ANY},
+
+                    // vp9 test vectors with AQ mode enabled
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
+                            null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ANY},
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
+                            null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ANY},
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
+                            null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ANY},
+                    {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
+                            null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ANY},
+            }));
+        }
         return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
     }
 
@@ -642,7 +763,11 @@
     // "5.1.3", "5.1.2/C-1-11" are covered partially
     @CddTest(requirements = {"5.1.2/C-1-1", "5.1.2/C-1-2", "5.1.2/C-1-3", "5.1.2/C-1-4",
             "5.1.2/C-1-11", "5.1.2/C-1-5", "5.1.2/C-1-6", "5.1.2/C-1-8", "5.1.2/C-1-9",
-            "5.1.2/C-1-10", "5.1.2/C-2-1", "5.1.2/C-6-1", "5.1.3"})
+            "5.1.2/C-1-10", "5.1.2/C-2-1", "5.1.2/C-6-1", "5.1.3", "5.3.1/C-1-1", "5.3.2/C-1-1",
+            "5.3.3/C-1-1", "5.3.4/C-1-1", "5.3.4/C-1-2", "5.3.4/C-2-1", "5.3.4/C-2-2",
+            "5.3.5/C-1-1", "5.3.5/C-1-2", "5.3.5/C-2-1", "5.3.6/C-1-1", "5.3.6/C-2-1",
+            "5.3.6/C-2-2", "5.3.7/C-1-1", "5.3.7/C-2-1", "5.3.7/C-3-1", "5.3.9/C-1-1",
+            "5.3.9/C-2-1", "5.3.9/C-2-2"})
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testDecodeAndValidate() throws IOException, InterruptedException {
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 5896b23..d295a59 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -19,28 +19,30 @@
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
 import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing;
-import static android.mediav2.common.cts.CodecTestBase.CONTEXT;
 import static android.mediav2.common.cts.CodecTestBase.FIRST_SDK_IS_AT_LEAST_T;
 import static android.mediav2.common.cts.CodecTestBase.IS_AT_LEAST_T;
+import static android.mediav2.common.cts.CodecTestBase.IS_HDR_CAPTURE_SUPPORTED;
 import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_MAP;
 import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_PLUS_MAP;
-import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR_MAP;
 import static android.mediav2.common.cts.CodecTestBase.VNDK_IS_AT_LEAST_T;
+import static android.mediav2.common.cts.CodecTestBase.canDisplaySupportHDRContent;
 import static android.mediav2.common.cts.CodecTestBase.isVendorCodec;
 import static android.mediav2.common.cts.CodecTestBase.selectCodecs;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.hardware.display.DisplayManager;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecProfileLevel;
 import android.media.MediaCodecList;
 import android.mediav2.common.cts.CodecTestBase;
 import android.os.Build;
-import android.view.Display;
 
 import androidx.test.filters.SmallTest;
 
@@ -68,19 +70,11 @@
 @RunWith(Parameterized.class)
 public class CodecInfoTest {
     private static final String LOG_TAG = CodecInfoTest.class.getSimpleName();
-    private static final int[] DISPLAY_HDR_TYPES;
 
     public String mMediaType;
     public String mCodecName;
     public MediaCodecInfo mCodecInfo;
 
-    static {
-        DisplayManager displayManager = CONTEXT.getSystemService(DisplayManager.class);
-        DISPLAY_HDR_TYPES =
-                displayManager.getDisplay(Display.DEFAULT_DISPLAY).getHdrCapabilities()
-                        .getSupportedHdrTypes();
-    }
-
     public CodecInfoTest(String mediaType, String codecName, MediaCodecInfo codecInfo) {
         mMediaType = mediaType;
         mCodecName = codecName;
@@ -145,7 +139,7 @@
             // native level, separate the following to independent checks for HDR10 and HDR10+
             if (isHdr10Profile || isHdr10PlusProfile) {
                 assertTrue(mCodecInfo.getName() + " Advertises support for HDR10/HDR10+ profile " +
-                        pl.profile + " without any HDR display", DISPLAY_HDR_TYPES.length > 0);
+                        pl.profile + " without any HDR display", canDisplaySupportHDRContent());
             }
         }
     }
@@ -155,7 +149,8 @@
      * formats. The test only checks if the decoder/encoder is advertising the required color
      * format. It doesn't verify if it actually supports by decoding/encoding.
      */
-    @CddTest(requirements = {"5.1.7/C-1-2", "5.1.7/C-4-1", "5.12/C-6-5", "5.12/C-7-3"})
+    @CddTest(requirements = {"5.1.7/C-1-2", "5.1.7/C-1-3", "5.1.7/C-4-1", "5.12/C-6-5",
+            "5.12/C-7-1", "5.12/C-7-3"})
     @Test
     public void testColorFormatSupport() {
         Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
@@ -164,20 +159,54 @@
                 IntStream.of(caps.colorFormats)
                         .noneMatch(x -> x == COLOR_FormatYUV420Flexible));
 
-        // Encoders that support FEATURE_HdrEditing, must support P010 and ABGR2101010
-        // color format and at least one HDR profile
-        boolean hdrEditingSupported = caps.isFeatureSupported(FEATURE_HdrEditing);
-        if (mCodecInfo.isEncoder() && hdrEditingSupported) {
-            boolean abgr2101010Supported =
-                    IntStream.of(caps.colorFormats)
-                            .anyMatch(x -> x == COLOR_Format32bitABGR2101010);
-            boolean p010Supported =
-                    IntStream.of(caps.colorFormats).anyMatch(x -> x == COLOR_FormatYUVP010);
-            assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support " +
-                    "COLOR_FormatABGR2101010 and COLOR_FormatYUVP010 color formats.",
-                    abgr2101010Supported && p010Supported);
-            assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support any HDR " +
-                    "profiles.", CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMediaType));
+        assertFalse(mCodecInfo.getName()
+                        + " does not support at least one of planar or semi planar yuv 420 888",
+                IntStream.of(caps.colorFormats)
+                        .noneMatch(x -> x == COLOR_FormatYUV420PackedPlanar)
+                        && IntStream.of(caps.colorFormats)
+                        .noneMatch(x -> x == COLOR_FormatYUV420Planar)
+                        && IntStream.of(caps.colorFormats)
+                        .noneMatch(x -> x == COLOR_FormatYUV420PackedSemiPlanar)
+                        && IntStream.of(caps.colorFormats)
+                        .noneMatch(x -> x == COLOR_FormatYUV420SemiPlanar));
+
+        boolean canHandleHdr = CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMediaType);
+        if (mCodecInfo.isEncoder()) {
+            if (IS_HDR_CAPTURE_SUPPORTED && canHandleHdr) {
+                assertFalse(mCodecInfo.getName()
+                                + " supports HDR profile but does not support COLOR_FormatYUVP010",
+                        IntStream.of(caps.colorFormats).noneMatch(x -> x == COLOR_FormatYUVP010));
+            }
+
+            // Encoders that support FEATURE_HdrEditing, must support ABGR2101010 color format
+            // and at least one HDR profile
+            boolean hdrEditingSupported = caps.isFeatureSupported(FEATURE_HdrEditing);
+            if (hdrEditingSupported) {
+                boolean abgr2101010Supported = IntStream.of(caps.colorFormats)
+                        .anyMatch(x -> x == COLOR_Format32bitABGR2101010);
+                assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+                        + " COLOR_FormatABGR2101010 color formats.", abgr2101010Supported);
+                assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+                        + " any HDR profiles.", canHandleHdr);
+            }
+        } else {
+            if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T && canDisplaySupportHDRContent()) {
+                if (MediaUtils.isTv()) {
+                    // Some TV devices support HDR10 display with VO instead of GPU. In this
+                    // case, skip checking P010 on TV devices.
+                    Assume.assumeFalse(mCodecInfo.getName()
+                                    + " supports HDR profile but does not support "
+                                    + "COLOR_FormatYUVP010. Skip checking on TV device",
+                            IntStream.of(caps.colorFormats)
+                                    .noneMatch(x -> x == COLOR_FormatYUVP010));
+                } else {
+                    assertFalse(mCodecInfo.getName()
+                                    + " supports HDR profile but does not support "
+                                    + "COLOR_FormatYUVP010",
+                            IntStream.of(caps.colorFormats)
+                                    .noneMatch(x -> x == COLOR_FormatYUVP010));
+                }
+            }
         }
 
         // COLOR_FormatSurface support is an existing requirement, but we did not
@@ -190,41 +219,6 @@
         }
     }
 
-    /** For devices launching with Android T or higher, if a codec supports an HDR profile and
-     * device supports HDR display, it must support COLOR_FormatYUVP010 as a video decoder output
-     * format. For TVs, this requirement is optional.
-     */
-    @CddTest(requirements = "5.12/C-6-5")
-    @Test
-    public void testP010SupportForHDRDisplay() {
-        Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
-        MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType);
-        int[] HdrProfileArray = PROFILE_HDR_MAP.get(mMediaType);
-        if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T
-                && HdrProfileArray != null && DISPLAY_HDR_TYPES.length > 0) {
-            for (CodecProfileLevel pl : caps.profileLevels) {
-                if (IntStream.of(HdrProfileArray).anyMatch(x -> x == pl.profile)) {
-                    if (MediaUtils.isTv()) {
-                        // Some TV devices support HDR10 display with VO instead of GPU. In this
-                        // case, skip checking P010 on TV devices.
-                        Assume.assumeFalse(mCodecInfo.getName() + " supports HDR profile "
-                                        + pl.profile + ","
-                                        + " but does not support COLOR_FormatYUVP010."
-                                        + " Skip checking on TV device",
-                                IntStream.of(caps.colorFormats)
-                                        .noneMatch(x -> x == COLOR_FormatYUVP010));
-                    } else {
-                        assertFalse(mCodecInfo.getName() + " supports HDR profile "
-                                        + pl.profile + "," +
-                                        " but does not support COLOR_FormatYUVP010",
-                                IntStream.of(caps.colorFormats)
-                                        .noneMatch(x -> x == COLOR_FormatYUVP010));
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * For all the available encoders on the device, the test checks if their encoding
      * capabilities are in sync with the device's decoding capabilities.
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index 9a6b350..1405ed3 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -309,6 +309,10 @@
                 new Pair<>(new int[]{HEVCProfileMain}, HEVCMainTierLevel3));
         PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_VP9,
                 new Pair<>(new int[]{VP9Profile0}, VP9Level3));
+        if (IS_AT_LEAST_U) {
+            PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_AV1,
+                    new Pair<>(new int[]{AV1ProfileMain8, AV1ProfileMain10}, -1));
+        }
     }
 
     void checkIfTrackFormatIsOk(MediaFormat trackFormat) {
@@ -362,7 +366,7 @@
      * Check description of class {@link EncoderProfileLevelTest}
      */
     @CddTest(requirements = {"2.2.2/5.1/H-0-3", "2.2.2/5.1/H-0-4", "2.2.2/5.1/H-0-5", "5/C-0-3",
-            "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1"})
+            "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1", "5.2.6/C-1-1"})
     @ApiTest(apis = {"android.media.MediaFormat#KEY_PROFILE",
             "android.media.MediaFormat#KEY_AAC_PROFILE",
             "android.media.MediaFormat#KEY_LEVEL"})
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 1ec8981..335099c 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -18,10 +18,13 @@
 
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ANY;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW_RECOMMENDED;
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_SHOULD;
 
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
 import android.mediav2.common.cts.CodecEncoderTestBase;
@@ -39,7 +42,6 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -58,100 +60,184 @@
  */
 @RunWith(Parameterized.class)
 public class VideoEncoderTest extends CodecEncoderTestBase {
+    private final SupportClass mSupportRequirements;
+
     public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
-            @SuppressWarnings("unused") String testLabel, String allTestParams) {
+            SupportClass supportRequirements, @SuppressWarnings("unused") String testLabel,
+            String allTestParams) {
         super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
+        mSupportRequirements = supportRequirements;
     }
 
     private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
-            int width, int height, int colorFormat, int maxBFrames) {
+            int width, int height, int frameRate, int colorFormat, int maxBFrames) {
         return new EncoderConfigParams.Builder(mediaType)
                 .setBitRate(bitRate)
                 .setWidth(width)
                 .setHeight(height)
+                .setFrameRate(frameRate)
                 .setColorFormat(colorFormat)
                 .setMaxBFrames(maxBFrames)
                 .build();
     }
 
-    private static List<Object[]> flattenParams(List<Object[]> params) {
+    private static List<Object[]> prepareTestArgs(List<Object[]> args) {
         List<Object[]> argsList = new ArrayList<>();
-        for (Object[] param : params) {
-            String mediaType = (String) param[0];
-            int[] bitRates = (int[]) param[1];
-            int[] widths = (int[]) param[2];
-            int[] heights = (int[]) param[3];
+        for (Object[] arg : args) {
+            String mediaType = (String) arg[0];
+            int bitRate = (int) arg[1];
+            int width = (int) arg[2];
+            int height = (int) arg[3];
+            int frameRate = (int) arg[4];
+            int colorFormat = (int) arg[5];
             int[] maxBFrames = {0, 2};
-            int colorFormat = (int) param[4];
-            for (int br : bitRates) {
-                for (int wd : widths) {
-                    for (int ht : heights) {
-                        for (int maxBframe : maxBFrames) {
-                            Object[] testArgs = new Object[3];
-                            if (maxBframe != 0) {
-                                if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
-                                        && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
-                                    continue;
-                                }
-                            }
-                            testArgs[0] = param[0];
-                            testArgs[1] = getVideoEncoderCfgParams(mediaType, br, wd, ht,
-                                    colorFormat, maxBframe);
-                            testArgs[2] = String.format("%dkbps_%dx%d_%s_%d-bframes", br / 1000, wd,
-                                    ht, colorFormatToString(colorFormat, -1), maxBframe);
-                            argsList.add(testArgs);
-                        }
+            for (int maxBframe : maxBFrames) {
+                Object[] testArgs = new Object[4];
+                if (maxBframe != 0) {
+                    if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+                            && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+                        continue;
                     }
                 }
+                testArgs[0] = arg[0];
+                testArgs[1] = getVideoEncoderCfgParams(mediaType, bitRate, width, height, frameRate,
+                        colorFormat, maxBframe);
+                testArgs[2] = arg[6];
+                testArgs[3] = String.format("%dkbps_%dx%d_%s_%d-bframes", bitRate / 1000, width,
+                        height, colorFormatToString(colorFormat, -1), maxBframe);
+                argsList.add(testArgs);
             }
         }
         return argsList;
     }
 
-    @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
+    private static SupportClass getSupportRequirementsDynamic(String mediaType, int width,
+            int height) {
+        ArrayList<MediaFormat> formats = new ArrayList<>();
+        formats.add(MediaFormat.createVideoFormat(mediaType, width, height));
+        return selectCodecs(mediaType, formats, null, true).size() != 0 ? CODEC_ANY : CODEC_SHOULD;
+    }
+
+    @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = false;
         final boolean needVideo = true;
         List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
-                // mediaType, arrays of bit-rates, width, height, color format
-                {MediaFormat.MIMETYPE_VIDEO_H263, new int[]{32000, 64000}, new int[]{176},
-                        new int[]{144}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, new int[]{32000, 64000}, new int[]{176},
-                        new int[]{144}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_VP8, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, COLOR_FormatYUV420Flexible},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, COLOR_FormatYUV420Flexible},
+                // mediaType, width, height, bit-rate, frame-rate, color format, support class
+                {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_OPTIONAL},
+                {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+                        CODEC_OPTIONAL},
+
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30,
+                        COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+                        MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720)},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
+                        COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+                        MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080)},
+
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 800000, 320, 180, 30, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 2000000, 640, 360, 30, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 4000000, 1280, 720, 30,
+                        COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+                        MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720)},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 10000000, 1920, 1080, 30,
+                        COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+                        MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080)},
+
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUV420Flexible,
+                        CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUV420Flexible,
+                        CODEC_HW_RECOMMENDED},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_ANY},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW},
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW},
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_HW},
+                {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
+                        COLOR_FormatYUV420Flexible, CODEC_SHOULD},
         }));
         // P010 support was added in Android T, hence limit the following tests to Android T and
         // above
         if (IS_AT_LEAST_T) {
             defArgsList.addAll(Arrays.asList(new Object[][]{
-                    {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, COLOR_FormatYUVP010},
-                    {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, COLOR_FormatYUVP010},
-                    {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, COLOR_FormatYUVP010},
-                    {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, COLOR_FormatYUVP010},
+                    {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
+                            COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+                    {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
+                            COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+                    {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
+                            CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
+                            COLOR_FormatYUVP010, CODEC_OPTIONAL},
+                    {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
+                            COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+                    {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30, COLOR_FormatYUVP010,
+                            CODEC_HW},
+                    {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30, COLOR_FormatYUVP010,
+                            CODEC_HW},
+                    {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
+                            COLOR_FormatYUVP010, CODEC_HW},
+                    {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
+                            COLOR_FormatYUVP010, CODEC_SHOULD},
             }));
         }
-        List<Object[]> argsList = flattenParams(defArgsList);
+        List<Object[]> argsList = prepareTestArgs(defArgsList);
         return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
     }
 
     /**
      * Check description of class {@link VideoEncoderTest}
      */
-    @CddTest(requirements = {"5.1.7/C-1-2", "5.12/C-6-5"})
+    @CddTest(requirements = {"5.2.1/C-1-1", "5.2.2/C-1-2", "5.2.2/C-2-1", "5.2.3/C-1-1",
+            "5.2.3/C-1-2", "5.2.3/C-2-1", "5.2.4/C-1-1", "5.2.6/C-2-1"})
     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
             "MediaCodecInfo.CodecCapabilities#COLOR_FormatYUVP010"})
     @LargeTest
@@ -164,11 +250,11 @@
             Assume.assumeTrue(mCodecName + " doesn't support " + colorFormatToString(
                             mEncCfgParams[0].mColorFormat, mEncCfgParams[0].mInputBitDepth),
                     hasSupportForColorFormat(mCodecName, mMediaType,
-                                             mEncCfgParams[0].mColorFormat));
+                            mEncCfgParams[0].mColorFormat));
         }
         ArrayList<MediaFormat> formats = new ArrayList<>();
         formats.add(mEncCfgParams[0].getFormat());
-        checkFormatSupport(mCodecName, mMediaType, true, formats, null, CODEC_OPTIONAL);
+        checkFormatSupport(mCodecName, mMediaType, true, formats, null, mSupportRequirements);
 
         // encode
         RawResource res = EncoderInput.getRawResource(mEncCfgParams[0]);
@@ -181,16 +267,10 @@
         }
         encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, muxOutput);
 
-        // cleanup tmp files
+        // validate output
         if (muxOutput) {
-            // validate output
             validateEncodedPSNR(res, mMediaType, mMuxedOutputFile, true, mIsLoopBack,
                     ACCEPTABLE_WIRELESS_TX_QUALITY);
-
-            File tmp = new File(mMuxedOutputFile);
-            if (tmp.exists()) {
-                assertTrue("unable to delete tmp file" + mMuxedOutputFile, tmp.delete());
-            }
         }
     }
 }
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
index 2a85818..04971d6 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
@@ -41,6 +41,8 @@
 import android.app.WallpaperManager
 import android.app.WallpaperManager.FLAG_SYSTEM
 import android.bluetooth.BluetoothManager
+import android.bluetooth.cts.BTAdapterUtils.disableAdapter as disableBTAdapter
+import android.bluetooth.cts.BTAdapterUtils.enableAdapter as enableBTAdapter
 import android.bluetooth.le.ScanCallback
 import android.content.BroadcastReceiver
 import android.content.ComponentName
@@ -54,6 +56,7 @@
 import android.content.pm.PackageManager.FEATURE_BLUETOOTH
 import android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE
 import android.content.pm.PackageManager.FEATURE_TELEPHONY
+import android.content.pm.PackageManager.FEATURE_WIFI
 import android.content.pm.PackageManager.GET_ATTRIBUTIONS
 import android.hardware.camera2.CameraCaptureSession
 import android.hardware.camera2.CameraCharacteristics
@@ -83,6 +86,10 @@
 import android.util.Size
 import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.Executor
+import java.util.concurrent.TimeUnit.MILLISECONDS
+import java.util.concurrent.TimeoutException
 import org.junit.After
 import org.junit.Assert.fail
 import org.junit.Assume.assumeNoException
@@ -90,12 +97,6 @@
 import org.junit.Before
 import org.junit.Ignore
 import org.junit.Test
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.Executor
-import java.util.concurrent.TimeUnit.MILLISECONDS
-import java.util.concurrent.TimeoutException
-import android.bluetooth.cts.BTAdapterUtils.disableAdapter as disableBTAdapter
-import android.bluetooth.cts.BTAdapterUtils.enableAdapter as enableBTAdapter
 
 private const val TEST_SERVICE_PKG = "android.app.appops.cts.appthatusesappops"
 private const val TIMEOUT_MILLIS = 10000L
@@ -442,6 +443,9 @@
      */
     @Test
     fun getWifiScanResults() {
+        assumeTrue("Device does not support WiFi feature",
+                context.packageManager.hasSystemFeature(FEATURE_WIFI))
+
         val wifiManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
             .getSystemService(WifiManager::class.java)
 
diff --git a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
index 9021f8e..843f490 100644
--- a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
+++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
@@ -25,6 +25,7 @@
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
+import android.graphics.Point
 import android.os.Handler
 import android.os.Looper
 import android.os.ParcelFileDescriptor
@@ -235,7 +236,12 @@
         waitFindObject(uiAutomation, By.text("Open")).click()
     } else {
         runShellCommandOrThrow(CMD_EXPAND_NOTIFICATIONS)
-        waitFindNotification(notifSelector, NOTIF_FIND_TIMEOUT).click()
+        val notification = waitFindNotification(notifSelector, NOTIF_FIND_TIMEOUT)
+        if (FeatureUtil.isAutomotive()) {
+            notification.click(Point(0, 0))
+        } else {
+            notification.click()
+        }
     }
 }
 
diff --git a/tests/tests/identity/src/android/security/identity/cts/TestUtil.java b/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
index 882439a..b3bf16e 100644
--- a/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
+++ b/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
@@ -150,4 +150,11 @@
         }
         return false;
     }
+
+    // Returns true if the device supports secure lock screen.
+    static boolean isLockScreenSupported() {
+        Context appContext = InstrumentationRegistry.getTargetContext();
+        PackageManager pm = appContext.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
+    }
 }
diff --git a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
index e4bd81f..1656190 100644
--- a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
@@ -184,8 +184,9 @@
 
     @Test
     public void testUserAuth() throws Exception {
-        String alias = "authbound";
+        assumeTrue("Device doesn't support lock screen", TestUtil.isLockScreenSupported());
 
+        String alias = "authbound";
         try (DeviceLockSession dl = new DeviceLockSession()) {
             Context appContext = InstrumentationRegistry.getTargetContext();
             KeyguardManager keyguardManager = (KeyguardManager)appContext
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index bf2e941..fa7a2d8 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -40,6 +40,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.bedstead.nene.annotations.Nullable;
+import com.android.compatibility.common.util.ApiTest;
 
 import org.junit.After;
 import org.junit.Before;
@@ -2807,6 +2808,7 @@
      * Create large number of Keystore entries with long aliases and try to list aliases of all the
      * entries in the keystore.
      */
+    @ApiTest(apis = {"java.security.KeyStore#aliases"})
     @Test
     public void testKeyStore_LargeNumberOfLongAliases() throws Exception {
         final int maxNumberOfKeys = 100;
@@ -2818,6 +2820,7 @@
      * Create limited number of Keystore entries with long aliases and try to list aliases of all
      * the entries in the keystore. Test should successfully list all the Keystore entries aliases.
      */
+    @ApiTest(apis = {"java.security.KeyStore#aliases"})
     @Test
     public void testKeyStore_LimitedNumberOfLongAliasesSuccess() throws Exception {
         final int maxNumberOfKeys = 10;
@@ -2829,6 +2832,7 @@
      * all the entries in the keystore. Test should successfully list all the Keystore entries
      * aliases.
      */
+    @ApiTest(apis = {"java.security.KeyStore#aliases"})
     @Test
     public void testKeyStore_LargeNumberShortAliasesSuccess() throws Exception {
         final int maxNumberOfKeys = 2500;
diff --git a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
index a703ce2..26254b5 100644
--- a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
@@ -458,11 +458,7 @@
                         }
                         String expectedSecondImei = null;
                         if ((devIdOpt & ID_TYPE_IMEI) != 0) {
-                            // TODO(b/262255219): Remove this condition when StrongBox supports 2nd
-                            // IMEI attestation.
-                            if (!useStrongBox) {
-                                expectedSecondImei = secondImei;
-                            }
+                            expectedSecondImei = secondImei;
                         }
                         validateDeviceIdAttestationData(attestation, expectedSerial,
                                 expectedImei, expectedMeid, expectedSecondImei);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
index a24638f..b584643 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
@@ -42,6 +42,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -270,6 +271,15 @@
         mUseHighBitDepth = useHighBitDepth;
     }
 
+    @ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+            "android.opengl.GLES20#glReadPixels",
+            "android.opengl.GLES30#glReadPixels",
+            "android.media.format.MediaFormat#KEY_ALLOW_FRAME_DROP",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_Format32bitABGR2101010",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testVideoEdit() throws Throwable {
         VideoEditWrapper.runTest(this);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
index 79b5eac..894d4b1 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
@@ -44,6 +44,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -1268,6 +1269,11 @@
      * a series of byte[] buffers and decoded into ByteBuffers.  The output is checked for
      * validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar"})
     @Test
     public void testEncodeDecodeVideoFromBufferToBuffer() throws Exception {
         encodeDecodeVideoFromBuffer(false);
@@ -1285,6 +1291,16 @@
      * the test thread, so we have to hand control off to a new thread for the duration of
      * the test.
      */
+    @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromBufferToSurface() throws Throwable {
         BufferToSurfaceWrapper.runTest(this);
@@ -1294,11 +1310,22 @@
      * Tests streaming of AVC through the encoder and decoder.  Data is provided through
      * a Surface and decoded onto a Surface.  The output is checked for validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodec#createInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToSurface() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, false, false);
     }
-
+    @ApiTest(apis = {"AMediaCodec_createInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToSurfaceNdk() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
@@ -1308,11 +1335,25 @@
      * Tests streaming of video through the encoder and decoder.  Data is provided through
      * a PersistentSurface and decoded onto a Surface.  The output is checked for validity.
      */
+    @ApiTest(apis = {"android.media.MediaCodec#createPersistentInputSurface",
+            "android.media.MediaCodec#setInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToPersistentSurface() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, true, false);
     }
 
+    @ApiTest(apis = {"AMediaCodec_createPersistentInputSurface",
+            "AMediaCodec_setInputSurface",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeDecodeVideoFromSurfaceToPersistentSurfaceNdk() throws Throwable {
         SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
old mode 100755
new mode 100644
index ca08397..fa4e2ac
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -48,6 +48,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Before;
@@ -189,6 +190,13 @@
      *
      * @throws Exception
      */
+    @ApiTest(apis = {"AMediaCodec_createInputSurface",
+            "android.hardware.display.DisplayManager#createVirtualDisplay",
+            "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+            "android.opengl.GLES20#glReadPixels",
+            "android.media.MediaFormat#KEY_COLOR_RANGE",
+            "android.media.MediaFormat#KEY_COLOR_STANDARD",
+            "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
     @Test
     public void testEncodeVirtualDisplay() throws Throwable {
         if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
index 67c3ce8..1225822 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -41,7 +41,7 @@
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.Preconditions;
 
 import org.junit.After;
@@ -69,6 +69,30 @@
  * <p>It also tests the way the codec config buffers need to be passed from the MediaCodec to the
  * MediaMuxer.
  */
+@ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+        "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+        "android.media.MediaFormat#KEY_BIT_RATE",
+        "android.media.MediaFormat#KEY_COLOR_FORMAT",
+        "android.media.MediaFormat#KEY_FRAME_RATE",
+        "android.media.MediaFormat#KEY_I_FRAME_INTERVAL",
+        "android.media.MediaFormat#KEY_SAMPLE_RATE",
+        "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+        "android.media.MediaFormat#KEY_PROFILE",
+        "android.media.MediaFormat#KEY_AAC_PROFILE",
+        "android.media.MediaExtractor#setDataSource",
+        "android.media.MediaExtractor#getTrackCount",
+        "android.media.MediaExtractor#getTrackFormat",
+        "android.media.MediaExtractor#selectTrack",
+        "android.media.MediaExtractor#readSampleData",
+        "android.media.MediaExtractor#getSampleTime",
+        "android.media.MediaExtractor#getSampleFlags",
+        "android.media.MediaExtractor#advance",
+        "android.media.MediaExtractor#release",
+        "android.media.MediaMuxer#start",
+        "android.media.MediaMuxer#stop",
+        "android.media.MediaMuxer#addTrack",
+        "android.media.MediaMuxer#writeSampleData",
+        "android.media.MediaMuxer#release"})
 @TargetApi(18)
 @AppModeFull(reason = "Instant apps cannot access the SD card")
 @RunWith(AndroidJUnit4.class)
@@ -145,7 +169,6 @@
         super.tearDown();
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxQCIF() throws Throwable {
         if(!setSize(176, 144)) return;
@@ -155,7 +178,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxQVGA() throws Throwable {
         if(!setSize(320, 240)) return;
@@ -165,7 +187,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMux720p() throws Throwable {
         if(!setSize(1280, 720)) return;
@@ -175,7 +196,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMux2160pHevc() throws Throwable {
         if(!setSize(3840, 2160)) return;
@@ -185,7 +205,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.1.1", "5.1.2"})
     @Test
     public void testExtractDecodeEditEncodeMuxAudio() throws Throwable {
         if(!setSize(1280, 720)) return;
@@ -195,7 +214,6 @@
         TestWrapper.runTest(this);
     }
 
-    @CddTest(requirements = {"5.1.1", "5.1.2", "5.2", "5.3"})
     @Test
     public void testExtractDecodeEditEncodeMuxAudioVideo() throws Throwable {
         if(!setSize(1280, 720)) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
index 29a14a0..5822063 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
@@ -41,6 +41,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.NonMainlineTest;
 import com.android.compatibility.common.util.Preconditions;
@@ -92,6 +93,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testDecodeShortVideo() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -112,6 +114,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testDecodeShortAudio() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -132,6 +135,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testEncodeShortAudio() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -145,6 +149,7 @@
     @Presubmit
     @SmallTest
     @RequiresDevice
+    @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
     @Test
     public void testEncodeShortVideo() throws InterruptedException {
         if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
index bb769ca..b94f2de8 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
@@ -45,6 +45,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiTest;
+
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -80,6 +82,7 @@
         public final int uid;
     }
 
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testCreateCodecForAnotherProcessWithoutPermissionsThrows() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -102,6 +105,7 @@
 
     // A process with lower priority (e.g. background app) should not be able to reclaim
     // MediaCodec resources from a process with higher priority (e.g. foreground app).
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testLowerPriorityProcessFailsToReclaimResources() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -188,6 +192,7 @@
 
     // A process with higher priority (e.g. foreground app) should be able to reclaim
     // MediaCodec resources from a process with lower priority (e.g. background app).
+    @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
     @Test
     public void testHigherPriorityProcessReclaimsResources() throws Exception {
         CodecInfo codecInfo = getFirstVideoHardwareDecoder();
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
index 3173465..52d01b2 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
@@ -68,6 +68,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.Preconditions;
 
@@ -142,6 +143,18 @@
      * A selective test to ensure proper exceptions are thrown from MediaCodec
      * methods when called in incorrect operational states.
      */
+    @ApiTest(apis = {"MediaCodec#createByCodecName", "MediaCodec#createDecoderByType",
+            "MediaCodec#createEncoderByType", "MediaCodec#start", "MediaCodec#flush",
+            "MediaCodec#configure", "MediaCodec#dequeueInputBuffer",
+            "MediaCodec#dequeueOutputBuffer", "MediaCodec#createInputSurface",
+            "MediaCodec#getInputBuffers", "MediaCodec#getQueueRequest",
+            "MediaCodec#getOutputFrame", "MediaCodec#stop", "MediaCodec#release",
+            "MediaCodec#getCodecInfo", "MediaCodec#getSupportedVendorParameters",
+            "MediaCodec#getParameterDescriptor",
+            "MediaCodec#subscribeToVendorParameters",
+            "MediaCodec#unsubscribeFromVendorParameters",
+            "MediaCodec#getInputBuffer", "MediaCodec#getOutputBuffer",
+            "MediaCodec#setCallback", "MediaCodec#getName"})
     @Test
     public void testException() throws Exception {
         boolean tested = false;
@@ -245,15 +258,6 @@
             fail("flush should not return MediaCodec.CodecException on wrong state");
         } catch (IllegalStateException e) { // expected
         }
-        try {
-            codec.setParameters(new Bundle());
-            fail("setParameters should not work if not yet configured/initialized");
-        } catch (MediaCodec.CodecException e) {
-            logMediaCodecException(e);
-            fail("setParameters should not return MediaCodec.CodecException if not yet "
-                    + "configured/initialized");
-        } catch (IllegalStateException e) { // expected
-        }
 
         MediaCodecInfo codecInfo = codec.getCodecInfo(); // obtaining the codec info now is fine.
         try {
@@ -553,6 +557,7 @@
      * <br> calling createInputSurface() after start() throws exception
      * <br> calling createInputSurface() with a non-Surface color format is not required to throw exception
      */
+    @ApiTest(apis = "MediaCodec#createInputSurface")
     @Test
     public void testCreateInputSurfaceErrors() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -604,6 +609,7 @@
      * <br> signaling EOS twice throws exception
      * <br> submitting a frame after EOS throws exception [TODO]
      */
+    @ApiTest(apis = "MediaCodec#signalEndOfInputStream")
     @Test
     public void testSignalSurfaceEOS() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -662,6 +668,7 @@
      * Tests:
      * <br> stopping with buffers in flight doesn't crash or hang
      */
+    @ApiTest(apis = "MediaCodec#stop")
     @Test
     public void testAbruptStop() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -718,6 +725,7 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#flush", "MediaCodec#release"})
     @Test
     public void testReleaseAfterFlush() throws IOException, InterruptedException {
         String mimes[] = new String[] { MIME_TYPE, MIME_TYPE_AUDIO};
@@ -781,11 +789,13 @@
         callbackThread.join();
     }
 
+    @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#flush", "MediaCodec#reset"})
     @Test
     public void testAsyncFlushAndReset() throws Exception, InterruptedException {
         testAsyncReset(false /* testStop */);
     }
 
+    @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#stop", "MediaCodec#reset"})
     @Test
     public void testAsyncStopAndReset() throws Exception, InterruptedException {
         testAsyncReset(true /* testStop */);
@@ -1116,6 +1126,7 @@
      * Tests:
      * <br> dequeueInputBuffer() fails when encoder configured with an input Surface
      */
+    @ApiTest(apis = {"MediaCodec#dequeueInputBuffer", "MediaCodec#getMetrics"})
     @Test
     public void testDequeueSurface() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -1175,6 +1186,8 @@
      * <br> configure() encoder with Surface, re-configure() without Surface works
      * <br> sending EOS with signalEndOfInputStream on non-Surface encoder fails
      */
+    @ApiTest(apis = {"MediaCodec#configure", "MediaCodec#signalEndOfInputStream",
+            "MediaCodec#getMetrics"})
     @Test
     public void testReconfigureWithoutSurface() {
         if (!supportsCodec(MIME_TYPE, true)) {
@@ -1244,6 +1257,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#flush")
     @Test
     public void testDecodeAfterFlush() throws InterruptedException {
         testDecodeAfterFlush(true /* audio */);
@@ -1425,6 +1439,7 @@
      * Tests whether decoding a short group-of-pictures succeeds. The test queues a few video frames
      * then signals end-of-stream. The test fails if the decoder doesn't output the queued frames.
      */
+    @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
     @Test
     public void testDecodeShortInput() throws InterruptedException {
         // Input buffers from this input video are queued up to and including the video frame with
@@ -1536,6 +1551,10 @@
     /**
      * Tests creating two decoders for {@link #MIME_TYPE_AUDIO} at the same time.
      */
+    @ApiTest(apis = {"MediaCodec#createDecoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
     @Test
     public void testCreateTwoAudioDecoders() {
         final MediaFormat format = MediaFormat.createAudioFormat(
@@ -1583,6 +1602,10 @@
     /**
      * Tests creating an encoder and decoder for {@link #MIME_TYPE_AUDIO} at the same time.
      */
+    @ApiTest(apis = {"MediaCodec#createDecoderByType", "MediaCodec#createEncoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
     @Test
     public void testCreateAudioDecoderAndEncoder() {
         if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1641,6 +1664,12 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#createEncoderByType",
+            "android.media.MediaFormat#KEY_MIME",
+            "android.media.MediaFormat#KEY_SAMPLE_RATE",
+            "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+            "android.media.MediaFormat#KEY_WIDTH",
+            "android.media.MediaFormat#KEY_HEIGHT"})
     @Test
     public void testConcurrentAudioVideoEncodings() throws InterruptedException {
         if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1689,6 +1718,7 @@
         public int mBitRate;
     }
 
+    @ApiTest(apis = {"MediaCodec#CryptoInfo", "MediaCodec#CryptoInfo#Pattern"})
     @Test
     public void testCryptoInfoPattern() {
         CryptoInfo info = new CryptoInfo();
@@ -1989,6 +2019,7 @@
     /**
      * Tests MediaCodec.CryptoException
      */
+    @ApiTest(apis = "MediaCodec#CryptoException")
     @Test
     public void testCryptoException() {
         int errorCode = CryptoException.ERROR_KEY_EXPIRED;
@@ -2007,6 +2038,8 @@
      *
      * As of Q, any codec of type "audio/raw" must support PCM encoding float.
      */
+    @ApiTest(apis = {"android.media.AudioFormat#ENCODING_PCM_16BIT",
+            "android.media.AudioFormat#ENCODING_PCM_FLOAT"})
     @MediumTest
     @Test
     public void testPCMEncoding() throws Exception {
@@ -2132,6 +2165,7 @@
         return actualEncoding;
     }
 
+    @ApiTest(apis = "android.media.AudioFormat#KEY_FLAC_COMPRESSION_LEVEL")
     @SmallTest
     @Test
     public void testFlacIdentity() throws Exception {
@@ -2185,6 +2219,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#release")
     @Test
     public void testAsyncRelease() throws Exception {
         OutputSurface outputSurface = new OutputSurface(1, 1);
@@ -2272,6 +2307,7 @@
         }
     }
 
+    @ApiTest(apis = "MediaCodec#setAudioPresentation")
     @Test
     public void testSetAudioPresentation() throws Exception {
         MediaFormat format = MediaFormat.createAudioFormat(
@@ -2287,6 +2323,7 @@
                 (new AudioPresentation.Builder(42 /* presentationId */)).build());
     }
 
+    @ApiTest(apis = "android.media.MediaFormat#KEY_PREPEND_HEADER_TO_SYNC_FRAMES")
     @Test
     public void testPrependHeadersToSyncFrames() throws IOException {
         MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -2361,6 +2398,7 @@
      * codec is flushed after the first buffer is queued, so this test walks
      * through the scenario.
      */
+    @ApiTest(apis = "MediaCodec#flush")
     @Test
     public void testFlushAfterFirstBuffer() throws Exception {
         if (MediaUtils.check(mIsAtLeastR, "test needs Android 11")) {
@@ -2458,6 +2496,10 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodec#getSupportedVendorParameters",
+            "MediaCodec#getParameterDescriptor",
+            "MediaCodec#subscribeToVendorParameters",
+            "MediaCodec#unsubscribeFromVendorParameters"})
     @Test
     public void testVendorParameters() {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) {
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 ac0dd0f..6c67812 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
@@ -26,6 +26,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Assume;
@@ -625,41 +626,65 @@
         }
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testBasic() throws Exception {
         internalTestBasic(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testAsyncEncode() throws Exception {
         internalTestAsyncEncoding(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
     @Test
     public void testSyncFrame() throws Exception {
         internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, false);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
     @Test
     public void testSyncFrameNdk() throws Exception {
         internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, true);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
     @Test
     public void testDynamicBitrateChange() throws Exception {
         internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, false);
     }
 
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
     @Test
     public void testDynamicBitrateChangeNdk() throws Exception {
         internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, true);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testEncoderQuality() throws Exception {
         internalTestEncoderQuality(mCodecName, mCodecMimeType, mBitRateMode);
     }
 
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_COLOR_FORMAT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
     @Test
     public void testParallelEncodingAndDecoding() throws Exception {
         Assume.assumeTrue("Parallel Encode Decode test is run only for VBR mode",
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
index 78021f4..fb61f78 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.NonMainlineTest;
 
 import org.junit.Test;
@@ -96,6 +97,7 @@
         return testParams;
     }
 
+    @ApiTest(apis = "android.media.MediaFormat#KEY_ROTATION")
     @Test
     public void testRendering800x480Rotated() throws Throwable {
         if (mImpl.isConcurrentEncodingDecodingSupported(
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
index 4979f76..4239679 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
@@ -26,6 +26,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Assume;
@@ -195,6 +196,9 @@
         }
     }
 
+    @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#FEATURE_EncodingStatistics",
+            "android.media.MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL",
+            "android.media.MediaFormat#KEY_VIDEO_QP_AVERAGE"})
     @Test
     public void testEncodingStatisticsAvgQp() throws Exception {
        testEncStatRateAvgQp(mCodecName, mCodecMimeType, mBitRateMode);
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
index 6f9421d..cbfb26d 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
@@ -23,7 +23,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
@@ -36,6 +35,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.Preconditions;
 
@@ -197,11 +197,13 @@
         mFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
     }
 
+    // "5.1.3" is covered partially. For instance aac is not tested for 5.0 and 5.1, Opus is not
+    // tested for different sample rates.
+    // TODO (b/272014629): Update test accordingly
+    @CddTest(requirements = "5.1.3")
     @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
     public void testEncoders() throws FileNotFoundException {
         setUpFormat();
-        assumeTrue("no encoders found for " + mFormat.toString(),
-                MediaUtils.supports(mEncoderName, mFormat));
         assertEquals(mMime, mFormat.getString(MediaFormat.KEY_MIME));
         testEncoder(mEncoderName, mFormat);
     }
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
index 95ceec6..dd0bf6e 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
@@ -43,6 +43,7 @@
 import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
+import com.android.compatibility.common.util.ApiTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.After;
@@ -114,13 +115,14 @@
     }
 
     /*
-     * Test KEY_MAX_PTS_GAP_TO_ENCODER
+     * Test KEY_MAX_PTS_GAP_TO_ENCODER when positive
      *
      * This key is supposed to cap the gap between any two frames fed to the encoder,
      * and restore the output pts back to the original. Since the pts is not supposed
      * to be modified, we can't really verify that the "capping" actually took place.
      * However, we can at least verify that the pts is preserved.
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
     @Test
     public void testMaxPtsGap() throws Throwable {
         long[] inputPts = {1000000, 2000000, 3000000, 4000000};
@@ -131,8 +133,10 @@
     }
 
     /*
-     * Test that by default backward-going frames get dropped.
+     * Test pts behavior if KEY_MAX_PTS_GAP_TO_ENCODER is unspecified.
+     * (Tests that by default backward-going frames get dropped)
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
     @Test
     public void testBackwardFrameDroppedWithoutFixedPtsGap() throws Throwable {
         long[] inputPts = {33333, 66667, 66000, 100000};
@@ -141,11 +145,12 @@
     }
 
     /*
-     * Test KEY_MAX_PTS_GAP_TO_ENCODER
+     * Test KEY_MAX_PTS_GAP_TO_ENCODER when negative
      *
-     * Test that when fixed pts gap is used, backward-going frames are accepted
+     * Test that when negative pts gap is used, backward-going frames are accepted
      * and the pts is preserved.
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
     @Test
     public void testBackwardFramePreservedWithFixedPtsGap() throws Throwable {
         long[] inputPts = {33333, 66667, 66000, 100000};
@@ -161,6 +166,7 @@
      * Input frames are timestamped at 60fps, the key is supposed to drop
      * one every other frame to maintain 30fps output.
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_FPS_TO_ENCODER")
     @Test
     public void testMaxFps() throws Throwable {
         long[] inputPts = {16667, 33333, 50000, 66667, 83333};
@@ -178,6 +184,7 @@
      * compress) the output timestamp so that the output fps becomes that specified
      * by  KEY_FRAME_RATE.
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_CAPTURE_RATE")
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
     public void testCaptureFps() throws Throwable {
@@ -213,6 +220,7 @@
      * Test that the frame is repeated at least once if no new frame arrives after
      * the specified amount of time.
      */
+    @ApiTest(apis = "android.media.MediaFormat#KEY_REPEAT_PREVIOUS_FRAME_AFTER")
     @Test
     public void testRepeatPreviousFrameAfter() throws Throwable {
         long[] inputPts = {16667, 33333, -100000, 133333};
@@ -228,6 +236,8 @@
      * Start the encoder with KEY_CREATE_INPUT_SURFACE_SUSPENDED set, then resume
      * by PARAMETER_KEY_SUSPEND. Verify only frames after resume are captured.
      */
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_CREATE_INPUT_SURFACE_SUSPENDED",
+            "android.media.MediaCodec#PARAMETER_KEY_SUSPEND"})
     @Test
     public void testCreateInputSurfaceSuspendedResume() throws Throwable {
         // Using PARAMETER_KEY_SUSPEND (instead of PARAMETER_KEY_SUSPEND +
@@ -256,6 +266,9 @@
      * at specific time using PARAMETER_KEY_SUSPEND + PARAMETER_KEY_SUSPEND_TIME.
      * Verify only frames after the specified time are captured.
      */
+    @ApiTest(apis = {"android.media.MediaFormat#KEY_CREATE_INPUT_SURFACE_SUSPENDED",
+            "android.media.MediaCodec#PARAMETER_KEY_SUSPEND",
+            "android.media.MediaCodec#PARAMETER_KEY_SUSPEND_TIME"})
     @Test
      public void testCreateInputSurfaceSuspendedResumeWithTime() throws Throwable {
          // Unlike using PARAMETER_KEY_SUSPEND alone to resume, using PARAMETER_KEY_SUSPEND
@@ -279,6 +292,7 @@
       * Suspend/resume during capture, and verify that frames during the suspension
       * period are dropped.
       */
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_SUSPEND")
     @Test
     public void testSuspendedResume() throws Throwable {
         // Using PARAMETER_KEY_SUSPEND (instead of PARAMETER_KEY_SUSPEND +
@@ -307,6 +321,8 @@
      * Suspend/resume with specified time during capture, and verify that frames during
      * the suspension period are dropped.
      */
+    @ApiTest(apis = {"android.media.MediaCodec#PARAMETER_KEY_SUSPEND",
+            "android.media.MediaCodec#PARAMETER_KEY_SUSPEND_TIME"})
     @Test
     public void testSuspendedResumeWithTime() throws Throwable {
         // Unlike using PARAMETER_KEY_SUSPEND alone to suspend/resume, requests using
@@ -334,6 +350,7 @@
      * Apply PARAMETER_KEY_OFFSET_TIME during capture, and verify that the pts
      * of frames after the request are adjusted by the offset correctly.
      */
+    @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_OFFSET_TIME")
     @Test
     public void testOffsetTime() throws Throwable {
         long[] inputPts = {33333, 66667, -100000, 100000, 133333};
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
index 93f858e..613f462 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
@@ -22,6 +22,7 @@
 import android.media.MediaFormat;
 import android.platform.test.annotations.AppModeFull;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.MediaUtils;
 
 import org.junit.Test;
@@ -90,6 +91,7 @@
     }
 
     // Tests encoder profiles required by CDD.
+    @CddTest(requirements = {"5.2.2/C-1-2", "5.2.3/C-1-1", "5.2.4/C-SR-1", "5.2.5/C-SR-1"})
     @Test
     public void testEncoderAvailability() {
         MediaFormat format = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index de642ed..bf0c71c 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -50,6 +50,8 @@
 import android.util.Size;
 import android.view.Surface;
 
+import com.android.compatibility.common.util.ApiTest;
+import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.MediaUtils;
 import com.android.compatibility.common.util.Preconditions;
 
@@ -1353,6 +1355,17 @@
         mMode = mode;
     }
 
+    @CddTest(requirements = {"5.1.7/C-3-1"})
+    @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#FEATURE_IntraRefresh",
+            "android.media.MediaFormat#KEY_WIDTH",
+            "android.media.MediaFormat#KEY_HEIGHT",
+            "android.media.MediaFormat#KEY_FRAME_RATE",
+            "android.media.MediaFormat#KEY_BIT_RATE",
+            "android.media.MediaFormat#KEY_I_FRAME_INTERVAL",
+            "android.media.MediaFormat#KEY_INTRA_REFRESH_PERIOD",
+            "android.media.MediaFormat#KEY_MAX_INPUT_SIZE",
+            "MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
+            "MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
     @Test
     public void testEncode() {
         int frameRate = 30;
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
index 2a30898..383e4b4 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
@@ -114,13 +114,6 @@
 
     // Copy the resource to cache.
     private Uri resourceToUri(Context context, int resId, String name) throws IOException {
-        Uri resUri = new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(context.getResources().getResourcePackageName(resId))
-                .appendPath(context.getResources().getResourceTypeName(resId))
-                .appendPath(context.getResources().getResourceEntryName(resId))
-                .build();
-
         Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
                 + mContext.getCacheDir().getAbsolutePath() + "/" + name);
 
diff --git a/tests/tests/permission2/res/raw/wear_android_manifest.xml b/tests/tests/permission2/res/raw/wear_android_manifest.xml
deleted file mode 100644
index 08488bc..0000000
--- a/tests/tests/permission2/res/raw/wear_android_manifest.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2023 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<!-- This file contains permissions which were back ported.
-     These permissions are already present on future platform releases.
-    -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android" coreApp="true" android:sharedUserId="android.uid.system"
-          android:sharedUserLabel="@string/android_system_label">
-
-   <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
-   <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
-   <p>Protection level: dangerous -->
-    <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
-                android:permissionGroup="android.permission-group.UNDEFINED"
-                android:label="@string/permlab_bodySensorsWristTemperature"
-                android:description="@string/permdesc_bodySensorsWristTemperature"
-                android:backgroundPermission="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
-                android:protectionLevel="dangerous" />
-
-    <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
-         If you're requesting this permission, you must also request
-         {@link #BODY_SENSORS_WRIST_TEMPERATURE}. Requesting this permission by itself doesn't
-         give you wrist temperature body sensors access.
-         <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
-         <p>Protection level: dangerous
-
-         <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record allowlists the permission. For more details see
-         {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-    -->
-    <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
-                android:permissionGroup="android.permission-group.UNDEFINED"
-                android:label="@string/permlab_bodySensors_wristTemperature_background"
-                android:description="@string/permdesc_bodySensors_wristTemperature_background"
-                android:protectionLevel="dangerous"
-                android:permissionFlags="hardRestricted" />
-
-</manifest>
\ No newline at end of file
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index ac9c97a..d8ea3f7 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -167,9 +167,6 @@
             }
             declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap);
         }
-        if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
-            expectedPermissions.addAll(loadExpectedPermissions(R.raw.wear_android_manifest));
-        }
 
         for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
             String expectedPermissionName = expectedPermission.name;
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index feaf20e..a1eca49 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -54,7 +54,6 @@
 import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
 import android.Manifest.permission_group.UNDEFINED
 import android.app.AppOpsManager.permissionToOp
-import android.content.pm.PackageManager
 import android.content.pm.PackageManager.GET_PERMISSIONS
 import android.content.pm.PermissionInfo.PROTECTION_DANGEROUS
 import android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP
@@ -162,23 +161,6 @@
         expectedPerms.add(POST_NOTIFICATIONS)
         expectedPerms.add(NEARBY_WIFI_DEVICES)
 
-        // Add runtime permissions added in V (back ported from U) which were _not_ split from a
-        // previously existing runtime permission
-        if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
-            expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE)
-            expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND)
-        }
-
         assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
     }
-
-    companion object {
-        // These permissions are back ported from Android U to tm-wear, hidden in the
-        // "core/res/AndroidManifest.xml" file of /framework/base repo. Added these 2 constants here
-        // because hidden permissions can't be imported like other imported permissions in this file
-        private const val BODY_SENSORS_WRIST_TEMPERATURE =
-                "android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
-        private const val BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND =
-                "android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
-    }
 }
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 0b88e01..7499e0f 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -65,6 +65,7 @@
     @Before
     fun setup() {
         Assume.assumeFalse(isTv)
+        Assume.assumeFalse(isWatch)
         // TODO(b/203784852) Auto will eventually support the blocked sensor banner, but there won't
         // be support in T or below
         Assume.assumeFalse(isAutomotive)
diff --git a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
index acf38c7..a386ff6 100644
--- a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
+++ b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
@@ -55,7 +55,10 @@
     asm volatile("aesenc %%xmm1, %%xmm0" : : : "xmm0");
 }
 #else
-#warning "unknown architecture, assuming AES instructions are available"
+// For unknown architectures, we cannot confirm that AES instructions are
+// unsupported.  So, assume they are supported, i.e. don't raise SIGILL.  This
+// disallows Adiantum until code is explicitly added for the architecture.
+#warning "unknown architecture, assuming Adiantum is not allowed"
 static void executeAESInstruction(void) {}
 #endif
 
@@ -65,8 +68,8 @@
     longjmp(jump_buf, 1);
 }
 
-// This function checks for the presence of AES instructions, e.g. ARMv8 crypto
-// extensions for ARM, or AES-NI for x86.
+// Checks whether Adiantum encryption is allowed.  Adiantum encryption is
+// allowed only when the CPU does *not* support AES instructions.
 //
 // ARM processors don't have a standard way for user processes to determine CPU
 // features.  On Linux it's possible to read the AT_HWCAP and AT_HWCAP2 values
@@ -76,10 +79,10 @@
 //
 // To keep things consistent we use the same approach on x86 to detect AES-NI,
 // though in principle the 'cpuid' instruction could be used there.
-static bool cpuHasAESInstructions(void) {
+static bool isAdiantumEncryptionAllowed(void) {
     struct sigaction act;
     struct sigaction oldact;
-    bool result;
+    bool allowed;
 
     memset(&act, 0, sizeof(act));
     act.sa_handler = handleSIGILL;
@@ -87,17 +90,20 @@
     EXPECT_EQ(0, sigaction(SIGILL, &act, &oldact));
 
     if (setjmp(jump_buf) != 0) {
-        // SIGILL was received when executing the AES instruction.
-        result = false;
+        // Trying to execute an AES instruction raised SIGILL, which shows that
+        // AES instructions are unsupported.  Thus, Adiantum is allowed.
+        allowed = true;
     } else {
         executeAESInstruction();
-        // Successfully executed the AES instruction.
-        result = true;
+        // Either an AES instruction was successfully executed, or the
+        // architecture is unknown.  So, it has *not* been shown that AES
+        // instructions are unsupported.  Thus, Adiantum is *not* allowed.
+        allowed = false;
     }
 
     EXPECT_EQ(0, sigaction(SIGILL, &oldact, NULL));
 
-    return result;
+    return allowed;
 }
 
 // CDD 9.9.3/C-1-5: must use AES-256-XTS or Adiantum contents encryption.
@@ -151,8 +157,7 @@
     }
 
     if (contents_mode == FSCRYPT_MODE_ADIANTUM || filenames_mode == FSCRYPT_MODE_ADIANTUM) {
-        // Adiantum encryption is only allowed if the CPU doesn't have AES instructions.
-        EXPECT_FALSE(cpuHasAESInstructions());
+        EXPECT_TRUE(isAdiantumEncryptionAllowed());
     }
 }
 
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 4bfe8fe..b6ee6ed 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -102,7 +102,7 @@
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_debug));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_release));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata3));
-        // The following keys are not not used by modules on the latest Android release, but it
+        // The following keys are not used by modules on the latest Android release, but it
         // won't negatively affect tests to include their signatures here too.
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata));
         wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata2));
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
index d012eb6..b6bedf0 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
@@ -71,6 +71,9 @@
         List<SubscriptionInfo> allSubscriptions = SystemUtil.runWithShellPermissionIdentity(() ->
                         subscriptionManager.getActiveSubscriptionInfoList(),
                 Manifest.permission.READ_PHONE_STATE);
+        if (allSubscriptions == null) {
+            allSubscriptions = Collections.emptyList();
+        }
         Map<Integer, List<SubscriptionInfo>> subscriptionsByCardId = allSubscriptions.stream()
                 .collect(Collectors.groupingBy(SubscriptionInfo::getCardId));
         for (UiccCardInfo cardInfo : uiccCards) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
index f5a8477..adee163 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
@@ -101,10 +101,11 @@
                 NetworkRegistrationInfo.SERVICE_TYPE_VOICE), nri.getAvailableServices());
     }
 
-     /**
+    /**
      * Basic test to ensure {@link NetworkRegistrationInfo#isSearching()} does not throw any
      * exception.
      */
+    @SuppressWarnings("deprecation")
     @Test
     public void testNetworkRegistrationInfoIsSearching() {
         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
@@ -114,6 +115,18 @@
         assertTrue(nri.isSearching());
     }
 
+    /**
+     * Basic test to ensure {@link NetworkRegistrationInfo#isNetworkSearching()} does not throw any
+     * exception.
+     */
+    @Test
+    public void testNetworkRegistrationInfoIsNetworkSearching() {
+        NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                .setRegistrationState(
+                        NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING)
+                .build();
+        assertTrue(nri.isNetworkSearching());
+    }
 
     @Test
     public void testGetDomain() {
@@ -123,6 +136,7 @@
         assertEquals(NetworkRegistrationInfo.DOMAIN_CS, nri.getDomain());
     }
 
+    @SuppressWarnings("deprecation")
     @Test
     public void testGetRegistrationState() {
         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
@@ -132,6 +146,16 @@
     }
 
     @Test
+    public void testGetNetworkRegistrationState() {
+        NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING)
+                .build();
+        nri.setRoamingType(NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+        assertEquals(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING,
+                nri.getNetworkRegistrationState());
+    }
+
+    @Test
     public void testGetTransportType() {
         NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
                 .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
@@ -175,6 +199,10 @@
         assertEquals(ci, nri.getCellIdentity());
     }
 
+    /**
+     * Test {@link NetworkRegistrationInfo#isRegistered()} to support backward compatibility.
+     */
+    @SuppressWarnings("deprecation")
     @Test
     public void testIsRegistered() {
         final int[] registeredStates = new int[] {NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
@@ -200,14 +228,67 @@
     }
 
     @Test
+    public void testIsNetworkRegistered() {
+        final int[] registeredStates = new int[] {NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING};
+        for (int state : registeredStates) {
+            NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                    .setRegistrationState(state)
+                    .build();
+            assertTrue(nri.isNetworkRegistered());
+        }
+
+        final int[] unregisteredStates = new int[] {
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING,
+                NetworkRegistrationInfo.REGISTRATION_STATE_DENIED,
+                NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN};
+        for (int state : unregisteredStates) {
+            NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                    .setRegistrationState(state)
+                    .build();
+            assertFalse(nri.isNetworkRegistered());
+        }
+    }
+
+    /**
+     * Test {@link NetworkRegistrationInfo#isSearching()} to support backward compatibility.
+     */
+    @SuppressWarnings("deprecation")
+    @Test
     public void testIsSearching() {
         final int[] isSearchingStates = new int[] {
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING};
+        for (int state : isSearchingStates) {
+            NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                    .setRegistrationState(state)
+                    .build();
+            assertTrue(nri.isSearching());
+        }
+
+        final int[] isNotSearchingStates = new int[] {
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+                NetworkRegistrationInfo.REGISTRATION_STATE_DENIED,
+                NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN};
+        for (int state : isNotSearchingStates) {
+            NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                    .setRegistrationState(state)
+                    .build();
+            assertFalse(nri.isSearching());
+        }
+    }
+
+    @Test
+    public void testIsNetworkSearching() {
+        final int[] isSearchingStates = new int[] {
             NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING};
         for (int state : isSearchingStates) {
             NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
                     .setRegistrationState(state)
                     .build();
-            assertTrue(nri.isSearching());
+            assertTrue(nri.isNetworkSearching());
         }
 
         final int[] isNotSearchingStates = new int[] {
@@ -220,7 +301,7 @@
             NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
                     .setRegistrationState(state)
                     .build();
-            assertFalse(nri.isSearching());
+            assertFalse(nri.isNetworkSearching());
         }
     }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
index 43c8be7..148c540 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
@@ -30,10 +30,12 @@
         Parcel p = Parcel.obtain();
         p.writeInt(1);
         p.writeInt(2);
+        p.writeBoolean(false);
 
         p.setDataPosition(0);
         TelephonyDisplayInfo tdi = TelephonyDisplayInfo.CREATOR.createFromParcel(p);
         assertEquals(1, tdi.getNetworkType());
         assertEquals(2, tdi.getOverrideNetworkType());
+        assertEquals(false, tdi.isRoaming());
     }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
index a2fe9d2..955d9da 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
@@ -110,6 +110,10 @@
         Assume.assumeTrue(hasTelephony());
     }
 
+    public static void assumeMessaging() {
+        Assume.assumeTrue(hasSms());
+    }
+
     public static boolean hasTelephony() {
         Context context = ApplicationProvider.getApplicationContext();
         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
index 2d2c140..4831f23 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -62,6 +63,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
index ca1f01a..087bfc5 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -67,6 +68,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
index 89b27ef..3515225 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -72,6 +73,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
index 05e52ea..a09f1d2 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -60,6 +61,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
index f40f4d7..a950d4d 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -68,6 +69,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContentResolver = getInstrumentation().getContext().getContentResolver();
         mSmsTestHelper = new SmsTestHelper();
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
index cbab7ef..739325f 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
@@ -17,6 +17,7 @@
 package android.telephonyprovider.cts;
 
 import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
@@ -62,6 +63,7 @@
     @Before
     public void setupTestEnvironment() {
         assumeTelephony();
+        assumeMessaging();
         cleanup();
         mContext = getInstrumentation().getContext();
         mContentResolver = mContext.getContentResolver();
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
index d70cc2b..e1a2fd0 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
@@ -99,7 +99,7 @@
     public TestNetworkWrapper(
             @NonNull Context context,
             int mtu,
-            boolean isMetered,
+            @NonNull Set<Integer> capabilities,
             @NonNull Set<Integer> subIds,
             @NonNull InetAddress localAddress)
             throws Exception {
@@ -125,7 +125,7 @@
             mConnectivityManager.requestNetwork(nr, vcnNetworkCallback);
 
             final NetworkCapabilities nc =
-                    createNetworkCapabilitiesForIface(iface, isMetered, subIds);
+                    createNetworkCapabilitiesForIface(iface, capabilities, subIds);
             final LinkProperties lp = createLinkPropertiesForIface(iface, mtu);
 
             final VcnNetworkPolicyResult policy = mVcnManager.applyVcnNetworkPolicy(nc, lp);
@@ -150,21 +150,19 @@
     }
 
     private static NetworkCapabilities createNetworkCapabilitiesForIface(
-            @NonNull String iface, boolean isMetered, Set<Integer> subIds) {
+            @NonNull String iface, Set<Integer> capabilities, Set<Integer> subIds) {
         NetworkCapabilities.Builder builder =
                 NetworkCapabilities.Builder.withoutDefaultCapabilities()
                         .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
                         .setNetworkSpecifier(new TestNetworkSpecifier(iface))
                         .setSubscriptionIds(subIds);
-        if (!isMetered) {
-            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+        for (int cap : capabilities) {
+            builder.addCapability(cap);
         }
+
         return builder.build();
     }
 
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 6051a5c..eba8a03 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -19,11 +19,14 @@
 import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
 import static android.ipsec.ike.cts.IkeTunUtils.PortPair;
 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
+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.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -51,6 +54,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
 import android.net.vcn.VcnConfig;
 import android.net.vcn.VcnManager;
 import android.net.vcn.VcnUnderlyingNetworkTemplate;
@@ -77,7 +81,9 @@
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
@@ -364,18 +370,29 @@
     }
 
     private TestNetworkWrapper createTestNetworkWrapper(
-            boolean isMetered, int subId, InetAddress localAddress) throws Exception {
+            int subId, InetAddress localAddress, Set<Integer> capabilities) throws Exception {
         TestNetworkWrapper testNetworkWrapper =
                 new TestNetworkWrapper(
                         mContext,
                         TEST_NETWORK_MTU,
-                        isMetered,
+                        capabilities,
                         Collections.singleton(subId),
                         localAddress);
         assertNotNull("No test network found", testNetworkWrapper.tunNetwork);
         return testNetworkWrapper;
     }
 
+    private TestNetworkWrapper createTestNetworkWrapper(
+            boolean isMetered, int subId, InetAddress localAddress) throws Exception {
+        final Set<Integer> capabilities = new HashSet<>();
+        capabilities.add(NET_CAPABILITY_CBS);
+        if (!isMetered) {
+            capabilities.add(NET_CAPABILITY_NOT_METERED);
+        }
+
+        return createTestNetworkWrapper(subId, localAddress, capabilities);
+    }
+
     @Test
     public void testVcnManagedNetworkLosesNotVcnManagedCapability() throws Exception {
         final int subId = verifyAndGetValidDataSubId();
@@ -519,108 +536,256 @@
         }
     }
 
+    private TestNetworkWrapper createTestNetworkForNetworkSelection(
+            int subId, Set<Integer> capabilities) throws Exception {
+        return createTestNetworkWrapper(subId, LOCAL_ADDRESS, capabilities);
+    }
+
+    private void verifyVcnMigratesToPreferredUnderlyingNetwork(
+            VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a less preferred network.
+        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperLessPreferred);
+
+                        // Then bring up a more preferred network, and expect to switch to it.
+                        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                                createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+                            injectAndVerifyIkeMobikePackets(
+                                    testNetworkWrapperPreferred.ikeTunUtils);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
+    private void verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+            VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a more preferred network.
+        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperPreferred);
+
+                        // Then bring up a less preferred network, and expect the VCN underlying
+                        // network does not change.
+                        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                                createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+                            injectAndVerifyIkeDpdPackets(
+                                    testNetworkWrapperPreferred.ikeTunUtils,
+                                    vcnSetupResult.ikeExchangePortPair);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
+    private void verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+            VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+            throws Exception {
+        final int subId = verifyAndGetValidDataSubId();
+
+        // Start on a more preferred network
+        try (TestNetworkWrapper testNetworkWrapperPreferred =
+                createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+            verifyUnderlyingCellAndRunTest(
+                    subId,
+                    (subGrp, cellNetwork, cellNetworkCb) -> {
+                        final VcnSetupResult vcnSetupResult =
+                                setupAndGetVcnNetwork(
+                                        subGrp,
+                                        cellNetwork,
+                                        cellNetworkCb,
+                                        vcnConfig,
+                                        testNetworkWrapperPreferred);
+
+                        // Bring up a less preferred network
+                        try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+                                createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+                            // Teardown the preferred network
+                            testNetworkWrapperPreferred.close();
+                            testNetworkWrapperPreferred.vcnNetworkCallback.waitForLost();
+
+                            // Verify the VCN switches to the remaining less preferred network
+                            injectAndVerifyIkeMobikePackets(
+                                    testNetworkWrapperLessPreferred.ikeTunUtils);
+
+                            clearVcnConfigsAndVerifyNetworkTeardown(
+                                    subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+                        }
+                    });
+        }
+    }
+
+    private VcnCellUnderlyingNetworkTemplate.Builder createCellTemplateBaseBuilder()
+            throws Exception {
+        return new VcnCellUnderlyingNetworkTemplate.Builder().setInternet(MATCH_ANY);
+    }
+
     private VcnConfig createVcnConfigPrefersMetered() throws Exception {
         final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
         nwTemplates.add(
-                new VcnWifiUnderlyingNetworkTemplate.Builder().setMetered(MATCH_REQUIRED).build());
+                createCellTemplateBaseBuilder()
+                        .setCbs(MATCH_REQUIRED)
+                        .setMetered(MATCH_REQUIRED)
+                        .build());
         nwTemplates.add(
-                new VcnWifiUnderlyingNetworkTemplate.Builder().setMetered(MATCH_FORBIDDEN).build());
+                createCellTemplateBaseBuilder()
+                        .setCbs(MATCH_REQUIRED)
+                        .setMetered(MATCH_FORBIDDEN)
+                        .build());
         return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
     }
 
     @Test
-    public void testVcnMigratesToPreferredUnderlyingNetwork() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
-        // Start on NOT_METERED, less preferred network.
-        try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                    setupAndGetVcnNetwork(
-                        subGrp,
-                        cellNetwork,
-                        cellNetworkCb,
-                        vcnConfig,
-                        testNetworkWrapperNotMetered);
-
-                // Then bring up a more preferred network, and expect to switch to it.
-                try (TestNetworkWrapper testNetworkWrapperMetered =
-                        createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    injectAndVerifyIkeMobikePackets(testNetworkWrapperMetered.ikeTunUtils);
-
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    public void testVcnMigratesToPreferredUnderlyingNetwork_preferMetered() throws Exception {
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                createVcnConfigPrefersMetered(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_CBS));
     }
 
     @Test
-    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
-        // Start on METERED, more preferred network
-        try (TestNetworkWrapper testNetworkWrapperMetered =
-                createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                        setupAndGetVcnNetwork(
-                                subGrp,
-                                cellNetwork,
-                                cellNetworkCb,
-                                vcnConfig,
-                                testNetworkWrapperMetered);
-
-                // Then bring up a less preferred network, and expect the VCN underlying
-                // network does not change.
-                try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                        createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    injectAndVerifyIkeDpdPackets(
-                            testNetworkWrapperMetered.ikeTunUtils,
-                            vcnSetupResult.ikeExchangePortPair);
-
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferMetered()
+            throws Exception {
+        verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+                createVcnConfigPrefersMetered(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_CBS));
     }
 
     @Test
-    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies() throws Exception {
-        final int subId = verifyAndGetValidDataSubId();
-        final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
+    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferMetered()
+            throws Exception {
+        verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+                createVcnConfigPrefersMetered(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_CBS));
+    }
 
-        // Start on METERED, more preferred network
-        try (TestNetworkWrapper testNetworkWrapperMetered =
-                createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
-            verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
-                final VcnSetupResult vcnSetupResult =
-                        setupAndGetVcnNetwork(
-                                subGrp,
-                                cellNetwork,
-                                cellNetworkCb,
-                                vcnConfig,
-                                testNetworkWrapperMetered);
+    private VcnConfig createVcnConfigPrefersCbs() throws Exception {
+        final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+        nwTemplates.add(createCellTemplateBaseBuilder().setCbs(MATCH_REQUIRED).build());
+        nwTemplates.add(createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).build());
 
-                // Bring up a NOT_METERED, less preferred network
-                try (TestNetworkWrapper testNetworkWrapperNotMetered =
-                        createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
-                    // Teardown the preferred network
-                    testNetworkWrapperMetered.close();
-                    testNetworkWrapperMetered.vcnNetworkCallback.waitForLost();
+        return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+    }
 
-                    // Verify the VCN switches to the remaining NOT_METERED network
-                    injectAndVerifyIkeMobikePackets(testNetworkWrapperNotMetered.ikeTunUtils);
+    @Test
+    public void testVcnMigratesToPreferredUnderlyingNetwork_preferCbs() throws Exception {
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                createVcnConfigPrefersCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+    }
 
-                    clearVcnConfigsAndVerifyNetworkTeardown(
-                            subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
-                }
-            });
-        }
+    @Test
+    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferCbs() throws Exception {
+        verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+                createVcnConfigPrefersCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+    }
+
+    @Test
+    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferCbs() throws Exception {
+        verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+                createVcnConfigPrefersCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+    }
+
+    private VcnConfig createVcnConfigPrefersNonCbs() throws Exception {
+        final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+        nwTemplates.add(
+                createCellTemplateBaseBuilder()
+                        .setRcs(MATCH_REQUIRED)
+                        .setCbs(MATCH_FORBIDDEN)
+                        .build());
+        nwTemplates.add(
+                createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+        return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+    }
+
+    @Test
+    public void testVcnMigratesToPreferredUnderlyingNetwork_preferNonCbs() throws Exception {
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                createVcnConfigPrefersNonCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+    }
+
+    @Test
+    public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferNonCbs() throws Exception {
+        verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+                createVcnConfigPrefersNonCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+    }
+
+    @Test
+    public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferNonCbs() throws Exception {
+        verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+                createVcnConfigPrefersNonCbs(),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+    }
+
+    @Test
+    public void testSetVcnWithCbsMatchAny_preferCbsNetworkOverUnmatchedNetwork() throws Exception {
+        final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+        nwTemplates.add(
+                createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+        final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                vcnConfig,
+                Set.of(NET_CAPABILITY_NOT_METERED),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS));
+    }
+
+    @Test
+    public void testSetVcnWithCbsMatchAny_preferNonCbsNetworkOverUnmatchedNetwork()
+            throws Exception {
+        final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+        nwTemplates.add(
+                createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+        final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+
+        verifyVcnMigratesToPreferredUnderlyingNetwork(
+                vcnConfig,
+                Set.of(NET_CAPABILITY_NOT_METERED),
+                Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
     }
 
     @Test
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
index c89cdb8..9cff62b 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
@@ -72,6 +72,9 @@
         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
         mContent.getViewTreeObserver().addOnDrawListener(this);
         mContent.setOnApplyWindowInsetsListener(this);
+
+        //setDecorFitsSystemWindows to false will ignore the cutout
+        getWindow().setDecorFitsSystemWindows(false);
     }
 
     @Override
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index d1e388b..08c2231 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
@@ -97,6 +97,7 @@
         decorView.setPointerIcon(
                 PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        getWindow().setDecorFitsSystemWindows(false);
 
         mLayoutParams = new FrameLayout.LayoutParams(DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
                 Gravity.LEFT | Gravity.TOP);
diff --git a/tools/cts-device-info/Android.bp b/tools/cts-device-info/Android.bp
index 21ec062..d6440b5 100644
--- a/tools/cts-device-info/Android.bp
+++ b/tools/cts-device-info/Android.bp
@@ -76,6 +76,7 @@
         " -a com.android.compatibility.common.deviceinfo.GraphicsDeviceInfo " +
         " -a com.android.compatibility.common.deviceinfo.HapticsDeviceInfo " +
         " -a com.android.compatibility.common.deviceinfo.InputDeviceInfo " +
+        " -a com.android.compatibility.common.deviceinfo.KeystoreAttestationDeviceInfo " +
         " -a com.android.compatibility.common.deviceinfo.LocaleDeviceInfo " +
         " -a com.android.compatibility.common.deviceinfo.MediaDeviceInfo " +
         " -a com.android.compatibility.common.deviceinfo.MemoryDeviceInfo " +