Merge "Snap for 11878398 from 128b052871c62d03b20dc106aa9e5413f8766c2b to busytown-mac-infra-release" into busytown-mac-infra-release
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 10f40ea..251146b 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -3079,6 +3079,7 @@
 
         <activity
             android:name=".camera.fov.PhotoCaptureActivity"
+            android:configChanges="orientation|screenSize"
             android:label="@string/camera_fov_calibration"
             android:exported="true"
             android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0caea4e..2f0bd55 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1208,6 +1208,8 @@
     <string name="multinetwork_connectivity_turn_wifi_off">Please turn Wi-Fi off.</string>
     <string name="multinetwork_connectivity_turn_wifi_positive">OK</string>
     <string name="multinetwork_connectivity_turn_wifi_negative">Cancel</string>
+    <string name="multinetwork_connectivity_connect_to_target_ap_positive">OK</string>
+    <string name="multinetwork_connectivity_connect_to_target_ap">Connect to configured SSID: %s</string>
     <!-- Strings for NfcTestActivity -->
     <string name="nfc_test">NFC Test</string>
     <string name="nfc_test_info">The Peer-to-Peer Data Exchange tests require two devices with
diff --git a/apps/CtsVerifier/res/xml/offhost_aid_list.xml b/apps/CtsVerifier/res/xml/offhost_aid_list.xml
index 524e54d..8329955 100644
--- a/apps/CtsVerifier/res/xml/offhost_aid_list.xml
+++ b/apps/CtsVerifier/res/xml/offhost_aid_list.xml
@@ -1,9 +1,7 @@
 <offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
     android:description="@string/offhostService">
     <aid-group>
-        <!-- OBTH card manager AID -->
         <aid-filter android:name="A000000151000000"/>
-        <!-- NXP card manager AID -->
-        <aid-filter android:name="A000000003000000"/>
+        <aid-filter android:name="A000000444000000"/>
     </aid-group>
 </offhost-apdu-service>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index e27ae0a..2259c3d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
@@ -271,6 +272,12 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        this.recreate();
+    }
+
+    @Override
     public void onPictureTaken(byte[] data, Camera camera) {
         File pictureFile = getPictureFile(this);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
index f1deb8d..44136cb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/net/MultiNetworkConnectivityTestActivity.java
@@ -20,14 +20,10 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
-        .COMPLETED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
-        .NOT_STARTED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
-        .STARTED;
-import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState
-        .WAITING_FOR_USER_INPUT;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.COMPLETED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.NOT_STARTED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.STARTED;
+import static com.android.cts.verifier.net.MultiNetworkConnectivityTestActivity.ValidatorState.WAITING_FOR_USER_INPUT;
 
 import android.app.ActivityManager;
 import android.app.AlertDialog;
@@ -44,7 +40,6 @@
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.wifi.SupplicantState;
-import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkSpecifier;
@@ -70,7 +65,7 @@
 import java.util.List;
 
 /**
- * A CTS verifier to ensure that when an app calls WifiManager#enableNetwork,
+ * A CTS verifier to ensure that when device connect to a new Wi-Fi network,
  * - When the wifi network does not have internet connectivity, the device should
  * not disable other forms or connectivity, for example cellular.
  * - When the wifi network that the phone connects to loses connectivity, then
@@ -212,7 +207,6 @@
     protected void onDestroy() {
         super.onDestroy();
         destroyBroadcastReceivers();
-        restoreOriginalWifiState();
     }
 
     private void recordCurrentWifiState() {
@@ -245,12 +239,6 @@
         return result;
     }
 
-    private void restoreOriginalWifiState() {
-        if (mRecordedWifiConfiguration >= 0) {
-            mWifiManager.enableNetwork(mRecordedWifiConfiguration, true);
-        }
-    }
-
     private boolean requestSystemAlertWindowPerimissionIfRequired() {
         if (isLowRamDevice()) {
           // For low ram devices, we won't run tests that depend on this permission.
@@ -298,6 +286,23 @@
         alertDialog.show();
     }
 
+    private void requestUserConnectToApAsync(ConnectApCallback callback) {
+        if (isConnectedToExpectedWifiNetwork()) {
+            callback.onComplete(/* isSuccess = */ true);
+            return;
+        }
+
+        AlertDialog alertDialog = new AlertDialog.Builder(this)
+                .setMessage(getString(R.string.multinetwork_connectivity_connect_to_target_ap,
+                        mAccessPointSsid))
+                .setPositiveButton(R.string.multinetwork_connectivity_turn_wifi_positive,
+                        (a, b) -> requestUserConnectToApAsync(callback))
+                .setNegativeButton(R.string.multinetwork_connectivity_turn_wifi_negative,
+                        (a, b) -> callback.onComplete(/* isSuccess = */ false))
+                .create();
+        alertDialog.show();
+    }
+
     private void toggleWifiAsync(SetWifiCallback callback) {
         // Turn off WiFi.
         requestUserEnableWifiAsync(false, (isSuccess) -> {
@@ -489,31 +494,6 @@
         }
     }
 
-    private WifiConfiguration buildWifiConfiguration() {
-        WifiConfiguration wifiConfiguration = new WifiConfiguration();
-        wifiConfiguration.SSID = "\"" + mAccessPointSsid + "\"";
-        wifiConfiguration.preSharedKey = "\"" + mPskValue + "\"";
-        wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
-        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
-        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
-        wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
-        wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-        wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-        return wifiConfiguration;
-    }
-
-    private int getOrAddLegacyNetwork() {
-        List<WifiConfiguration> availableConfigurations = mWifiManager.getConfiguredNetworks();
-        for (WifiConfiguration configuration : availableConfigurations) {
-            if (mAccessPointSsid.equals(configuration.SSID)) {
-                return configuration.networkId;
-            }
-        }
-        int newNetwork = mWifiManager.addNetwork(buildWifiConfiguration());
-        return newNetwork;
-    }
-
     private boolean isConnectedToExpectedWifiNetwork() {
         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
         DhcpInfo dhcpInfo = mWifiManager.getDhcpInfo();
@@ -601,15 +581,7 @@
             }
         }
 
-        private void legacyConnectToWifiNetwork(boolean requireInternet) {
-            // If device is not connected to the expected WifiNetwork, connect to the wifi Network.
-            // Timeout with failure if it can't connect.
-            if (!isConnectedToExpectedWifiNetwork()) {
-                int network = getOrAddLegacyNetwork();
-                WifiManager wifiManager = (WifiManager) getApplicationContext()
-                        .getSystemService(Context.WIFI_SERVICE);
-                wifiManager.enableNetwork(network, true);
-            }
+        private void requestNetwork(boolean requireInternet) {
             startTimerDisplay(WIFI_NETWORK_CONNECT_TIMEOUT_MS / 1000);
             NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder()
                     .addTransportType(TRANSPORT_WIFI);
@@ -750,6 +722,9 @@
 
         /** Called when cellular network is connected. */
         void onCellularNetworkConnected(Network network) {
+            if (mValidatorState != NOT_STARTED) {
+                return;
+            }
             onContinuePreWifiConnect();
         }
 
@@ -855,7 +830,14 @@
 
         void connectToWifi() {
             mTestCallback.testProgress(R.string.multinetwork_connectivity_test_connect_wifi);
-            mConnectivityState.legacyConnectToWifiNetwork(false);
+            requestUserConnectToApAsync((isSuccess) -> {
+                if (isSuccess) {
+                    // Request network
+                    mConnectivityState.requestNetwork(false);
+                } else {
+                    endTest(false, R.string.multinetwork_status_wifi_connect_wrong_ap);
+                }
+            });
         }
     }
 
@@ -898,7 +880,14 @@
 
         void connectToWifi() {
             mTestCallback.testProgress(R.string.multinetwork_connectivity_test_connect_wifi);
-            mConnectivityState.legacyConnectToWifiNetwork(true);
+            requestUserConnectToApAsync((isSuccess) -> {
+                if (isSuccess) {
+                    // Request network
+                    mConnectivityState.requestNetwork(true);
+                } else {
+                    endTest(false, R.string.multinetwork_status_unable_to_toggle_wifi);
+                }
+            });
         }
 
         @Override
@@ -1042,4 +1031,8 @@
     private interface SetWifiCallback {
         void onComplete(boolean isSuccess);
     }
+
+    private interface ConnectApCallback {
+        void onComplete(boolean isSuccess);
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
index d8cdf19..d9b18ab 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
@@ -10,7 +10,7 @@
     public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
         HceUtils.buildSelectApdu("A000000151000000", true),
         HceUtils.buildCommandApdu("80CA9F7F00", true),
-        HceUtils.buildSelectApdu("A000000003000000", true),
+        HceUtils.buildSelectApdu("A000000444000000", true),
         HceUtils.buildCommandApdu("80CA9F7F00", true)
     };
 
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
index 0231a04..4de51e6 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/OWNERS
@@ -3,3 +3,6 @@
 # Bug component: 1084732 = per-file KeystoreAttestationDeviceInfo.java
 # Bug template url: http://b/new?component=1084732&template=1604634 = per-file KeystoreAttestationDeviceInfo.java
 per-file KeystoreAttestationDeviceInfo.java = file:platform/cts:/tests/tests/keystore/OWNERS
+
+# Bug component: 137825 = per-file PermissionDeviceInfo.java
+per-file PermissionDeviceInfo.java = file:platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java
new file mode 100644
index 0000000..e1d38ac
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/FrameworkSpecificTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for tests that specifically exercises Framework code (e.g. not in a mainline
+ * module). This is used to identify tests that should be skipped when running mainline
+ * module tests, such as MTS or MCTS.
+ * in summary:
+ * tag with '@FrameworkSpecificTest' -- run: CTS, skip: MCTS, MTS
+ * tag with '@ModuleSpecificTest' -- run: MCTS, MTS; skip: CTS
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface FrameworkSpecificTest {
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java
new file mode 100644
index 0000000..5b38701
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/ModuleSpecificTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for tests that specifically exercises Mainline Module code.
+ * This is used to identify tests that should be skipped when running CTS.
+ * in summary:
+ * tag with '@FrameworkSpecificTest' -- run: CTS, skip: MCTS, MTS
+ * tag with '@ModuleSpecificTest' -- run: MCTS, MTS; skip: CTS
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface ModuleSpecificTest {
+}
diff --git a/hostsidetests/adb/OWNERS b/hostsidetests/adb/OWNERS
index 5050f5c..f86fdc1 100644
--- a/hostsidetests/adb/OWNERS
+++ b/hostsidetests/adb/OWNERS
@@ -1,3 +1,3 @@
 # Bug component: 1352
-shaju@google.com
+sanglardf@google.com
 include platform/system/core:/janitors/OWNERS
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesPreInstallOverrideTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesPreInstallOverrideTest.java
index e3d3d80..7e85795 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesPreInstallOverrideTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesPreInstallOverrideTest.java
@@ -31,6 +31,8 @@
     private static final String CTS_CHANGE_ID_NAME = "CTS_SYSTEM_API_CHANGEID";
     private static final long CTS_CHANGE_ID = 149391281L;
 
+    private static final int WAIT_TIME_MS = 1_000;
+
     @Override
     protected void setUp() throws Exception {
         uninstallPackage(TEST_PACKAGE, false);
@@ -130,6 +132,9 @@
     }
 
     private Change getCtsChange() throws Exception {
+        // Data put by device_config app_compat_overrides need some time to update the data
+        // for dumpsys platform_compat so adding some sleep time
+        Thread.sleep(WAIT_TIME_MS);
         return getOnDeviceChangeIdConfig(CTS_CHANGE_ID);
     }
 }
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
index f57fe29..af840c9 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesValidConfigTest.java
@@ -108,6 +108,7 @@
             "OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED",
             "OVERRIDE_RESPECT_REQUESTED_ORIENTATION",
             "OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS",
+            "OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION",
             "DEFAULT_RESCIND_BAL_FG_PRIVILEGES_BOUND_SERVICE",
             "DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER",
             "RETURN_DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY",
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
index 236192e..ac90bba 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
@@ -49,12 +49,18 @@
             assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getDeviceId"),
                     ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
                             TelephonyManager::getDeviceId), telephonyManager.getDeviceId());
-            assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getImei"),
-                    ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
-                            TelephonyManager::getImei), telephonyManager.getImei());
-            assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getMeid"),
-                    ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
-                            TelephonyManager::getMeid), telephonyManager.getMeid());
+            if (mContext.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_TELEPHONY_GSM)) {
+                assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getImei"),
+                        ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+                                TelephonyManager::getImei), telephonyManager.getImei());
+            }
+            if (mContext.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_TELEPHONY_CDMA)) {
+                assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getMeid"),
+                        ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+                                TelephonyManager::getMeid), telephonyManager.getMeid());
+            }
             assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getSubscriberId"),
                     ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
                             TelephonyManager::getSubscriberId), telephonyManager.getSubscriberId());
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
index 055653f..13f0b74 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assume.assumeFalse;
+
 import android.hdmicec.cts.BaseHdmiCecCtsTest;
 import android.hdmicec.cts.CecMessage;
 import android.hdmicec.cts.CecOperand;
@@ -161,6 +163,9 @@
      */
     @Test
     public void testPowerStateChangeOnActiveSourceLost_standby() throws Exception {
+        assumeFalse("Skip for audio system devices (b/323469502)",
+                hasDeviceType(HdmiCecConstants.CEC_DEVICE_TYPE_AUDIO_SYSTEM));
+
         String previousActionOnActiveSourceLost = setPowerStateChangeOnActiveSourceLost(
                 HdmiCecConstants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW);
         try {
diff --git a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
index cecb6ed..881ab71 100644
--- a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
+++ b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
@@ -128,7 +128,7 @@
             RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(mTestPackageName, RUNNER,
                     device.getIDevice());
             // set a max deadline limit to avoid hanging forever
-            runner.setMaxTimeToOutputResponse(5, TimeUnit.MINUTES);
+            runner.setMaxTimeToOutputResponse(10, TimeUnit.MINUTES);
 
             AttachAgent aa = new AttachAgent(device, mTestPackageName, mTestApk);
             aa.prepare();
diff --git a/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml b/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
index a3c5336..54e7d95 100644
--- a/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
+++ b/hostsidetests/mediapc/videoencodingquality/app/AndroidManifest.xml
@@ -37,8 +37,5 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="android.videoencoding.app"
             android:label="Video encoding app for android.media" >
-        <meta-data
-            android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 </manifest>
diff --git a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
index df3e178..1b789dd 100644
--- a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
+++ b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
@@ -134,82 +134,129 @@
     @Option(name = "quick-check", description = "Run a quick check.")
     private boolean mQuickCheck = false;
 
-    public CtsVideoEncodingQualityHostTest(String jsonName) {
+    public CtsVideoEncodingQualityHostTest(String jsonName,
+            @SuppressWarnings("unused") String testLabel) {
         mJsonName = jsonName;
     }
 
-    private static final List<String> AVC_VBR_B0_PARAMS = Arrays.asList(
-            "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p"
-                    + "-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+    private static final List<Object[]> AVC_VBR_B0_PARAMS = Arrays.asList(new Object[][]{
+            {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+                    "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
                     + ".json",
-            "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p"
+                    "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
                     + "-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+                            + "vbr_b0"},
+            {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+                    "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json"
+                    , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json",
+                    "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0"
                     + ".json",
-            "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_avc_vbr_b0.json");
+                    "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b0.json"
+                    , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+                    + "-1080p-30fps_hw_avc_vbr_b0.json",
+                    "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+                            + "vbr_b0"}});
 
-    private static final List<String> AVC_VBR_B3_PARAMS = Arrays.asList(
-            "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+    private static final List<Object[]> AVC_VBR_B3_PARAMS = Arrays.asList(new Object[][]{
+            {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+                    "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
                     + ".json",
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+                    "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
                     + "-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+                            + "vbr_b3"},
+            {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+                    "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json"
+                    , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
+                    "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3"
                     + ".json",
-            "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json",
-            "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_avc_vbr_b3.json");
+                    "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_avc_vbr_b3.json"
+                    , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_avc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+                    + "-1080p-30fps_hw_avc_vbr_b3.json",
+                    "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_"
+                            + "vbr_b3"}});
 
-    private static final List<String> HEVC_VBR_B0_PARAMS = Arrays.asList(
-            "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+    private static final List<Object[]> HEVC_VBR_B0_PARAMS = Arrays.asList(new Object[][]{
+            {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+                    "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
                     + ".json",
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+                    "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
                     + "-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+                            + "vbr_b0"},
+            {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+                    "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json"
+                    , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
+                    "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0"
                     + ".json",
-            "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_hevc_vbr_b0.json");
+                    "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b0.json"
+                    , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b0"},
+            {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+                    + "-1080p-30fps_hw_hevc_vbr_b0.json",
+                    "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+                            + "vbr_b0"}});
 
-    private static final List<String> HEVC_VBR_B3_PARAMS = Arrays.asList(
-            "AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
-            "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
+    private static final List<Object[]> HEVC_VBR_B3_PARAMS = Arrays.asList(new Object[][]{
+            {"AVICON-MOBILE-Beach-SO04-CRW02-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+                    "Beach_SO04_CRW02_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+            {"AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
                     + ".json",
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+                    "BirthdayHalfway_SI17_CRUW03_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
                     + "-30fps_hw_hevc_vbr_b3.json",
-            "AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
-            "AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
-            "AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+                            + "vbr_b3"},
+            {"AVICON-MOBILE-Waterfall-SO05-CRW01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+                    "Waterfall_SO05_CRW01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieFamily-SF14-CF01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json"
+                    , "SelfieFamily_SF14_CF01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+            {"AVICON-MOBILE-River-SO03-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
+                    "River_SO03_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
             // Abnormal curve, not monotonically increasing.
-            /*"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
-                    + ".json",*/
-            "AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json",
-            "AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_hevc_vbr_b3.json");
+            /*{"AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3"
+                    + ".json",
+                    "SelfieGroupGarden_SF15_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},*/
+            {"AVICON-MOBILE-ConcertNear-SI10-CRW01-L-420-8bit-SDR-1080p-30fps_hw_hevc_vbr_b3.json"
+                    , "ConcertNear_SI10_CRW01_L_420_8bit_SDR_1080p_30fps_hw_hevc_vbr_b3"},
+            {"AVICON-MOBILE-SelfieCoupleCitySocialMedia-SS02-CF01-P-420-8bit-SDR"
+                    + "-1080p-30fps_hw_hevc_vbr_b3.json",
+                    "SelfieCoupleCitySocialMedia_SS02_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+                            + "vbr_b3"}});
 
-    private static final List<String> QUICK_RUN_PARAMS = Arrays.asList(
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+    private static final List<Object[]> QUICK_RUN_PARAMS = Arrays.asList(new Object[][]{
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
                     + "-30fps_hw_avc_vbr_b0.json",
-            "AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
-                    + "-30fps_hw_hevc_vbr_b0.json");
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_avc_" +
+                            "vbr_b0"},
+            {"AVICON-MOBILE-SelfieTeenKitchenSocialMedia-SS01-CF01-P-420-8bit-SDR-1080p"
+                    + "-30fps_hw_hevc_vbr_b0.json",
+                    "SelfieTeenKitchenSocialMedia_SS01_CF01_P_420_8bit_SDR_1080p_30fps_hw_hevc_"
+                            + "vbr_b0"}});
 
-    @Parameterized.Parameters(name = "{index}_{0}")
-    public static List<String> input() {
-        final List<String> args = new ArrayList<>();
+    @Parameterized.Parameters(name = "{index}_{1}")
+    public static List<Object[]> input() {
+        final List<Object[]> args = new ArrayList<>();
         args.addAll(AVC_VBR_B0_PARAMS);
         args.addAll(AVC_VBR_B3_PARAMS);
         args.addAll(HEVC_VBR_B0_PARAMS);
@@ -297,6 +344,15 @@
         sIsTestSetUpDone = true;
     }
 
+    public static boolean containsJson(String jsonName, List<Object[]> params) {
+        for (Object[] param : params) {
+            if (param[0].equals(jsonName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Verify the video encoding quality requirements for the performance class 14 devices.
      */
@@ -304,19 +360,19 @@
     @Test
     public void testEncoding() throws Exception {
         Assume.assumeFalse("Skipping due to quick run mode",
-                mQuickCheck && !QUICK_RUN_PARAMS.contains(mJsonName));
+                mQuickCheck && !containsJson(mJsonName, QUICK_RUN_PARAMS));
         Assume.assumeFalse("Skipping avc encoder tests",
-                mSkipAvc && (AVC_VBR_B0_PARAMS.contains(mJsonName) || AVC_VBR_B3_PARAMS.contains(
-                        mJsonName)));
+                mSkipAvc && (containsJson(mJsonName, AVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+                        AVC_VBR_B3_PARAMS)));
         Assume.assumeFalse("Skipping hevc encoder tests",
-                mSkipHevc && (HEVC_VBR_B0_PARAMS.contains(mJsonName) || HEVC_VBR_B3_PARAMS.contains(
-                        mJsonName)));
+                mSkipHevc && (containsJson(mJsonName, HEVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+                        HEVC_VBR_B3_PARAMS)));
         Assume.assumeFalse("Skipping b-frame tests",
-                mSkipB && (AVC_VBR_B3_PARAMS.contains(mJsonName) || HEVC_VBR_B3_PARAMS.contains(
-                        mJsonName)));
+                mSkipB && (containsJson(mJsonName, AVC_VBR_B3_PARAMS) || containsJson(mJsonName,
+                        HEVC_VBR_B3_PARAMS)));
         Assume.assumeFalse("Skipping non b-frame tests",
-                mSkipP && (AVC_VBR_B0_PARAMS.contains(mJsonName) || HEVC_VBR_B0_PARAMS.contains(
-                        mJsonName)));
+                mSkipP && (containsJson(mJsonName, AVC_VBR_B0_PARAMS) || containsJson(mJsonName,
+                        HEVC_VBR_B0_PARAMS)));
 
         // set up test environment
         sLock.lock();
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index b337265..c024efc 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -1200,13 +1200,16 @@
         return packageManager.hasSystemFeature(feature);
     }
 
-    private static void scrollIntoView(UiSelector selector) {
+    private static void scrollIntoView(UiSelector selector) throws Exception {
         UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+        uiScrollable.setSwipeDeadZonePercentage(0.25);
         try {
             uiScrollable.scrollIntoView(selector);
         } catch (UiObjectNotFoundException e) {
             // Scrolling can fail if the UI is not scrollable
         }
+        // Sleep for a few moments to let the scroll fully stop.
+        Thread.sleep(250);
     }
 
     /**
diff --git a/hostsidetests/statsdatom/apps/statsdapp/Android.bp b/hostsidetests/statsdatom/apps/statsdapp/Android.bp
index 16f4505..c8faad0 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/Android.bp
+++ b/hostsidetests/statsdatom/apps/statsdapp/Android.bp
@@ -60,6 +60,7 @@
     ],
     privileged: true,
     static_libs: [
+        "bluetooth-test-util-lib",
         "core-tests-support",
         "ctstestrunner-axt",
         "compatibility-device-util-axt",
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 22c1915..4405882 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
@@ -18,6 +18,7 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertNotNull;
@@ -35,12 +36,13 @@
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
 import android.app.usage.NetworkStatsManager;
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.le.BluetoothLeScanner;
 import android.bluetooth.le.ScanCallback;
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanResult;
 import android.bluetooth.le.ScanSettings;
+import android.bluetooth.test_utils.BlockingBluetoothAdapter;
+import android.bluetooth.test_utils.EnableBluetoothRule;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -85,6 +87,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.PropertyUtil;
@@ -94,7 +97,9 @@
 import libcore.javax.net.ssl.TestSSLSocketPair;
 
 import org.junit.Assert;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.net.HttpURLConnection;
 import java.net.URL;
@@ -104,11 +109,14 @@
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
 
 import javax.net.ssl.SSLSocket;
 
+@RunWith(AndroidJUnit4.class)
 public class AtomTests {
+    @ClassRule
+    public static final EnableBluetoothRule sEnableBluetoothRule = new EnableBluetoothRule();
+
     private static final String TAG = AtomTests.class.getSimpleName();
 
     private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsdatom";
@@ -321,62 +329,56 @@
 
     @Test
     public void testBleScanInterrupted() throws Exception {
-        performBleAction((bluetoothAdapter, bleScanner) -> {
-            ScanSettings scanSettings = new ScanSettings.Builder()
-                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
-            ScanCallback scanCallback = new ScanCallback() {
-                @Override
-                public void onScanResult(int callbackType, ScanResult result) {
-                    Log.v(TAG, "called onScanResult");
-                }
-
-                @Override
-                public void onScanFailed(int errorCode) {
-                    Log.v(TAG, "called onScanFailed");
-                }
-
-                @Override
-                public void onBatchScanResults(List<ScanResult> results) {
-                    Log.v(TAG, "called onBatchScanResults");
-                }
-            };
-
-            int uid = Process.myUid();
-            int whatAtomId = 9_999;
-
-            // Get the current setting for bluetooth background scanning.
-            // Set to 0 if the setting is not found or an error occurs.
-            int initialBleScanGlobalSetting = Settings.Global.getInt(
-                    InstrumentationRegistry.getTargetContext().getContentResolver(),
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
-
-            // Turn off bluetooth background scanning.
-            Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
-
-            // Change state to State.ON.
-            bleScanner.startScan(null, scanSettings, scanCallback);
-            sleep(6_000);
-            writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-            writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-
-            bluetoothAdapter.disable();
-            sleep(6_000);
-
-            // Trigger State.RESET so that new state is State.OFF.
-            if (!bluetoothAdapter.enable()) {
-                Log.e(TAG, "Could not enable bluetooth to trigger state reset");
-                return;
+        BluetoothLeScanner bleScanner = sEnableBluetoothRule.mAdapter.getBluetoothLeScanner();
+        assertThat(bleScanner).isNotNull();
+        ScanSettings scanSettings = new ScanSettings.Builder()
+                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+        ScanCallback scanCallback = new ScanCallback() {
+            @Override
+            public void onScanResult(int callbackType, ScanResult result) {
+                Log.v(TAG, "called onScanResult");
             }
-            sleep(6_000); // Wait for Bluetooth to fully turn on.
-            writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-            writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
-            writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
 
-            // Set bluetooth background scanning to original setting.
-            Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, initialBleScanGlobalSetting);
-        });
+            @Override
+            public void onScanFailed(int errorCode) {
+                Log.v(TAG, "called onScanFailed");
+            }
+
+            @Override
+            public void onBatchScanResults(List<ScanResult> results) {
+                Log.v(TAG, "called onBatchScanResults");
+            }
+        };
+
+        int uid = Process.myUid();
+        int whatAtomId = 9_999;
+
+        // Get the current setting for bluetooth background scanning.
+        // Set to 0 if the setting is not found or an error occurs.
+        int initialBleScanGlobalSetting = Settings.Global.getInt(
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+
+        // Turn off bluetooth background scanning.
+        Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
+
+        // Change state to State.ON.
+        bleScanner.startScan(null, scanSettings, scanCallback);
+        sleep(6_000);
+        writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
+        writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
+
+        assertThat(BlockingBluetoothAdapter.disable(true)).isTrue();
+        assertThat(BlockingBluetoothAdapter.enable()).isTrue();
+
+        writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
+        writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
+        writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false);
+
+        // Set bluetooth background scanning to original setting.
+        Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, initialBleScanGlobalSetting);
     }
 
     private static void writeSliceByBleScanStateChangedAtom(int atomId, int firstUid,
@@ -393,71 +395,37 @@
         StatsLog.write(builder.build());
     }
 
-    /**
-     * Set up BluetoothLeScanner and perform the action in the callback.
-     * Restore Bluetooth to original state afterwards.
-     **/
-    private static void performBleAction(BiConsumer<BluetoothAdapter, BluetoothLeScanner> actions) {
-        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-        if (bluetoothAdapter == null) {
-            Log.e(TAG, "Device does not support Bluetooth");
-            return;
-        }
-        boolean bluetoothEnabledByTest = false;
-        if (!bluetoothAdapter.isEnabled()) {
-            if (!bluetoothAdapter.enable()) {
-                Log.e(TAG, "Bluetooth is not enabled");
-                return;
-            }
-            sleep(2_000); // Wait for Bluetooth to fully turn on.
-            bluetoothEnabledByTest = true;
-        }
-        BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
-        if (bleScanner == null) {
-            Log.e(TAG, "Cannot access BLE scanner");
-            return;
-        }
-
-        actions.accept(bluetoothAdapter, bleScanner);
-
-        // Restore adapter state
-        if (bluetoothEnabledByTest) {
-            bluetoothAdapter.disable();
-        }
-    }
-
-
     private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters,
             boolean waitForResult) {
-        performBleAction((bluetoothAdapter, bleScanner) -> {
-            CountDownLatch resultsLatch = new CountDownLatch(1);
-            ScanCallback scanCallback = new ScanCallback() {
-                @Override
-                public void onScanResult(int callbackType, ScanResult result) {
-                    Log.v(TAG, "called onScanResult");
-                    resultsLatch.countDown();
-                }
-
-                @Override
-                public void onScanFailed(int errorCode) {
-                    Log.v(TAG, "called onScanFailed");
-                }
-
-                @Override
-                public void onBatchScanResults(List<ScanResult> results) {
-                    Log.v(TAG, "called onBatchScanResults");
-                    resultsLatch.countDown();
-                }
-            };
-
-            bleScanner.startScan(scanFilters, scanSettings, scanCallback);
-            if (waitForResult) {
-                waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null);
-            } else {
-                sleep(2_000);
+        BluetoothLeScanner bleScanner = sEnableBluetoothRule.mAdapter.getBluetoothLeScanner();
+        assertThat(bleScanner).isNotNull();
+        CountDownLatch resultsLatch = new CountDownLatch(1);
+        ScanCallback scanCallback = new ScanCallback() {
+            @Override
+            public void onScanResult(int callbackType, ScanResult result) {
+                Log.v(TAG, "called onScanResult");
+                resultsLatch.countDown();
             }
-            bleScanner.stopScan(scanCallback);
-        });
+
+            @Override
+            public void onScanFailed(int errorCode) {
+                Log.v(TAG, "called onScanFailed");
+            }
+
+            @Override
+            public void onBatchScanResults(List<ScanResult> results) {
+                Log.v(TAG, "called onBatchScanResults");
+                resultsLatch.countDown();
+            }
+        };
+
+        bleScanner.startScan(scanFilters, scanSettings, scanCallback);
+        if (waitForResult) {
+            waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null);
+        } else {
+            sleep(2_000);
+        }
+        bleScanner.stopScan(scanCallback);
     }
 
     @Test
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsBackgroundService.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsBackgroundService.java
index daab751..36c2452 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsBackgroundService.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsBackgroundService.java
@@ -42,7 +42,7 @@
 
         switch (action) {
             case ACTION_BACKGROUND_SLEEP:
-                AtomTests.sleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP);
+                sleep(SLEEP_OF_ACTION_BACKGROUND_SLEEP);
                 break;
             case ACTION_ALLOCATE_MEMORY:
                 new Thread(MemoryHogger::allocate).start();
@@ -53,4 +53,12 @@
                 Log.e(TAG, "Intent had invalid action");
         }
     }
+
+    static void sleep(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Interrupted exception while sleeping", e);
+        }
+    }
 }
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsForegroundActivity.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsForegroundActivity.java
index 6f21bb3..0e54e1e 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsForegroundActivity.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/StatsdCtsForegroundActivity.java
@@ -129,7 +129,7 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                AtomTests.sleep(sleepTime);
+                sleep(sleepTime);
                 return null;
             }
 
@@ -167,7 +167,7 @@
         wm.addView(v, wmlp);
 
         // The overlay continues long after the finish. The following is just to end the activity.
-        AtomTests.sleep(SLEEP_OF_ACTION_SHOW_APPLICATION_OVERLAY);
+        sleep(SLEEP_OF_ACTION_SHOW_APPLICATION_OVERLAY);
         finish();
     }
 
@@ -257,8 +257,16 @@
         WifiManager wm = getSystemService(WifiManager.class);
         WifiManager.WifiLock lock = wm.createWifiLock(lockMode, "StatsdCTSWifiLock");
         lock.acquire();
-        AtomTests.sleep(500);
+        sleep(500);
         lock.release();
         finish();
     }
+
+    static void sleep(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Interrupted exception while sleeping", e);
+        }
+    }
 }
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
index 21d8ab7..b73916d 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/DeviceUtils.java
@@ -281,13 +281,22 @@
             throws DeviceNotAvailableException {
         String uidLine = device.executeShellCommand("cmd package list packages -U --user "
                 + userId + " " + pkgName);
-        String[] uidLineArr = uidLine.split(":");
 
-        // Package uid is located at index 2.
-        assertThat(uidLineArr.length).isGreaterThan(2);
-        int appUid = Integer.parseInt(uidLineArr[2].trim());
-        assertThat(appUid).isGreaterThan(10000);
-        return appUid;
+        // Split package list by lines
+        // Sample packages response:
+        // package:com.android.server.cts.device.statsd.host uid:1010033
+        // package:com.android.server.cts.device.statsd uid:1010034
+        final String[] lines = uidLine.split("\\R+");
+        for (final String line : lines) {
+            if (line.startsWith("package:" + pkgName + " ")) {
+                final int uidIndex = line.lastIndexOf(":") + 1;
+                final int uid = Integer.parseInt(line.substring(uidIndex).trim());
+                assertThat(uid).isGreaterThan(10_000);
+                return uid;
+            }
+        }
+        throw new Error(
+                String.format("Could not find installed package: %s", pkgName));
     }
 
     /**
diff --git a/hostsidetests/videoencodingminimum/app/AndroidManifest.xml b/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
index 3d25235..2cc1cf8 100644
--- a/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
+++ b/hostsidetests/videoencodingminimum/app/AndroidManifest.xml
@@ -37,8 +37,5 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="android.videoencodingmin.app"
             android:label="Video encoding app for android.media" >
-        <meta-data
-            android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 </manifest>
diff --git a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
index 25b2c86..6fb41c6 100644
--- a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
+++ b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
@@ -100,13 +100,14 @@
     @Option(name = "reset", description = "Start with a fresh directory.")
     private boolean mReset = false;
 
-    public CtsVideoQualityFloorHostTest(String jsonName) {
+    public CtsVideoQualityFloorHostTest(String jsonName,
+            @SuppressWarnings("unused") String testLabel) {
         mJsonName = jsonName;
     }
 
-    @Parameterized.Parameters(name = "{index}_{0}")
-    public static List<String> input() {
-        final List<String> args = new ArrayList<>();
+    @Parameterized.Parameters(name = "{index}_{1}")
+    public static List<Object[]> input() {
+        final List<Object[]> args = new ArrayList<>();
         String[] clips = {"Fireworks", "MountainBike", "Motorcycle", "TreesAndGrass"};
         String[] resolutions = {"1080p", "720p", "540p", "480p"};
         String[] codecInfos = {"avcBaseline3", "avcHigh4", "avcHigh52", "hevcMain3"};
@@ -114,7 +115,10 @@
         for (String clip : clips) {
             for (String res : resolutions) {
                 for (String info : codecInfos) {
-                    args.add(res + "-" + clip + "-" + info + ".json");
+                    Object[] testArgs = new Object[2];
+                    testArgs[0] = res + "-" + clip + "-" + info + ".json";
+                    testArgs[1] = res + "_" + clip + "_" + info;
+                    args.add(testArgs);
                 }
             }
         }
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 321ac8b..36424a7 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -468,11 +468,11 @@
         }
     }
 
-    private String cannonicalizeProcessName(ApplicationInfo ai) {
-        return cannonicalizeProcessName(ai.processName, ai);
+    private String canonicalizeProcessName(ApplicationInfo ai) {
+        return canonicalizeProcessName(ai.processName, ai);
     }
 
-    private String cannonicalizeProcessName(String process, ApplicationInfo ai) {
+    private String canonicalizeProcessName(String process, ApplicationInfo ai) {
         if (process == null) {
             return null;
         }
@@ -502,10 +502,10 @@
         ProviderInfo downloadInfo = pm.resolveContentProvider("downloads", 0);
         assertNotNull(downloadInfo);
         String downloadProcess
-                = cannonicalizeProcessName(downloadInfo.processName, downloadInfo.applicationInfo);
+                = canonicalizeProcessName(downloadInfo.processName, downloadInfo.applicationInfo);
 
         for (PackageInfo pi : mContext.getPackageManager().getInstalledPackages(0)) {
-            if (downloadProcess.equals(cannonicalizeProcessName(pi.applicationInfo))) {
+            if (downloadProcess.equals(canonicalizeProcessName(pi.applicationInfo))) {
                 assertTrue("package: " + pi.applicationInfo.packageName
                         + " must set android:usesCleartextTraffic=true"
                         ,(pi.applicationInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index e5ac608..5152135 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1531,9 +1531,16 @@
         long minExposureValue = -1;
         long maxExposureValuePreview = -1;
         long maxExposureValueStill = -1;
+        long maxPostRawSensitivity = 100;
+        Range<Integer> postRawSensitivityRange = mStaticInfo.getCharacteristics().get(
+                CameraCharacteristics.CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE);
+        if (postRawSensitivityRange != null) {
+            maxPostRawSensitivity = postRawSensitivityRange.getUpper();
+        }
+
         if (canReadExposureValueRange) {
             // Minimum exposure settings is mostly static while maximum exposure setting depends on
-            // frame rate range which in term depends on capture request.
+            // frame rate range which in turn depends on capture request.
             minExposureValue = mStaticInfo.getSensitivityMinimumOrDefault() *
                     mStaticInfo.getExposureMinimumOrDefault() / 1000;
             long maxSensitivity = mStaticInfo.getSensitivityMaximumOrDefault();
@@ -1559,12 +1566,14 @@
 
             long normalExposureValue = -1;
             if (canVerifyExposureValue) {
-                // get and check if current exposure value is valid
+                // get and check if current exposure value is valid, with maxPostRawSensitivity
+                // in mind.
                 normalExposureValue = getExposureValue(normalResult);
                 mCollector.expectInRange("Exposure setting out of bound", normalExposureValue,
-                        minExposureValue, maxExposureValuePreview);
+                        minExposureValue, maxExposureValuePreview * maxPostRawSensitivity / 100);
 
-                // Only run the test if expectedExposureValue is within valid range
+                // Only run the test if expectedExposureValue is within valid range. Do not
+                // scale the range by maxPostRawSensitivity to avoid clipping.
                 long expectedExposureValue = (long) (normalExposureValue * expectedRatio);
                 if (expectedExposureValue < minExposureValue ||
                     expectedExposureValue > maxExposureValueStill) {
@@ -1606,10 +1615,11 @@
                     request, WAIT_FOR_RESULT_TIMEOUT_MS);
 
             if (canVerifyExposureValue) {
-                // Verify the exposure value compensates as requested
+                // Verify the exposure value compensates as requested, with maxPostRawSensitivity
+                // in mind.
                 long compensatedExposureValue = getExposureValue(compensatedResult);
                 mCollector.expectInRange("Exposure setting out of bound", compensatedExposureValue,
-                        minExposureValue, maxExposureValueStill);
+                        minExposureValue, maxExposureValueStill * maxPostRawSensitivity / 100);
                 double observedRatio = (double) compensatedExposureValue / normalExposureValue;
                 double error = observedRatio / expectedRatio;
                 String errorString = String.format(
diff --git a/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java b/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
index b297b93..e827a50 100644
--- a/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
+++ b/tests/core/runner-axt/src/com/android/cts/core/runner/filter/CoreTestModeFilter.java
@@ -53,19 +53,19 @@
      */
     public static Predicate<Description> createInstance(Bundle args) {
         String mode = args.getString(ARGUMENT_MODE);
-        if ("mts".equals(mode)) {
-            // We have to hard-coded the annotation name of NonMts because the annotation definition
-            // isn't built into the same apk file.
-            return new CoreTestModeFilter(NonMts.class);
-        } else if ("presubmit".equals(mode)) {
-            return new CoreTestModeFilter(FlakyTest.class, LargeTest.class);
-        } else {
-            // The default mode is CTS, because most libcore test suites are prefixed with "Cts".
+        if ("cts".equals(mode)) {
             // It's okay that ignoredTestsInCts.txt doesn't exist in the test .apk file, and
             // the created CoreExpectationFilter doesn't skip any test in this case.
             Set<String> expectationFile = Set.of("/skippedCtsTest.txt");
             return new CoreTestModeFilter(NonCts.class)
                     .and(CoreExpectationFilter.createInstance(expectationFile));
+        } else if ("presubmit".equals(mode)) {
+            return new CoreTestModeFilter(FlakyTest.class, LargeTest.class);
+        } else {
+            // Use MTS mode by default because MCTS should dynamically download
+            // the MCTS artifacts in the same version as the ART module installed
+            // on the device.
+            return new CoreTestModeFilter(NonMts.class);
         }
     }
 
diff --git a/tests/core/runner-axt/src/com/android/cts/runner/CtsTestRunListener.java b/tests/core/runner-axt/src/com/android/cts/runner/CtsTestRunListener.java
deleted file mode 100644
index 0822ca2..0000000
--- a/tests/core/runner-axt/src/com/android/cts/runner/CtsTestRunListener.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.runner;
-
-import android.app.ActivityManager;
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.test.internal.runner.listener.InstrumentationRunListener;
-
-import junit.framework.TestCase;
-
-import org.junit.runner.Description;
-import org.junit.runner.notification.RunListener;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.Class;
-import java.lang.ReflectiveOperationException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.net.Authenticator;
-import java.net.CookieHandler;
-import java.net.ResponseCache;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.TimeZone;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSocketFactory;
-
-/**
- * A {@link RunListener} for CTS. Sets the system properties necessary for many
- * core tests to run. This is needed because there are some core tests that need
- * writing access to the file system.
- * Finally, we add a means to free memory allocated by a TestCase after its
- * execution.
- */
-public class CtsTestRunListener extends InstrumentationRunListener {
-
-    private static final String TAG = "CtsTestRunListener";
-
-    private TestEnvironment mEnvironment;
-    private Class<?> lastClass;
-
-    @Override
-    public void testRunStarted(Description description) throws Exception {
-        mEnvironment = new TestEnvironment(getInstrumentation().getTargetContext());
-
-        // We might want to move this to /sdcard, if is is mounted/writable.
-        File cacheDir = getInstrumentation().getTargetContext().getCacheDir();
-        System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
-
-        // attempt to disable keyguard, if current test has permission to do so
-        // TODO: move this to a better place, such as InstrumentationTestRunner
-        // ?
-        if (getInstrumentation().getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.DISABLE_KEYGUARD)
-                == PackageManager.PERMISSION_GRANTED) {
-            Log.i(TAG, "Disabling keyguard");
-            KeyguardManager keyguardManager =
-                    (KeyguardManager) getInstrumentation().getContext().getSystemService(
-                            Context.KEYGUARD_SERVICE);
-            keyguardManager.newKeyguardLock("cts").disableKeyguard();
-        } else {
-            Log.i(TAG, "Test lacks permission to disable keyguard. " +
-                    "UI based tests may fail if keyguard is up");
-        }
-    }
-
-    @Override
-    public void testStarted(Description description) throws Exception {
-        if (description.getTestClass() != lastClass) {
-            lastClass = description.getTestClass();
-            printMemory(description.getTestClass());
-        }
-
-        mEnvironment.reset();
-    }
-
-    @Override
-    public void testFinished(Description description) {
-        // no way to implement this in JUnit4...
-        // offending test cases that need this logic should probably be cleaned
-        // up individually
-        // if (test instanceof TestCase) {
-        // cleanup((TestCase) test);
-        // }
-    }
-
-    /**
-     * Dumps some memory info.
-     */
-    private void printMemory(Class<?> testClass) {
-        Runtime runtime = Runtime.getRuntime();
-
-        long total = runtime.totalMemory();
-        long free = runtime.freeMemory();
-        long used = total - free;
-
-        Log.d(TAG, "Total memory  : " + total);
-        Log.d(TAG, "Used memory   : " + used);
-        Log.d(TAG, "Free memory   : " + free);
-
-        String tempdir = System.getProperty("java.io.tmpdir", "");
-        // TODO: Remove these extra Logs added to debug a specific timeout problem.
-        Log.d(TAG, "java.io.tmpdir is:" + tempdir);
-
-        if (!TextUtils.isEmpty(tempdir)) {
-            String[] commands = {"df", tempdir};
-            BufferedReader in = null;
-            try {
-                Log.d(TAG, "About to .exec df");
-                Process proc = runtime.exec(commands);
-                Log.d(TAG, ".exec returned");
-                in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
-                Log.d(TAG, "Stream reader created");
-                String line;
-                while ((line = in.readLine()) != null) {
-                    Log.d(TAG, line);
-                }
-            } catch (IOException e) {
-                Log.d(TAG, "Exception: " + e.toString());
-                // Well, we tried
-            } finally {
-                Log.d(TAG, "In finally");
-                if (in != null) {
-                    try {
-                        in.close();
-                    } catch (IOException e) {
-                        // Meh
-                    }
-                }
-            }
-        }
-
-        Log.d(TAG, "Now executing : " + testClass.getName());
-    }
-
-    /**
-     * Nulls all non-static reference fields in the given test class. This
-     * method helps us with those test classes that don't have an explicit
-     * tearDown() method. Normally the garbage collector should take care of
-     * everything, but since JUnit keeps references to all test cases, a little
-     * help might be a good idea.
-     */
-    private void cleanup(TestCase test) {
-        Class<?> clazz = test.getClass();
-
-        while (clazz != TestCase.class) {
-            Field[] fields = clazz.getDeclaredFields();
-            for (int i = 0; i < fields.length; i++) {
-                Field f = fields[i];
-                if (!f.getType().isPrimitive() &&
-                        !Modifier.isStatic(f.getModifiers())) {
-                    try {
-                        f.setAccessible(true);
-                        f.set(test, null);
-                    } catch (Exception ignored) {
-                        // Nothing we can do about it.
-                    }
-                }
-            }
-
-            clazz = clazz.getSuperclass();
-        }
-    }
-
-    private interface TestEnvironmentResetter {
-        Boolean getDateFormatIs24Hour();
-        void setDateFormatIs24Hour(Boolean value);
-        Properties createDefaultProperties();
-    }
-
-    private static class AndroidTestEnvironmentResetter implements TestEnvironmentResetter {
-        private final Field mDateFormatIs24HourField;
-
-        AndroidTestEnvironmentResetter() {
-            try {
-                Class<?> dateFormatClass = Class.forName("java.text.DateFormat");
-                mDateFormatIs24HourField = dateFormatClass.getDeclaredField("is24Hour");
-            } catch (ReflectiveOperationException e) {
-                throw new AssertionError("Missing DateFormat.is24Hour", e);
-            }
-        }
-
-        @Override
-        public Boolean getDateFormatIs24Hour() {
-            try {
-                return (Boolean) mDateFormatIs24HourField.get(null);
-            } catch (ReflectiveOperationException e) {
-                throw new AssertionError("Unable to get java.text.DateFormat.is24Hour", e);
-            }
-        }
-
-        @Override
-        public void setDateFormatIs24Hour(Boolean value) {
-            try {
-                mDateFormatIs24HourField.set(null, value);
-            } catch (ReflectiveOperationException e) {
-                throw new AssertionError("Unable to set java.text.DateFormat.is24Hour", e);
-            }
-        }
-
-        @Override
-        public Properties createDefaultProperties() {
-            return new Properties();
-        }
-    }
-
-    private static class StubTestEnvironmentResetter implements TestEnvironmentResetter {
-        @Override
-        public Boolean getDateFormatIs24Hour() {
-            return false;
-        }
-
-        @Override
-        public void setDateFormatIs24Hour(Boolean value) {
-        }
-
-        @Override
-        public Properties createDefaultProperties() {
-            return System.getProperties();
-        }
-    }
-
-    // http://code.google.com/p/vogar/source/browse/trunk/src/vogar/target/TestEnvironment.java
-    static class TestEnvironment {
-        private final static TestEnvironmentResetter sTestEnvironmentResetter;
-        static {
-            if (System.getProperty("java.vendor").toLowerCase().contains("android")) {
-                sTestEnvironmentResetter = new AndroidTestEnvironmentResetter();
-            } else {
-                sTestEnvironmentResetter = new StubTestEnvironmentResetter();
-            }
-        }
-
-        private final Locale mDefaultLocale;
-        private final TimeZone mDefaultTimeZone;
-        private final HostnameVerifier mHostnameVerifier;
-        private final SSLSocketFactory mSslSocketFactory;
-        private final Properties mProperties;
-        private final Boolean mDefaultIs24Hour;
-
-        TestEnvironment(Context context) {
-            mDefaultLocale = Locale.getDefault();
-            mDefaultTimeZone = TimeZone.getDefault();
-            mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
-            mSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
-
-            mProperties = sTestEnvironmentResetter.createDefaultProperties();
-            mProperties.setProperty("user.home", "");
-            mProperties.setProperty("java.io.tmpdir", context.getCacheDir().getAbsolutePath());
-            // The CDD mandates that devices that support WiFi are the only ones that will have
-            // multicast.
-            PackageManager pm = context.getPackageManager();
-            mProperties.setProperty("android.cts.device.multicast",
-                    Boolean.toString(pm.hasSystemFeature(PackageManager.FEATURE_WIFI)));
-            mDefaultIs24Hour = sTestEnvironmentResetter.getDateFormatIs24Hour();
-
-            // There are tests in libcore that should be disabled for low ram devices. They can't
-            // access ActivityManager to call isLowRamDevice, but can read system properties.
-            ActivityManager activityManager =
-                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-            mProperties.setProperty("android.cts.device.lowram",
-                    Boolean.toString(activityManager.isLowRamDevice()));
-        }
-
-        void reset() {
-            System.setProperties(null);
-            System.setProperties(mProperties);
-            Locale.setDefault(mDefaultLocale);
-            TimeZone.setDefault(mDefaultTimeZone);
-            Authenticator.setDefault(null);
-            CookieHandler.setDefault(null);
-            ResponseCache.setDefault(null);
-            HttpsURLConnection.setDefaultHostnameVerifier(mHostnameVerifier);
-            HttpsURLConnection.setDefaultSSLSocketFactory(mSslSocketFactory);
-            sTestEnvironmentResetter.setDateFormatIs24Hour(mDefaultIs24Hour);
-        }
-    }
-}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
index 42d10eb..461ae88 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/BluetoothTest.java
@@ -413,6 +413,8 @@
     @Postsubmit(reason = "new test")
     @ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH_SHARING")
     public void share_disallowBluetoothAndSharingRestrictionsAreNotSet_canShare() {
+        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
         Poll.forValue("Opp Launcher Component Enabled",
                 () -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
                         .isEnabled(TestApis.users().system()))
@@ -420,8 +422,6 @@
                 .errorOnFail()
                 .await();
 
-        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
         List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
                 FILE_SHARING_INTENT, /* flags= */ 0);
         assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isTrue();
@@ -432,6 +432,8 @@
     @Postsubmit(reason = "new test")
     @ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH_SHARING")
     public void share_disallowBluetoothSharingRestrictionIsSet_canNotShare() {
+        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
         Poll.forValue("Opp Launcher Component Enabled",
                 () -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
                         .isEnabled(TestApis.users().system()))
@@ -439,8 +441,6 @@
                 .errorOnFail()
                 .await();
 
-        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
         List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
                 FILE_SHARING_INTENT, /* flags= */ 0);
         assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isFalse();
@@ -489,6 +489,8 @@
     @ApiTest(apis = "android.os.UserManager#DISALLOW_BLUETOOTH")
     @RequireNotHeadlessSystemUserMode(reason = "b/276405672 bluetooth restriction not enforced on secondary users")
     public void share_disallowBluetoothRestrictionIsSet_canNotShare() {
+        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
+
         Poll.forValue("Opp Launcher Component Enabled",
                 () -> TestApis.packages().activity(OPP_LAUNCHER_COMPONENT)
                         .isEnabled(TestApis.users().system()))
@@ -496,8 +498,6 @@
                 .errorOnFail()
                 .await();
 
-        Assume.assumeTrue("We can't test resolving if opp is disabled", OPP_ENABLED);
-
         List<ResolveInfo> resolveInfos = sPackageManager.queryIntentActivities(
                 FILE_SHARING_INTENT, /* flags= */ 0);
         assertThat(resolveInfosContainsActivity(resolveInfos, OPP_LAUNCHER_COMPONENT)).isFalse();
diff --git a/tests/input/src/android/input/cts/InputShellCommandTest.kt b/tests/input/src/android/input/cts/InputShellCommandTest.kt
index 39969ae..8d478c7 100644
--- a/tests/input/src/android/input/cts/InputShellCommandTest.kt
+++ b/tests/input/src/android/input/cts/InputShellCommandTest.kt
@@ -116,8 +116,8 @@
         val event = getMotionEvent()
         assertThat(event.source).isEqualTo(InputDevice.SOURCE_MOUSE)
         assertThat(event.action).isEqualTo(MotionEvent.ACTION_SCROLL)
-        assertThat(event.x).isEqualTo(x)
-        assertThat(event.y).isEqualTo(y)
+        assertThat(event.getRawX()).isEqualTo(x)
+        assertThat(event.getRawY()).isEqualTo(y)
         assertThat(event.getAxisValue(MotionEvent.AXIS_VSCROLL)).isEqualTo(-1)
     }
 
diff --git a/tests/libcore/ojluni/Android.bp b/tests/libcore/ojluni/Android.bp
index 1ee4d5a..9fd7270 100644
--- a/tests/libcore/ojluni/Android.bp
+++ b/tests/libcore/ojluni/Android.bp
@@ -47,6 +47,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mcts-art",
         "mts-art",
     ],
     data: [
@@ -55,3 +56,95 @@
     per_testcase_directory: true,
     host_required: ["cts-dalvik-host-test-runner"],
 }
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_lang_invoke",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "test.java.lang.invoke",
+        "org.openjdk.tests.java.lang.invoke",
+    ],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_net",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: ["test.java.net"],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_awt_font",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: ["test.java.awt.font"],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_nio_file_attribute",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: ["test.java.nio.file.attribute"],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_security_cert",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: ["test.java.security.cert"],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_time",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "tck.java.time.serial",
+        "tck.java.time",
+        "test.java.time",
+    ],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_time_chrono",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "tck.java.time.chrono.serial",
+        "test.java.time.chrono",
+        "tck.java.time.chrono",
+    ],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_time_format",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "test.java.time.format",
+        "tck.java.time.format",
+    ],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_time_temporal",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "tck.java.time.temporal",
+        "tck.java.time.temporal.serial",
+        "test.java.time.temporal",
+    ],
+}
+
+test_module_config {
+    name: "CtsLibcoreOjTestCases_time_zone",
+    base: "CtsLibcoreOjTestCases",
+    test_suites: ["general-tests"],
+    include_filters: [
+        "test.java.time.zone",
+        "tck.java.time.zone.serial",
+        "tck.java.time.zone",
+    ],
+}
diff --git a/tests/libcore/wycheproof/Android.bp b/tests/libcore/wycheproof/Android.bp
index 2138676..86cf252 100644
--- a/tests/libcore/wycheproof/Android.bp
+++ b/tests/libcore/wycheproof/Android.bp
@@ -21,6 +21,7 @@
     name: "CtsLibcoreWycheproofConscryptTestCases",
     defaults: ["cts_support_defaults"],
     platform_apis: true,
+    min_sdk_version: "30",
     static_libs: [
         "cts-core-test-runner-axt",
 
@@ -43,6 +44,8 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts-conscrypt",
+        "mcts-conscrypt",
     ],
     host_required: ["cts-dalvik-host-test-runner"],
 }
diff --git a/tests/libcore/wycheproof/AndroidTest.xml b/tests/libcore/wycheproof/AndroidTest.xml
index 29dd8ef..cf7f569 100644
--- a/tests/libcore/wycheproof/AndroidTest.xml
+++ b/tests/libcore/wycheproof/AndroidTest.xml
@@ -22,6 +22,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+    <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.conscrypt.apex" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has just the instrumentation which acts as the tests we want to run -->
@@ -43,4 +44,8 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.conscrypt" />
+    </object>
 </configuration>
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
index 9f6f5bf..54c370d 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecDecoderBlockModelMultiAccessUnitDrmTestBase.java
@@ -35,6 +35,8 @@
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.filters.SdkSuppress;
+
 import org.junit.After;
 
 import java.util.ArrayDeque;
@@ -45,6 +47,7 @@
  * Wrapper class for trying and testing secure mediacodec decoder components in block model large
  * audio buffer mode
  */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
 @RequiresApi(api = Build.VERSION_CODES.R)
 public class CodecDecoderBlockModelMultiAccessUnitDrmTestBase
         extends CodecDecoderBlockModelMultiAccessUnitTestBase {
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderBlockModelTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderBlockModelTestBase.java
index f953f4e..27a2c6f 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderBlockModelTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderBlockModelTestBase.java
@@ -172,7 +172,9 @@
                         mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
                         mMuxer.start();
                     }
-                    mMuxer.writeSampleData(mTrackID, buf, info);
+                    if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                        mMuxer.writeSampleData(mTrackID, buf, info);
+                    }
                 }
                 frame.getLinearBlock().recycle();
             }
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderSurfaceTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderSurfaceTestBase.java
index 8d2715a..91025b5 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderSurfaceTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderSurfaceTestBase.java
@@ -342,7 +342,9 @@
                     mTrackID = mMuxer.addTrack(mEncoder.getOutputFormat());
                     mMuxer.start();
                 }
-                mMuxer.writeSampleData(mTrackID, buf, info);
+                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                    mMuxer.writeSampleData(mTrackID, buf, info);
+                }
             }
             if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                 mOutputBuff.saveOutPTS(info.presentationTimeUs);
@@ -546,6 +548,14 @@
     protected void encodeToMemory(boolean isAsync, boolean signalEOSWithLastFrame,
             boolean saveToMem, OutputManager outBuff, boolean muxOutput, String outPath)
             throws IOException, InterruptedException {
+        encodeToMemory(isAsync, signalEOSWithLastFrame, saveToMem, outBuff, muxOutput, outPath,
+                Integer.MAX_VALUE);
+    }
+
+    @TargetApi(33)
+    protected void encodeToMemory(boolean isAsync, boolean signalEOSWithLastFrame,
+            boolean saveToMem, OutputManager outBuff, boolean muxOutput, String outPath,
+            int frameLimit) throws IOException, InterruptedException {
         mSaveToMem = saveToMem;
         mOutputBuff = outBuff;
         mOutputBuff.reset();
@@ -565,7 +575,7 @@
         }
         mEncoder.start();
         mDecoder.start();
-        doWork(Integer.MAX_VALUE);
+        doWork(frameLimit);
         queueEOS();
         waitForAllEncoderOutputs();
         if (muxOutput) {
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
index 79836443..55084e6 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
@@ -136,7 +136,9 @@
             int trackID = muxer.addTrack(format);
             muxer.start();
             for (MediaCodec.BufferInfo info : infos) {
-                muxer.writeSampleData(trackID, buffer, info);
+                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                    muxer.writeSampleData(trackID, buffer, info);
+                }
             }
             muxer.stop();
         } finally {
@@ -537,7 +539,9 @@
                     mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
                     mMuxer.start();
                 }
-                mMuxer.writeSampleData(mTrackID, buf, info);
+                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                    mMuxer.writeSampleData(mTrackID, buf, info);
+                }
             }
         }
         mCodec.releaseOutputBuffer(bufferIndex, false);
diff --git a/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp b/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
index bca05e5..ff3d77f 100644
--- a/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
+++ b/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
@@ -85,7 +85,7 @@
 
     bool testSimpleEncode(const char* encoder, const char* decoder, const char* srcPath,
                           const char* srcMediaType, const char* muxOutPath, int colorFormat,
-                          bool usePersistentSurface);
+                          bool usePersistentSurface, int frameLimit);
 };
 
 CodecEncoderSurfaceTest::CodecEncoderSurfaceTest(const char* mediaType, const char* cfgParams,
@@ -339,8 +339,10 @@
                 mMuxTrackID = AMediaMuxer_addTrack(mMuxer, AMediaCodec_getOutputFormat(mEncoder));
                 RETURN_IF_FAIL(AMediaMuxer_start(mMuxer), "AMediaMuxer_start failed")
             }
-            RETURN_IF_FAIL(AMediaMuxer_writeSampleData(mMuxer, mMuxTrackID, buf, info),
-                           "AMediaMuxer_writeSampleData failed")
+            if ((info->flags & AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                RETURN_IF_FAIL(AMediaMuxer_writeSampleData(mMuxer, mMuxTrackID, buf, info),
+                                "AMediaMuxer_writeSampleData failed")
+            }
         }
         if ((info->flags & AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) == 0) {
             mOutputBuff->saveOutPTS(info->presentationTimeUs);
@@ -557,7 +559,7 @@
 bool CodecEncoderSurfaceTest::testSimpleEncode(const char* encoder, const char* decoder,
                                                const char* srcPath, const char *srcMediaType,
                                                const char* muxOutPath, int colorFormat,
-                                               bool usePersistentSurface) {
+                                               bool usePersistentSurface, int frameLimit) {
     RETURN_IF_FALSE(setUpExtractor(srcPath, srcMediaType, colorFormat),
                     std::string{"setUpExtractor failed"})
     bool muxOutput = muxOutPath != nullptr;
@@ -596,7 +598,7 @@
         if (!configureCodec(isAsync, false, usePersistentSurface)) return false;
         RETURN_IF_FAIL(AMediaCodec_start(mEncoder), "Encoder AMediaCodec_start failed")
         RETURN_IF_FAIL(AMediaCodec_start(mDecoder), "Decoder AMediaCodec_start failed")
-        if (!doWork(INT32_MAX)) return false;
+        if (!doWork(frameLimit)) return false;
         if (!queueEOS()) return false;
         if (!waitForAllEncoderOutputs()) return false;
         if (muxOutput) {
@@ -654,7 +656,8 @@
                                        jstring jMediaType, jstring jtestFile,
                                        jstring jTestFileMediaType, jstring jmuxFile,
                                        jint jColorFormat, jboolean jUsePersistentSurface,
-                                       jstring jCfgParams, jstring jSeparator, jobject jRetMsg) {
+                                       jstring jCfgParams, jstring jSeparator, jobject jRetMsg,
+                                       jint jFrameLimit) {
     const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
@@ -666,7 +669,8 @@
     auto codecEncoderSurfaceTest = new CodecEncoderSurfaceTest(cMediaType, cCfgParams, cSeparator);
     bool isPass = codecEncoderSurfaceTest->testSimpleEncode(cEncoder, cDecoder, cTestFile,
                                                             cTestFileMediaType, cMuxFile,
-                                                            jColorFormat, jUsePersistentSurface);
+                                                            jColorFormat, jUsePersistentSurface,
+                                                            jFrameLimit);
     std::string msg = isPass ? std::string{} : codecEncoderSurfaceTest->getErrorMsg();
     delete codecEncoderSurfaceTest;
     jclass clazz = env->GetObjectClass(jRetMsg);
@@ -690,7 +694,7 @@
             {"nativeTestSimpleEncode",
              "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
              "String;Ljava/lang/String;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/"
-             "StringBuilder;)Z",
+             "StringBuilder;I)Z",
              (void*)nativeTestSimpleEncode},
     };
     jclass c = env->FindClass("android/mediav2/cts/CodecEncoderSurfaceTest");
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderBlockModelMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderBlockModelMultiAccessUnitTest.java
index b726edb..cc6c95f 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderBlockModelMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderBlockModelMultiAccessUnitTest.java
@@ -18,9 +18,10 @@
 
 import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_MultipleFrames;
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
+import static android.mediav2.cts.CodecDecoderMultiAccessUnitTest.RECONFIG_FILE_MEDIA_TYPE_MAP;
+import static android.mediav2.cts.CodecDecoderMultiAccessUnitTest.exhaustiveArgsList;
 
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.media.MediaCodec;
 import android.media.MediaExtractor;
@@ -47,11 +48,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * Tests audio decoders support for feature MultipleFrames in block model mode.
@@ -75,7 +72,6 @@
     private static final String LOG_TAG =
             CodecDecoderBlockModelMultiAccessUnitTest.class.getSimpleName();
     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
-    private static final Map<String, String> RECONFIG_FILE_MEDIA_TYPE_MAP = new HashMap<>();
     private static final int[][] OUT_SIZE_IN_MS = {
             {1000, 250},  // max out size, threshold batch out size
             {1000, 100},
@@ -84,255 +80,12 @@
             {40, 100}
     };
 
-    static {
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_16kHz.wav");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_MPEG,
-                "bbb_1ch_8kHz_lame_cbr.mp3");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AMR_WB,
-                "bbb_1ch_16kHz_16kbps_amrwb.3gp");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AMR_NB,
-                "bbb_1ch_8kHz_10kbps_amrnb.3gp");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_16kHz_flac.mka");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_G711_ALAW,
-                "bbb_1ch_8kHz_alaw.wav");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_G711_MLAW,
-                "bbb_1ch_8kHz_mulaw.wav");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_VORBIS,
-                "bbb_1ch_16kHz_vorbis.mka");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_1ch_16kHz_aac.mp4");
-    }
-
     private final String mReconfigFile;
 
     @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
-        final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_2ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_8kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_22kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_24kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_32kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_8kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_22kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_24kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_32kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_96kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_96kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/sd_2ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s32le.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s24le.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_176kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_192kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_176kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_192kHz.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_vbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_16kHz_lame_vbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_crc.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_192kbps_mp3.mp3"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_16kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_23kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_10kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_8kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"},
-
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_16kHz_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_2ch_44kHz_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_8kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_12kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_16kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_22kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_24kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_32kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_44kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_48kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_8kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_12kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_16kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_22kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_24kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_32kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_44kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_48kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_96kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_176kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_192kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_96kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_176kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_192kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/sd_2ch_48kHz_lvl4_flac.mka"},
-
-                {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_2ch_8kHz_alaw.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_2ch_8kHz_mulaw.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_1ch_16kHz_vorbis.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_2ch_44kHz_vorbis.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_8kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_12kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_16kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_24kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_32kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_48kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_8kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_12kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_16kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_24kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_32kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_48kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/highres_1ch_96kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/highres_2ch_96kHz_q10_vorbis.ogg"},
-
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_1ch_48kHz_opus.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_48kHz_opus.ogg"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_1ch_16kHz_aac.mp4"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_2ch_44kHz_aac.mp4"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_48kHz_aac_lc.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_48kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_48kHz_aac_he.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_hev2.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_eld.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_8kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_8kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_usac.m4a"},
-        }));
-        return prepareParamList(exhaustiveArgsList, false, true, false, true);
+        return prepareParamList(exhaustiveArgsList, false, true, false, true, ComponentClass.ALL,
+                new String[]{FEATURE_MultipleFrames});
     }
 
     public CodecDecoderBlockModelMultiAccessUnitTest(String decoder, String mediaType,
@@ -365,9 +118,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecode() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
         CodecDecoderTestBase cdtb = new CodecDecoderTestBase(mCodecName, mMediaType, null,
                 mAllTestParams);
         cdtb.decodeToMemory(mTestFile, mCodecName, 0, MediaExtractor.SEEK_TO_CLOSEST_SYNC,
@@ -394,10 +144,10 @@
         for (int[] outSizeInMs : OUT_SIZE_IN_MS) {
             configureKeysForLargeAudioBlockModelFrameMode(format, maxSampleSize, outSizeInMs[0],
                     outSizeInMs[1]);
-            for (boolean eosType : boolStates) {
-                mOutputBuff = eosType ? testA : testB;
+            for (boolean signalEosWithLastFrame : boolStates) {
+                mOutputBuff = signalEosWithLastFrame ? testA : testB;
                 mOutputBuff.reset();
-                configureCodec(format, true, eosType, false);
+                configureCodec(format, true, signalEosWithLastFrame, false);
                 mMaxInputLimitMs = outSizeInMs[0];
                 mCodec.start();
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
@@ -449,9 +199,6 @@
     @Ignore("TODO(b/147576107)")
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlush() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
         MediaFormat format = setUpSource(mTestFile);
         final long pts = 250000;
         mExtractor.release();
@@ -551,11 +298,7 @@
             "android.media.MediaCodec#configure"})
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void testReconfigure() throws IOException,
-            InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
+    public void testReconfigure() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
         MediaFormat newFormat = setUpSource(mReconfigFile);
@@ -649,5 +392,4 @@
         mExtractor.release();
         mCodec.release();
     }
-
 }
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderMultiAccessUnitTest.java
index 3dae33f..a39deab 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderMultiAccessUnitTest.java
@@ -20,7 +20,6 @@
 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
 
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.media.MediaCodec;
 import android.media.MediaExtractor;
@@ -72,7 +71,6 @@
 public class CodecDecoderMultiAccessUnitTest extends CodecDecoderMultiAccessUnitTestBase {
     private static final String LOG_TAG = CodecDecoderMultiAccessUnitTest.class.getSimpleName();
     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
-    private static final Map<String, String> RECONFIG_FILE_MEDIA_TYPE_MAP = new HashMap<>();
     private static final int[][] OUT_SIZE_IN_MS = {
             {1000, 250},  // max out size, threshold batch out size
             {1000, 100},
@@ -80,256 +78,92 @@
             {100, 100},
             {40, 100}
     };
+    static final Map<String, String> RECONFIG_FILE_MEDIA_TYPE_MAP = new HashMap<>();
 
     static {
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_16kHz.wav");
+        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_24kHz.wav");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_MPEG,
-                "bbb_1ch_8kHz_lame_cbr.mp3");
+                "bbb_2ch_44kHz_lame_crc.mp3");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AMR_WB,
-                "bbb_1ch_16kHz_16kbps_amrwb.3gp");
+                "audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AMR_NB,
-                "bbb_1ch_8kHz_10kbps_amrnb.3gp");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_16kHz_flac.mka");
+                "audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp");
+        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_FLAC,
+                "audio/bbb_1ch_32kHz_lvl4_flac.mka");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_G711_ALAW,
                 "bbb_1ch_8kHz_alaw.wav");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_G711_MLAW,
                 "bbb_1ch_8kHz_mulaw.wav");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav");
         RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_VORBIS,
-                "bbb_1ch_16kHz_vorbis.mka");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka");
-        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_1ch_16kHz_aac.mp4");
+                "audio/bbb_1ch_32kHz_q10_vorbis.ogg");
+        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_OPUS,
+                "audio/bbb_1ch_32kHz_opus.ogg");
+        RECONFIG_FILE_MEDIA_TYPE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC,
+                "audio/bbb_1ch_32kHz_aac_lc.m4a");
     }
 
+    static final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_8kHz.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_16kHz.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_44kHz.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_48kHz.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/sd_2ch_48kHz.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s32le.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s24le.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_192kHz.wav"},
+
+            {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3"},
+            {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_16kHz_lame_vbr.mp3"},
+            {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3"},
+            {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_192kbps_mp3.mp3"},
+
+            {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"},
+            {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"},
+
+            {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
+            {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"},
+
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_8kHz_lvl4_flac.mka"},
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_16kHz_lvl4_flac.mka"},
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_44kHz_lvl4_flac.mka"},
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_48kHz_lvl4_flac.mka"},
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/sd_2ch_48kHz_lvl4_flac.mka"},
+            {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_192kHz_lvl4_flac.mka"},
+
+            {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_2ch_8kHz_alaw.wav"},
+
+            {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav"},
+            {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_2ch_8kHz_mulaw.wav"},
+
+            {MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav"},
+
+            {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_8kHz_q10_vorbis.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_16kHz_q10_vorbis.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_48kHz_q10_vorbis.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/highres_2ch_96kHz_q10_vorbis.ogg"},
+
+            {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_8kHz_opus.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_16kHz_opus.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_48kHz_opus.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_48kHz_opus.ogg"},
+            {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_48kHz_opus.ogg"},
+
+            {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_8kHz_aac_lc.m4a"},
+            {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_aac_lc.m4a"},
+            {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_lc.m4a"},
+            {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_48kHz_aac_lc.m4a"},
+            {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_48kHz_aac_lc.m4a"},
+    }));
+
+
     private final String mReconfigFile;
 
     @Parameterized.Parameters(name = "{index}_{0}_{1}")
     public static Collection<Object[]> input() {
-        final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_2ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_8kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_22kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_24kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_32kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_1ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_8kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_16kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_22kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_24kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_32kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_44kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bbb_2ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_96kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_96kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/sd_2ch_48kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s32le.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/bellezza_2ch_48kHz_s24le.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_176kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_1ch_192kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_176kHz.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, "audio/highres_2ch_192kHz.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_vbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_16kHz_lame_vbr.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_crc.mp3"},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_192kbps_mp3.mp3"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_16kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_23kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_10kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_8kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"},
-
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_16kHz_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_2ch_44kHz_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_8kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_12kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_16kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_22kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_24kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_32kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_44kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_1ch_48kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_8kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_12kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_16kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_22kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_24kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_32kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_44kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/bbb_2ch_48kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_96kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_176kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_1ch_192kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_96kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_176kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/highres_2ch_192kHz_lvl4_flac.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, "audio/sd_2ch_48kHz_lvl4_flac.mka"},
-
-                {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_2ch_8kHz_alaw.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav"},
-                {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_2ch_8kHz_mulaw.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav"},
-
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_1ch_16kHz_vorbis.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_2ch_44kHz_vorbis.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_8kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_12kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_16kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_24kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_32kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_1ch_48kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_8kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_12kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_16kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_24kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_32kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/bbb_2ch_48kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/highres_1ch_96kHz_q10_vorbis.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_VORBIS, "audio/highres_2ch_96kHz_q10_vorbis.ogg"},
-
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_1ch_48kHz_opus.mka"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_1ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_2ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_5ch_48kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_8kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_12kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_16kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_24kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_32kHz_opus.ogg"},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, "audio/bbb_6ch_48kHz_opus.ogg"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_1ch_16kHz_aac.mp4"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_2ch_44kHz_aac.mp4"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_48kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_8kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_12kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_16kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_22kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_24kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_32kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_44kHz_aac_lc.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_48kHz_aac_lc.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_5ch_48kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_16kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_22kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_24kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_32kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_44kHz_aac_he.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_6ch_48kHz_aac_he.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_hev2.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_hev2.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_aac_eld.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_aac_eld.m4a"},
-
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_8kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_16kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_22kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_24kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_32kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_44kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_1ch_48kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_8kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_16kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_22kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_24kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_32kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_44kHz_usac.m4a"},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, "audio/bbb_2ch_48kHz_usac.m4a"},
-        }));
-        return prepareParamList(exhaustiveArgsList, false, true, false, true);
+        return prepareParamList(exhaustiveArgsList, false, true, false, true, ComponentClass.ALL,
+                new String[]{FEATURE_MultipleFrames});
     }
 
     public CodecDecoderMultiAccessUnitTest(String decoder, String mediaType, String testFile,
@@ -364,9 +198,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecode() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
         CodecDecoderTestBase cdtb = new CodecDecoderTestBase(mCodecName, mMediaType, null,
                 mAllTestParams);
         cdtb.decodeToMemory(mTestFile, mCodecName, 0, MediaExtractor.SEEK_TO_CLOSEST_SYNC,
@@ -383,10 +214,10 @@
         for (int[] outSizeInMs : OUT_SIZE_IN_MS) {
             configureKeysForLargeAudioFrameMode(format, maxSampleSize, outSizeInMs[0],
                     outSizeInMs[1]);
-            for (boolean eosType : boolStates) {
-                mOutputBuff = eosType ? testA : testB;
+            for (boolean signalEosWithLastFrame : boolStates) {
+                mOutputBuff = signalEosWithLastFrame ? testA : testB;
                 mOutputBuff.reset();
-                configureCodec(format, true, eosType, false);
+                configureCodec(format, true, signalEosWithLastFrame, false);
                 mMaxInputLimitMs = outSizeInMs[0];
                 mCodec.start();
                 mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
@@ -440,8 +271,6 @@
     @Ignore("TODO(b/147576107)")
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testFlush() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
         MediaFormat format = setUpSource(mTestFile);
         final long pts = 250000;
         mExtractor.release();
@@ -559,9 +388,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testReconfigure() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
         MediaFormat newFormat = setUpSource(mReconfigFile);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
index 5f57dc7..acdbdae 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderBlockModelMultiAccessUnitTest.java
@@ -25,7 +25,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.media.AudioFormat;
 import android.media.MediaCodec;
@@ -96,28 +95,35 @@
     @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
-                // mediaType, arrays of bit-rates, sample rates, channel counts, pcm encoding
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000, 128000}, new int[]{8000, 12000,
-                        16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000, 128000}, new int[]{8000, 12000,
-                        16000, 24000, 48000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 5150, 5900, 6700, 7400, 7950,
-                        10200, 12200}, new int[]{8000}, new int[]{1},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 8850, 12650, 14250, 15850,
-                        18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
-                        new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
-                        new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_FLOAT},
+                // mediaType, arrays of bit-rates, sample rate, channel counts, pcm encoding
+
+                // mono testing @ common sample rates, pcm encoding
+                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 12200}, new int[]{8000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 23850}, new int[]{16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_FLOAT},
+
+                // stereo testing @ common sample rates, pcm encoding
+                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{128000}, new int[]{44100, 48000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{128000}, new int[]{48000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_FLOAT},
         }));
         List<Object[]> argsList = flattenParams(defArgsList);
-        return prepareParamList(argsList, true, true, false, true);
+        return prepareParamList(argsList, true, true, false, true, ComponentClass.ALL,
+                new String[]{FEATURE_MultipleFrames});
     }
 
     public CodecEncoderBlockModelMultiAccessUnitTest(String encoder, String mediaType,
@@ -297,11 +303,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleEncode() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-        assumeTrue(mCodecName + " is not compatible with LinearBlocks",
-                MediaCodec.LinearBlock.isCodecCopyFreeCompatible(new String[]{mCodecName}));
-
         CodecEncoderTestBase referenceBase = new CodecEncoderTestBase(mCodecName, mMediaType,
                 new EncoderConfigParams[]{mActiveEncCfg}, mAllTestParams);
         referenceBase.encodeToMemory(mCodecName, mActiveEncCfg, mActiveRawRes, Integer.MAX_VALUE,
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
index ed55b72..600e73a 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderMultiAccessUnitTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import android.media.AudioFormat;
 import android.media.MediaCodec;
@@ -93,28 +92,35 @@
     @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
     public static Collection<Object[]> input() {
         List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
-                // mediaType, arrays of bit-rates, sample rates, channel counts, pcm encoding
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000, 128000}, new int[]{8000, 12000,
-                        16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000, 128000}, new int[]{8000, 12000,
-                        16000, 24000, 48000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 5150, 5900, 6700, 7400, 7950,
-                        10200, 12200}, new int[]{8000}, new int[]{1},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 8850, 12650, 14250, 15850,
-                        18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
-                        new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_16BIT},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8},
-                        new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        AudioFormat.ENCODING_PCM_FLOAT},
+                // mediaType, arrays of bit-rates, sample rate, channel counts, pcm encoding
+
+                // mono testing @ common sample rates, pcm encoding
+                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 12200}, new int[]{8000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 23850}, new int[]{16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{8000, 16000},
+                        new int[]{1}, AudioFormat.ENCODING_PCM_FLOAT},
+
+                // stereo testing @ common sample rates, pcm encoding
+                {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{128000}, new int[]{44100, 48000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{128000}, new int[]{48000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_16BIT},
+                {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{0, 7}, new int[]{48000, 192000},
+                        new int[]{2}, AudioFormat.ENCODING_PCM_FLOAT},
         }));
         List<Object[]> argsList = flattenParams(defArgsList);
-        return prepareParamList(argsList, true, true, false, true);
+        return prepareParamList(argsList, true, true, false, true, ComponentClass.ALL,
+                new String[]{FEATURE_MultipleFrames});
     }
 
     public CodecEncoderMultiAccessUnitTest(String encoder, String mediaType,
@@ -191,7 +197,9 @@
                         mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
                         mMuxer.start();
                     }
-                    mMuxer.writeSampleData(mTrackID, buf, info);
+                    if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+                        mMuxer.writeSampleData(mTrackID, buf, info);
+                    }
                 }
             }
             totalSize += info.size;
@@ -285,9 +293,6 @@
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleEncode() throws IOException, InterruptedException {
-        assumeTrue(mCodecName + " does not support FEATURE_MultipleFrames",
-                isFeatureSupported(mCodecName, mMediaType, FEATURE_MultipleFrames));
-
         CodecEncoderTestBase cetb = new CodecEncoderTestBase(mCodecName, mMediaType,
                 new EncoderConfigParams[]{mActiveEncCfg}, mAllTestParams);
         cetb.encodeToMemory(mCodecName, mActiveEncCfg, mActiveRawRes, Integer.MAX_VALUE, true,
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index 3fb93cc..59705c8 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -83,6 +83,7 @@
 public class CodecEncoderSurfaceTest extends CodecEncoderSurfaceTestBase {
     private static final String LOG_TAG = CodecEncoderSurfaceTest.class.getSimpleName();
     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
+    private final int mFrameLimit;
 
     private final ArrayList<String> mTmpFiles = new ArrayList<>();
 
@@ -99,6 +100,7 @@
             @SuppressWarnings("unused") String testLabel, String allTestParams) {
         super(encoder, mediaType, decoder, testFileMediaType, MEDIA_DIR + testFile, encCfgParams,
                 colorFormat, isOutputToneMapped, usePersistentSurface, allTestParams);
+        mFrameLimit = Math.max(encCfgParams.mFrameRate, 30);
     }
 
     private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
@@ -320,7 +322,7 @@
                 mTmpFiles.add(tmpPath);
             }
             encodeToMemory(isAsync, false, saveToMem, (count == 0 ? ref : test), muxOutput,
-                    tmpPath);
+                    tmpPath, mFrameLimit);
             // TODO:(b/149027258) Remove false once output is validated across runs
             if (false) {
                 if (count != 0 && !ref.equals(test)) {
@@ -340,7 +342,8 @@
 
     private native boolean nativeTestSimpleEncode(String encoder, String decoder, String mediaType,
             String testFile, String testFileMediaType, String muxFile, int colorFormat,
-            boolean usePersistentSurface, String cfgParams, String separator, StringBuilder retMsg);
+            boolean usePersistentSurface, String cfgParams, String separator, StringBuilder retMsg,
+            int frameLimit);
 
     /**
      * Test is similar to {@link #testSimpleEncodeFromSurface()} but uses ndk api
@@ -363,7 +366,7 @@
         boolean isPass = nativeTestSimpleEncode(mEncoderName, mDecoderName, mEncMediaType,
                 mTestFile, mTestFileMediaType, tmpPath, colorFormat, mUsePersistentSurface,
                 EncoderConfigParams.serializeMediaFormat(mEncoderFormat),
-                EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+                EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig, mFrameLimit);
         assertTrue(mTestConfig.toString(), isPass);
         if (tmpPath != null) {
             if (mEncCfgParams.mInputBitDepth > 8 && !VNDK_IS_AT_LEAST_T) return;
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index e330006..4ba9d32 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -329,7 +329,7 @@
 
     /**
      * Components advertising support for compression technologies that were introduced after 2002
-     * must support a smallest width/height alignment allowed by the video standard.
+     * must support 1x1 alignment for vp8, av1 and 2x2 for avc, hevc and vp9.
      */
     @VsrTest(requirements = {"VSR-4.2-004.001"})
     @Test
@@ -348,13 +348,13 @@
         switch (mMediaType) {
             case MediaFormat.MIMETYPE_VIDEO_AVC:
             case MediaFormat.MIMETYPE_VIDEO_HEVC:
+            case MediaFormat.MIMETYPE_VIDEO_VP9:
                 assertTrue(mCodecName + ", width alignment = " + widthAlignment
                         + " should be <= 2 ", widthAlignment <= 2);
                 assertTrue(mCodecName + ", height alignment = " + heightAlignment
                         + " should be <= 2 ", heightAlignment <= 2);
                 break;
             case MediaFormat.MIMETYPE_VIDEO_VP8:
-            case MediaFormat.MIMETYPE_VIDEO_VP9:
             case MediaFormat.MIMETYPE_VIDEO_AV1:
                 assertEquals(mCodecName + ", width alignment = " + widthAlignment
                         + "  should be equal to 1 ", 1, widthAlignment);
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 697618e..b883153 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -62,12 +62,14 @@
 @RunWith(Parameterized.class)
 public class VideoEncoderTest extends CodecEncoderTestBase {
     private final SupportClass mSupportRequirements;
+    private final int mFrameLimit;
 
     public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
             SupportClass supportRequirements, @SuppressWarnings("unused") String testLabel,
             String allTestParams) {
         super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
         mSupportRequirements = supportRequirements;
+        mFrameLimit = Math.max(encCfgParams.mFrameRate, 30);
     }
 
     private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
@@ -272,7 +274,7 @@
         if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
             muxOutput = false;
         }
-        encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, muxOutput);
+        encodeToMemory(mCodecName, mEncCfgParams[0], res, mFrameLimit, false, muxOutput);
 
         // validate output
         if (muxOutput) {
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 0eb0d58..bac06fa 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -379,30 +379,6 @@
         }
 
         /**
-         * [2.2.7.1/5.1/H-1-7] MUST have a codec initialization latency of 65(R) / 50(S) / 40(T)
-         * ms or less for a 1080p or smaller video encoding session for all hardware video
-         * encoders when under load. Load here is defined as a concurrent 1080p to 720p
-         * video-only transcoding session using hardware video codecs together with the 1080p
-         * audio-video recording initialization. For Dolby vision codec, the codec initialization
-         * latency MUST be 50 ms or less.
-         */
-        public static CodecInitLatencyRequirement createR5_1__H_1_7(String mediaType) {
-            long latency = mediaType.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION) ? 50L : 40L;
-            RequiredMeasurement<Long> codec_init_latency =
-                RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY)
-                        .setPredicate(RequirementConstants.LONG_LTE)
-                        .addRequiredValue(Build.VERSION_CODES.R, 65L)
-                        .addRequiredValue(Build.VERSION_CODES.S, 50L)
-                        .addRequiredValue(Build.VERSION_CODES.TIRAMISU, latency)
-                        .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, latency)
-                        .addRequiredValue(Build.VERSION_CODES.VANILLA_ICE_CREAM, latency)
-                        .build();
-
-            return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_7,
-                codec_init_latency);
-        }
-
-        /**
          * [2.2.7.1/5.1/H-1-12] Codec initialization latency of 40ms or less for a 1080p or
          * smaller video decoding session for all hardware video encoders when under load. Load
          * here is defined as a concurrent 1080p to 720p video-only transcoding session using
@@ -2281,10 +2257,6 @@
         return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_6_4k());
     }
 
-    public CodecInitLatencyRequirement addR5_1__H_1_7(String mediaType) {
-        return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7(mediaType));
-    }
-
     public ConcurrentCodecRequirement addR5_1__H_1_9_1080p() {
         return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_9_1080p());
     }
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl b/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
index 66e8081..b2794b9 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Requirements.java.tmpl
@@ -1,3 +1,83 @@
+{{- /*
+ * CompMethod generates comparison method constant from a RequiredMeasurement
+ */}}
+{{- define "CompMethod" -}}
+    {{- $c :=.GetComparison }}
+    {{- $mt :=.GetMeasurementType }}
+    {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}BOOLEAN
+    {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}DOUBLE
+    {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}INTEGER
+    {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}STRING
+    {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}LONG
+    {{- else }}{{$mt}}
+    {{- end }}_
+    {{- if eq $c.String "COMPARISON_EQUAL" -}}EQ
+    {{- else if eq $c.String "COMPARISON_LESS_THAN" -}}LT
+    {{- else if eq $c.String "COMPARISON_LESS_THAN_OR_EQUAL" -}}LTE
+    {{- else if eq $c.String "COMPARISON_GREATER_THAN" -}}GTE
+    {{- else if eq $c.String "COMPARISON_GREATER_THAN_OR_EQUAL" -}}GTE
+    {{- else if eq $c.String "COMPARISON_INFO_ONLY" -}}INFO
+    {{- else }}{{$c}}
+    {{- end }}
+{{- end -}}
+
+
+{{- /*
+ * JavaClass generates Java class name from a MeasurementType
+ */}}
+{{- define "JavaClass" -}}
+    {{- if eq .String "MEASUREMENT_TYPE_BOOL" -}}Boolean
+    {{- else if eq .String "MEASUREMENT_TYPE_DOUBLE" -}}Double
+    {{- else if eq .String "MEASUREMENT_TYPE_INT" -}}Integer
+    {{- else if eq .String "MEASUREMENT_TYPE_STRING" -}}String
+    {{- else if eq .String "MEASUREMENT_TYPE_LONG" -}}Long
+    {{- else }}{{.}}
+    {{- end }}
+{{- end -}}
+
+{{- /*
+ * JavaClass generates Java type from a MeasurementType
+ */}}
+{{- define "JavaType" -}}
+    {{- if eq .String "MEASUREMENT_TYPE_BOOL" -}}boolean
+    {{- else if eq .String "MEASUREMENT_TYPE_DOUBLE" -}}double
+    {{- else if eq .String "MEASUREMENT_TYPE_INT" -}}int
+    {{- else if eq .String "MEASUREMENT_TYPE_STRING" -}}String
+    {{- else if eq .String "MEASUREMENT_TYPE_LONG" -}}long
+    {{- else }}{{.}}
+    {{- end }}
+{{- end -}}
+
+{{- /*
+ * VersionCode generates the android.Build VersionCode constant from an mpc value.
+ * It is an error if the mpc value listed here.
+ */}}
+{{- define "VersionCode" -}}
+    VERSION_CODES.
+    {{- if  eq . 30}}R
+    {{- else if eq . 31}}S
+    {{- else if eq . 33}}TIRAMISU
+    {{- else if eq . 34}}UPSIDE_DOWN_CAKE
+    {{- else if eq . 35}}VANILLA_ICE_CREAM
+    {{- else }}{{.}}
+    {{- end }}
+{{- end -}}
+
+
+{{- /*
+ * MeasurementValue gets value from RequiredValue base on the MeasurementType
+ * It is an error if the MeasurementType is not listed here.
+ */}}
+{{- define "MeasurementValue" -}}
+    {{- if eq .MeasurementType.String "MEASUREMENT_TYPE_BOOL" -}}{{.RequiredValue.GetBoolValue}}
+    {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_DOUBLE" -}}{{printf "%f" .RequiredValue.GetDoubleValue}}
+    {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_INT" -}}{{.RequiredValue.GetIntValue}}
+    {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_STRING" -}}"{{.RequiredValue.GetStringValue}}"
+    {{- else if eq .MeasurementType.String "MEASUREMENT_TYPE_LONG" -}}{{.RequiredValue.GetLongValue}}L
+    {{- else }}{{.MeasurementType}}
+    {{- end }}
+{{- end -}}
+
 /*
  * Copyright (C) 2024 The Android Open Source Project
  *
@@ -35,7 +115,25 @@
     public static {{UpperCamelCase $r.GetName}}Requirement add{{ SafeReqID $r.GetId | UpperCase}}(
            PerformanceClassEvaluator pce) {
         return pce.addRequirement({{UpperCamelCase $r.GetName}}Requirement.create());
-     }
+    }
+
+    {{- range $v_id, $v := $r.GetVariants }}
+
+    /**
+      * Add a new {{UpperCamelCase $r.GetName}}Requirement for requirement {{ $r.GetId }}
+      * to a {@code PerformanceClassEvaluator} instance
+      * {{$v.GetDescription}}.
+      {{- with $r.GetDescription}}
+      *
+      * {{.}}{{end}}
+      */
+    public static {{UpperCamelCase $r.GetName}}Requirement add{{ SafeReqID $r.GetId | UpperCase}}
+              {{- UpperCamelCase $v_id}}(
+           PerformanceClassEvaluator pce) {
+        return pce.addRequirement({{UpperCamelCase $r.GetName}}Requirement.create
+            {{- UpperCamelCase $v_id}}());
+    }
+    {{- end }}{{/* range $v_id, $v */}}
 
     /**
       * {{ $r.GetId }} {{$r.GetName}}
@@ -56,82 +154,72 @@
             {{- $mt := $m.GetMeasurementType}}
             {{- $c := $m.GetComparison}}
             var {{LowerCamelCase $m_id}} = RequiredMeasurement
-                    .<
-                        {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}Boolean
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}Double
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}Integer
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}String
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}Long
-                        {{- else }}{{$mt}}
-                        {{- end }}>builder()
+                    .<{{template "JavaClass" $mt}}>builder()
                     .setId("{{$m_id}}")
-                    .setPredicate(RequirementConstants.
-                        {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}BOOLEAN
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}DOUBLE
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}INTEGER
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}STRING
-                        {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}LONG
-                        {{- else }}{{$mt}}
-                        {{- end }}_
-                        {{- if eq $c.String "COMPARISON_EQUAL" -}}EQ
-                        {{- else if eq $c.String "COMPARISON_LESS_THAN" -}}LT
-                        {{- else if eq $c.String "COMPARISON_LESS_THAN_OR_EQUAL" -}}LTE
-                        {{- else if eq $c.String "COMPARISON_GREATER_THAN" -}}GTE
-                        {{- else if eq $c.String "COMPARISON_GREATER_THAN_OR_EQUAL" -}}GTE
-                        {{- else if eq $c.String "COMPARISON_INFO_ONLY" -}}INFO
-                        {{- else }}{{$c}}
-                        {{- end }})
+                    .setPredicate(RequirementConstants.{{template "CompMethod" $m}})
                     {{- range $mpc, $s := $r.GetSpecs }}
                     {{- with index $s.GetRequiredValues $m_id}}
-                    .addRequiredValue(VERSION_CODES.
-                       {{- if  eq $mpc 30}}R
-                       {{- else if eq $mpc 31}}S
-                       {{- else if eq $mpc 33}}TIRAMISU
-                       {{- else if eq $mpc 34}}UPSIDE_DOWN_CAKE
-                       {{- else if eq $mpc 35}}VANILLA_ICE_CREAM
-                       {{- else }}{{$mpc}}
-                       {{- end }}
-                       {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}, {{.GetBoolValue}}
-                       {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}, {{printf "%f" .GetDoubleValue}}
-                       {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}, {{.GetIntValue}}
-                       {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}, "{{.GetStringValue}}"
-                       {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}, {{.GetLongValue}}L
-                       {{- else }}{{$mt}}
-                       {{- end }})
+                    .addRequiredValue({{template "VersionCode" $mpc}}, {{template
+                         "MeasurementValue" Dict "RequiredValue" . "MeasurementType" $mt}})
                     {{- end}}
                     {{- end}}
                     .build();
             {{- end }}
-           return new {{UpperCamelCase $r.GetName}}Requirement(
+            return new {{UpperCamelCase $r.GetName}}Requirement(
                     "{{SafeReqID $r.GetId }}"
                     {{- range $m_id, $m := $r.GetMeasurements }},
                     {{LowerCamelCase $m_id}}
                     {{- end}});
         }
 
+        {{- range $v_id, $v := $r.GetVariants }}
+        /**
+          * {{ $r.GetId }} {{$r.GetName}}{{- with $v.GetDescription}} {{.}}{{end}}
+          {{- with $r.GetDescription}}
+          *
+          * {{.}}{{end}}
+          */
+        private static {{UpperCamelCase $r.GetName}}Requirement create{{UpperCamelCase $v_id}}() {
+            {{- range $m_id, $m := $r.GetMeasurements }}
+            {{- $mt := $m.GetMeasurementType}}
+            {{- $c := $m.GetComparison}}
+            var {{LowerCamelCase $m_id}} = RequiredMeasurement
+                    .<{{template "JavaClass" $mt}}>builder()
+                    .setId("{{$m_id}}")
+                    .setPredicate(RequirementConstants.{{template "CompMethod" $m}})
+                    {{- range $mpc, $s := $r.GetSpecs }}
+                    {{- $vs := index $s.GetVariantSpecs $v_id}}
+                    {{- if $vs }}
+                    {{- with index $vs.GetRequiredValues $m_id}}
+                    .addRequiredValue({{template "VersionCode" $mpc}}, {{template
+                         "MeasurementValue" Dict "RequiredValue" . "MeasurementType" $mt}})
+                    {{- end}}{{/* if $vs */}}
+                    {{- end}}{{/* with rv */}}
+                    {{- end}}{{/* range $mpc, $s */}}
+                    .build();
+            {{- end}}{{/* range $m_id, $m */}}
+            return new {{UpperCamelCase $r.GetName}}Requirement(
+                    "{{SafeReqID $r.GetId }}"
+                    {{- range $m_id, $m := $r.GetMeasurements }},
+                    {{LowerCamelCase $m_id}}
+                    {{- end}});
+        }
+        {{- end }}{{/* range $v_id, $v */}}
 
-       {{- range $m_id, $m := $r.GetMeasurements }}
-       {{- $mt := $m.GetMeasurementType}}
-       /** {{$m.GetDescription}} */
-       public void set{{UpperCamelCase $m_id}}(
-         {{- if eq $mt.String "MEASUREMENT_TYPE_BOOL" -}}boolean
-         {{- else if eq $mt.String "MEASUREMENT_TYPE_DOUBLE" -}}double
-         {{- else if eq $mt.String "MEASUREMENT_TYPE_INT" -}}int
-         {{- else if eq $mt.String "MEASUREMENT_TYPE_STRING" -}}String
-         {{- else if eq $mt.String "MEASUREMENT_TYPE_LONG" -}}long
-         {{- else }}{{$mt}}
-         {{- end }} v) {
-           this.setMeasuredValue("{{$m_id}}", v);
-       }
-       {{- end }}{{/* range $m_id, $m */}}
+        {{- range $m_id, $m := $r.GetMeasurements }}
+        {{- $mt := $m.GetMeasurementType}}
+        /** {{$m.GetDescription}} */
+        public void set{{UpperCamelCase $m_id}}({{template "JavaType" $mt}} v) {
+            this.setMeasuredValue("{{$m_id}}", v);
+        }
+        {{- end }}{{/* range $m_id, $m */}}
 
-       private {{UpperCamelCase $r.GetName}}Requirement(String id, RequiredMeasurement<?>... reqs) {
-           super(id, reqs);
-       }
-
+        private {{UpperCamelCase $r.GetName}}Requirement(String id, RequiredMeasurement<?>... reqs) {
+            super(id, reqs);
+        }
     }
 {{- end }} {{/* if $r.GetName */}}
 {{- end }} {{/* range $r */}}
 
-  private Requirements () {}
+    private Requirements () {}
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
index 219b35a..0f795ae 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java
@@ -364,7 +364,13 @@
                 Requirements.addR5_1__H_1_8(pce).setCodecInitializationLatencyMs(
                         initializationLatency);
             } else {
-                pce.addR5_1__H_1_7(mMime).setCodecInitLatencyMs(initializationLatency);
+                if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION)) {
+                    Requirements.addR5_1__H_1_7Dolby(pce).setCodecInitializationLatencyMs(
+                            initializationLatency);
+                } else {
+                    Requirements.addR5_1__H_1_7(pce).setCodecInitializationLatencyMs(
+                            initializationLatency);
+                }
             }
         } else {
             if (isAudio) {
diff --git a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
index bbbd391..0f465e7 100644
--- a/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
@@ -29,7 +29,7 @@
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="class" value="android.signature.cts.api.DebugClassKillswitchTest" />
         <option name="runtime-hint" value="60s" />
-        <option name="shell-timeout" value="45m" />
+        <option name="shell-timeout" value="65m" />
     </test>
 
     <!-- Controller that will skip the module if a native bridge situation is detected -->
diff --git a/tests/signature/api-check/hidden-api-killswitch-sdklist/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-sdklist/AndroidTest.xml
index bcd4bf9..bc43c36 100644
--- a/tests/signature/api-check/hidden-api-killswitch-sdklist/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-sdklist/AndroidTest.xml
@@ -35,7 +35,7 @@
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="class" value="android.signature.cts.api.SdkListKillswitchTest" />
         <option name="runtime-hint" value="60s" />
-        <option name="shell-timeout" value="45m" />
+        <option name="shell-timeout" value="65m" />
     </test>
 
     <!-- Controller that will skip the module if a native bridge situation is detected -->
diff --git a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
index f971b5b..5ca9acd 100644
--- a/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
@@ -35,7 +35,7 @@
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="class" value="android.signature.cts.api.WildcardKillswitchTest" />
         <option name="runtime-hint" value="60s" />
-        <option name="shell-timeout" value="45m" />
+        <option name="shell-timeout" value="65m" />
     </test>
 
     <!-- Controller that will skip the module if a native bridge situation is detected -->
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index ee3903f..b3c26b3 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -44,22 +44,22 @@
     private final static Predicate<DexMember> FIELD_FILTER =
             dexMember -> (dexMember instanceof DexField);
 
-    @Test(timeout = 2400000)
+    @Test(timeout = 3600000)
     public void testKillswitchMechanismMethodsThroughReflection() {
         doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ true, /* jni= */ false);
     }
 
-   @Test(timeout = 2400000)
+   @Test(timeout = 3600000)
     public void testKillswitchMechanismMethodsThroughJni() {
         doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ false, /* jni= */ true);
     }
 
-    @Test(timeout = 2400000)
+    @Test(timeout = 3600000)
     public void testKillswitchMechanismFieldsThroughReflection() {
         doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ true, /* jni= */ false);
     }
 
-   @Test(timeout = 2400000)
+   @Test(timeout = 3600000)
     public void testKillswitchMechanismFieldsThroughJni() {
         doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ false, /* jni= */ true);
     }
diff --git a/tests/tests/attributionsource/src/android/attributionsource/cts/AttributionSourceTest.kt b/tests/tests/attributionsource/src/android/attributionsource/cts/AttributionSourceTest.kt
index 021a02b..c43e921 100644
--- a/tests/tests/attributionsource/src/android/attributionsource/cts/AttributionSourceTest.kt
+++ b/tests/tests/attributionsource/src/android/attributionsource/cts/AttributionSourceTest.kt
@@ -71,7 +71,7 @@
     @Test
     @ApiTest(apis = ["android.content.AttributionSource.Builder#setNextAttributionSource"])
     @Throws(Exception::class)
-    @RequiresFlagsEnabled(Flags.FLAG_ATTRIBUTION_SOURCE_CONSTRUCTOR)
+    @RequiresFlagsEnabled(Flags.FLAG_SET_NEXT_ATTRIBUTION_SOURCE)
     fun testSetNextAttributionSourceWithNull() {
         assertFailsWith(Exception::class, "setNextAttributionSource should throw on null") {
             val nullBuilder = AttributionSource.Builder(Process.myUid())
diff --git a/tests/tests/attributionsource/src/android/attributionsource/cts/RenouncedPermissionsTest.kt b/tests/tests/attributionsource/src/android/attributionsource/cts/RenouncedPermissionsTest.kt
index 5058f8f..a64eb5c 100644
--- a/tests/tests/attributionsource/src/android/attributionsource/cts/RenouncedPermissionsTest.kt
+++ b/tests/tests/attributionsource/src/android/attributionsource/cts/RenouncedPermissionsTest.kt
@@ -22,14 +22,10 @@
 import android.content.Context
 import android.content.ContextParams
 import android.content.pm.PackageManager
-import android.os.Binder
 import android.os.Process
 import android.os.UserHandle
 import android.permission.PermissionManager
-import android.permission.flags.Flags
 import android.platform.test.annotations.AppModeFull
-import android.platform.test.annotations.RequiresFlagsDisabled
-import android.platform.test.annotations.RequiresFlagsEnabled
 import android.platform.test.flag.junit.DeviceFlagsValueProvider
 import android.provider.CalendarContract
 import android.provider.ContactsContract
@@ -91,21 +87,7 @@
     }
 
     @Test(expected = IllegalArgumentException::class)
-    @RequiresFlagsEnabled(Flags.FLAG_ATTRIBUTION_SOURCE_CONSTRUCTOR)
-    fun testCannotRequestRenouncePermissions_attributionSourceConstructorEnabled() {
-        val renouncedPermissions = arrayOf(Manifest.permission.READ_CONTACTS)
-        val attributionSource = AttributionSource(Process.myUid(),
-                Process.myPid(), context.packageName, /*attributionTag*/ null,
-                /*token*/ Binder(), renouncedPermissions, /*next*/ null)
-        val activity = createActivityWithAttributionSource(attributionSource)
-
-        // Requesting renounced permissions throws
-        activity.requestPermissions(arrayOf(Manifest.permission.READ_CONTACTS), 1)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    @RequiresFlagsDisabled(Flags.FLAG_ATTRIBUTION_SOURCE_CONSTRUCTOR)
-    fun testCannotRequestRenouncePermissions_attributionSourceConstructorDisabled() {
+    fun testCannotRequestRenouncePermissions() {
         val renouncedPermissions = arrayOf(Manifest.permission.READ_CONTACTS)
         val attributionSource = AttributionSource(
                 Process.myUid(), context.packageName, null,
diff --git a/tests/tests/bluetooth/AndroidManifest.xml b/tests/tests/bluetooth/AndroidManifest.xml
index c72a503..8a2e1bd 100644
--- a/tests/tests/bluetooth/AndroidManifest.xml
+++ b/tests/tests/bluetooth/AndroidManifest.xml
@@ -20,8 +20,6 @@
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
-    <!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> -->
-    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index 58b6c1d..6adb8db 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -27,6 +27,12 @@
         <option name="test-file-name" value="CtsBluetoothTestCases.apk" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="throw-if-cmd-fail" value="true" />
+        <option name="run-command" value="setprop persist.log.tag.bluetooth VERBOSE" />
+       <!-- In order for the setprop to take effect everywhere, we need to toggle OFF Bluetooth -->
+        <option name="run-command" value="settings put global ble_scan_always_enabled 0"/>
+        <option name="run-command" value="cmd bluetooth_manager disable" />
+        <option name="run-command" value="cmd bluetooth_manager wait-for-state:STATE_OFF" />
         <option name="run-command" value="cmd bluetooth_manager enable" />
         <option name="run-command" value="cmd bluetooth_manager wait-for-state:STATE_ON" />
         <option name="teardown-command" value="cmd bluetooth_manager disable" />
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
index c1a96b6..7f32291 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.BLUETOOTH_CONNECT;
 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -38,6 +39,7 @@
 import android.bluetooth.BluetoothQualityReport;
 import android.bluetooth.BluetoothServerSocket;
 import android.bluetooth.BluetoothStatusCodes;
+import android.bluetooth.test_utils.Permissions;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -416,9 +418,14 @@
         TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
         assertThrows(IllegalArgumentException.class, () -> mAdapter.setDiscoverableTimeout(
                 Duration.ofDays(25000)));
-        assertEquals(BluetoothStatusCodes.SUCCESS,
-                mAdapter.setDiscoverableTimeout(minutes));
-        assertEquals(minutes, mAdapter.getDiscoverableTimeout());
+        Permissions.enforceEachPermissions(
+                () -> mAdapter.setDiscoverableTimeout(minutes),
+                List.of(BLUETOOTH_PRIVILEGED, BLUETOOTH_SCAN));
+        try (var p = Permissions.withPermissions(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED)) {
+            assertEquals(BluetoothStatusCodes.SUCCESS,
+                    mAdapter.setDiscoverableTimeout(minutes));
+            assertEquals(minutes, mAdapter.getDiscoverableTimeout());
+        }
     }
 
     @Test
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
index 693311c..8934395 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
@@ -122,6 +122,8 @@
     @MediumTest
     @Test
     public void basicBleScan() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_SCAN);
         long scanStartMillis = SystemClock.elapsedRealtime();
         Collection<ScanResult> scanResults = scan();
         long scanEndMillis = SystemClock.elapsedRealtime();
@@ -138,6 +140,10 @@
     @MediumTest
     @Test
     public void scanFilter() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        android.Manifest.permission.BLUETOOTH_CONNECT,
+                        android.Manifest.permission.BLUETOOTH_SCAN);
         List<ScanFilter> filters = new ArrayList<ScanFilter>();
         ScanFilter filter = createScanFilter();
         if (filter == null) {
@@ -167,6 +173,7 @@
                 .adoptShellPermissionIdentity(
                         android.Manifest.permission.BLUETOOTH_CONNECT,
                         android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+                        android.Manifest.permission.BLUETOOTH_SCAN,
                         android.Manifest.permission.UPDATE_DEVICE_STATS
                 );
         BleScanCallback filterLeScanCallback = new BleScanCallback();
@@ -188,6 +195,7 @@
                 .adoptShellPermissionIdentity(
                         android.Manifest.permission.BLUETOOTH_CONNECT,
                         android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+                        android.Manifest.permission.BLUETOOTH_SCAN,
                         android.Manifest.permission.UPDATE_DEVICE_STATS
                 );
         BleScanCallback filterLeScanCallback = new BleScanCallback();
@@ -294,6 +302,10 @@
     @Test
     public void batchScan() {
         Assume.assumeTrue(isBleBatchScanSupported());
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        android.Manifest.permission.BLUETOOTH_CONNECT,
+                        android.Manifest.permission.BLUETOOTH_SCAN);
 
         ScanSettings batchScanSettings = new ScanSettings.Builder()
                 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
@@ -325,6 +337,10 @@
     @Test
     public void startScanPendingIntent_nullnull() throws Exception {
         Assume.assumeTrue(isBleBatchScanSupported());
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        android.Manifest.permission.BLUETOOTH_CONNECT,
+                        android.Manifest.permission.BLUETOOTH_SCAN);
 
         Intent broadcastIntent = new Intent();
         broadcastIntent.setClass(mContext, BluetoothScanReceiver.class);
@@ -345,6 +361,10 @@
     @Test
     public void startScanPendingIntent() throws Exception {
         Assume.assumeTrue(isBleBatchScanSupported());
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(
+                        android.Manifest.permission.BLUETOOTH_CONNECT,
+                        android.Manifest.permission.BLUETOOTH_SCAN);
 
         ScanSettings batchScanSettings = new ScanSettings.Builder()
                 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
index 96b0c84..19a3225 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
@@ -20,20 +20,25 @@
 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
 import static android.Manifest.permission.BLUETOOTH_SCAN;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
 
 import android.app.UiAutomation;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothHearingAid.AdvertisementServiceData;
-import android.bluetooth.BluetoothManager;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.test_utils.BlockingBluetoothAdapter;
+import android.bluetooth.test_utils.EnableBluetoothRule;
+import android.bluetooth.test_utils.Permissions;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -45,137 +50,98 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
 import com.android.compatibility.common.util.CddTest;
 
-import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.time.Duration;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 
-/**
- * Unit test cases for {@link BluetoothHearingAid}.
- * <p>
- * To run the test, use adb shell am instrument -e class 'android.bluetooth.HearingAidProfileTest'
- * -w 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
- */
+/** Unit test cases for {@link BluetoothHearingAid}. */
 @RunWith(AndroidJUnit4.class)
 public class HearingAidProfileTest {
-    private static final String TAG = "HearingAidProfileTest";
+    private static final String TAG = HearingAidProfileTest.class.getSimpleName();
 
-    private static final int WAIT_FOR_INTENT_TIMEOUT_MS = 10000; // ms to wait for intent callback
-    private static final int PROXY_CONNECTION_TIMEOUT_MS = 500;  // ms timeout for Proxy Connect
-    // ADAPTER_ENABLE_TIMEOUT_MS = AdapterState.BLE_START_TIMEOUT_DELAY +
-    //                              AdapterState.BREDR_START_TIMEOUT_DELAY
-    private static final int ADAPTER_ENABLE_TIMEOUT_MS = 8000;
-    // ADAPTER_DISABLE_TIMEOUT_MS = AdapterState.BLE_STOP_TIMEOUT_DELAY +
-    //                                  AdapterState.BREDR_STOP_TIMEOUT_DELAY
-    private static final int ADAPTER_DISABLE_TIMEOUT_MS = 5000;
-    private static final String FAKE_REMOTE_ADDRESS = "00:11:22:AA:BB:CC";
+    @ClassRule public static final EnableBluetoothRule sEnableBluetooth = new EnableBluetoothRule();
 
-    private Context mContext;
+    @Rule
+    public final AdoptShellPermissionsRule mPermissionRule =
+            new AdoptShellPermissionsRule(sUiAutomation, BLUETOOTH_CONNECT);
+
+    private static final BluetoothAdapter sBluetoothAdapter = BlockingBluetoothAdapter.getAdapter();
+    private static final Context sContext =
+            InstrumentationRegistry.getInstrumentation().getContext();
+    private static final UiAutomation sUiAutomation =
+            InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+    private static final Duration PROXY_CONNECTION_TIMEOUT = Duration.ofMillis(500);
+    private static final Duration WAIT_FOR_INTENT_TIMEOUT = Duration.ofSeconds(1);
+    private static final BluetoothDevice sFakeDevice =
+            sBluetoothAdapter.getRemoteDevice("42:11:22:AA:BB:CC");
+
+    private static List<Integer> sValidConnectionStates =
+            List.of(
+                    BluetoothProfile.STATE_CONNECTING,
+                    BluetoothProfile.STATE_CONNECTED,
+                    BluetoothProfile.STATE_DISCONNECTED,
+                    BluetoothProfile.STATE_DISCONNECTING);
+
     private BluetoothHearingAid mService;
-    private BluetoothAdapter mBluetoothAdapter;
-    private BroadcastReceiver mIntentReceiver;
-    private UiAutomation mUiAutomation;;
 
-    private Condition mConditionProfileConnection;
-    private ReentrantLock mProfileConnectionlock;
-    private boolean mIsProfileReady;
-    private AdvertisementServiceData mAdvertisementData;
+    private static final AdvertisementServiceData sAdvertisementData;
 
-    private static List<Integer> mValidConnectionStates = new ArrayList<Integer>(
-        Arrays.asList(BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED,
-                      BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING));
-
-    private List<BluetoothDevice> mIntentCallbackDeviceList;
-
-    @Before
-    public void setUp() throws Exception {
-        mContext = InstrumentationRegistry.getInstrumentation().getContext();
-
-        Assume.assumeTrue(TestUtils.isBleSupported(mContext));
-        Assume.assumeTrue(TestUtils.isProfileEnabled(BluetoothProfile.HEARING_AID));
-
-        mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
-
-        BluetoothManager manager = (BluetoothManager) mContext.getSystemService(
-                Context.BLUETOOTH_SERVICE);
-        mBluetoothAdapter = manager.getAdapter();
-
-        assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
-        mProfileConnectionlock = new ReentrantLock();
-        mConditionProfileConnection = mProfileConnectionlock.newCondition();
-        mIsProfileReady = false;
-        mService = null;
-        mBluetoothAdapter.getProfileProxy(mContext, new HearingAidsServiceListener(),
-                BluetoothProfile.HEARING_AID);
-
+    static {
         Parcel parcel = Parcel.obtain();
         parcel.writeInt(0b110); // CSIP supported, MODE_BINAURAL, SIDE_LEFT
         parcel.writeInt(1);
         parcel.setDataPosition(0);
-        mAdvertisementData = AdvertisementServiceData.CREATOR.createFromParcel(parcel);
-        assertNotNull(mAdvertisementData);
+        sAdvertisementData = AdvertisementServiceData.CREATOR.createFromParcel(parcel);
     }
 
-    @After
-    public void tearDown() {
-        if (mUiAutomation != null) {
-            mUiAutomation.dropShellPermissionIdentity();
-        }
+    @Mock BluetoothProfile.ServiceListener mServiceListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Assume.assumeTrue(TestUtils.isBleSupported(sContext));
+        Assume.assumeTrue(TestUtils.isProfileEnabled(BluetoothProfile.HEARING_AID));
+
+        assertThat(
+                        sBluetoothAdapter.getProfileProxy(
+                                sContext, mServiceListener, BluetoothProfile.HEARING_AID))
+                .isTrue();
+
+        ArgumentCaptor<BluetoothProfile> captor = ArgumentCaptor.forClass(BluetoothProfile.class);
+        verify(mServiceListener, timeout(PROXY_CONNECTION_TIMEOUT.toMillis()))
+                .onServiceConnected(eq(BluetoothProfile.HEARING_AID), captor.capture());
+        mService = (BluetoothHearingAid) captor.getValue();
+        assertThat(mService).isNotNull();
     }
 
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @Test
     public void closeProfileProxy() {
-        assertTrue(waitForProfileConnect());
-        assertNotNull(mService);
-        assertTrue(mIsProfileReady);
-
-        mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEARING_AID, mService);
-        assertTrue(waitForProfileDisconnect());
-        assertFalse(mIsProfileReady);
+        sBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEARING_AID, mService);
+        verify(mServiceListener, timeout(PROXY_CONNECTION_TIMEOUT.toMillis()))
+                .onServiceDisconnected(eq(BluetoothProfile.HEARING_AID));
     }
 
-    /**
-     * Basic test case to make sure that Hearing Aid Profile Proxy can connect.
-     */
-    @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
-    @MediumTest
-    @Test
-    public void getProxyServiceConnect() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-    }
-
-    /**
-     * Basic test case to make sure that a fictional device is disconnected.
-     */
+    /** Basic test case to make sure that a fictional device is disconnected. */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getConnectionState() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake device
-        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
-        assertNotNull(device);
-
-        int connectionState = mService.getConnectionState(device);
-        // Fake device should be disconnected
-        assertEquals(connectionState, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mService.getConnectionState(sFakeDevice))
+                .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
     }
 
     /**
@@ -186,74 +152,40 @@
     @MediumTest
     @Test
     public void setVolume() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
         // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
         assertThrows(SecurityException.class, () -> mService.setVolume(42));
     }
 
-    /**
-     * Basic test case to make sure that a fictional device is unknown side.
-     */
+    /** Basic test case to make sure that a fictional device is unknown side. */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getDeviceSide() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake device
-        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
-        assertNotNull(device);
-
-        final int side = mService.getDeviceSide(device);
-        // Fake device should be no value, unknown side
-        assertEquals(BluetoothHearingAid.SIDE_UNKNOWN, side);
+        assertThat(mService.getDeviceSide(sFakeDevice)).isEqualTo(BluetoothHearingAid.SIDE_UNKNOWN);
     }
 
-    /**
-     * Basic test case to make sure that a fictional device is unknown mode.
-     */
+    /** Basic test case to make sure that a fictional device is unknown mode. */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getDeviceMode() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake device
-        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
-        assertNotNull(device);
-
-        final int mode = mService.getDeviceMode(device);
-        // Fake device should be no value, unknown mode
-        assertEquals(BluetoothHearingAid.MODE_UNKNOWN, mode);
+        assertThat(mService.getDeviceMode(sFakeDevice)).isEqualTo(BluetoothHearingAid.MODE_UNKNOWN);
     }
 
     /**
-     * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data
-     * is null.
+     * Basic test case to make sure that a fictional device's ASHA Advertisement Service Data is
+     * null.
      */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getAdvertisementServiceData() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake device
-        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(FAKE_REMOTE_ADDRESS);
-        assertNotNull(device);
-
-        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED);
-
-        // Fake device should have no service data
-        assertNull(mService.getAdvertisementServiceData(device));
+        Permissions.enforceEachPermissions(
+                () -> mService.getAdvertisementServiceData(sFakeDevice),
+                List.of(BLUETOOTH_PRIVILEGED, BLUETOOTH_SCAN));
+        try (var p = Permissions.withPermissions(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED)) {
+            assertThat(mService.getAdvertisementServiceData(sFakeDevice)).isNull();
+        }
     }
 
     /**
@@ -264,16 +196,7 @@
     @MediumTest
     @Test
     public void getAdvertisementDeviceMode() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake advertisement data
-        AdvertisementServiceData data = mAdvertisementData;
-
-        final int mode = data.getDeviceMode();
-        // Fake device should be MODE_BINAURAL
-        assertEquals(BluetoothHearingAid.MODE_BINAURAL, mode);
+        assertThat(sAdvertisementData.getDeviceMode()).isEqualTo(BluetoothHearingAid.MODE_BINAURAL);
     }
 
     /**
@@ -284,37 +207,18 @@
     @MediumTest
     @Test
     public void getAdvertisementDeviceSide() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake advertisement data
-        AdvertisementServiceData data  = mAdvertisementData;
-
-        final int side = data.getDeviceSide();
-        // Fake device should be SIDE_LEFT
-        assertEquals(BluetoothHearingAid.SIDE_LEFT, side);
+        assertThat(sAdvertisementData.getDeviceSide()).isEqualTo(BluetoothHearingAid.SIDE_LEFT);
     }
 
     /**
-     * Basic test case to make sure that a fictional device's truncated HiSyncId is the
-     * expected value.
+     * Basic test case to make sure that a fictional device's truncated HiSyncId is the expected
+     * value.
      */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getTruncatedHiSyncId() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake advertisement data
-        AdvertisementServiceData data = mAdvertisementData;
-        assertNotNull(data);
-
-        final int id = data.getTruncatedHiSyncId();
-        // Fake device should be supported
-        assertEquals(1, id);
+        assertThat(sAdvertisementData.getTruncatedHiSyncId()).isEqualTo(1);
     }
 
     /**
@@ -325,17 +229,7 @@
     @MediumTest
     @Test
     public void isCsipSupported() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake advertisement data
-        AdvertisementServiceData data  = mAdvertisementData;
-        assertNotNull(data);
-
-        final boolean supported = data.isCsipSupported();
-        // Fake device should be supported
-        assertEquals(true, supported);
+        assertThat(sAdvertisementData.isCsipSupported()).isTrue();
     }
 
     /**
@@ -346,14 +240,6 @@
     @MediumTest
     @Test
     public void isLikelyPairOfBluetoothHearingAid() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        // Create a fake advertisement data
-        final AdvertisementServiceData data  = mAdvertisementData;
-        assertNotNull(data);
-
         // Create another fake advertisement data
         Parcel parcel = Parcel.obtain();
         parcel.writeInt(0b111); // CSIP supported, MODE_BINAURAL, SIDE_RIGHT
@@ -361,31 +247,21 @@
         parcel.setDataPosition(0);
         AdvertisementServiceData dataOtherSide =
                 AdvertisementServiceData.CREATOR.createFromParcel(parcel);
-        assertNotNull(dataOtherSide);
+        assertThat(dataOtherSide).isNotNull();
 
-        final boolean isLikelyPair = data.isInPairWith(dataOtherSide);
         // two devices should be a pair
-        assertEquals(true, isLikelyPair);
+        assertThat(sAdvertisementData.isInPairWith(dataOtherSide)).isTrue();
     }
 
-    /**
-     * Basic test case to get the list of connected Hearing Aid devices.
-     */
+    /** Basic test case to get the list of connected Hearing Aid devices. */
     @CddTest(requirements = {"7.4.3/C-2-1", "7.4.3/C-3-2"})
     @MediumTest
     @Test
     public void getConnectedDevices() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        List<BluetoothDevice> deviceList;
-
-        deviceList = mService.getConnectedDevices();
+        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
         Log.d(TAG, "getConnectedDevices(): size=" + deviceList.size());
         for (BluetoothDevice device : deviceList) {
-            int connectionState = mService.getConnectionState(device);
-            checkValidConnectionState(connectionState);
+            assertThat(mService.getConnectionState(device)).isIn(sValidConnectionStates);
         }
     }
 
@@ -397,18 +273,15 @@
     @MediumTest
     @Test
     public void getDevicesMatchingConnectionStates() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
-
-        for (int connectionState : mValidConnectionStates) {
-            List<BluetoothDevice> deviceList;
-
-            deviceList = mService.getDevicesMatchingConnectionStates(new int[]{connectionState});
-            assertNotNull(deviceList);
-            Log.d(TAG, "getDevicesMatchingConnectionStates(" + connectionState + "): size="
-                  + deviceList.size());
-            checkDeviceListAndStates(deviceList, connectionState);
+        for (int connectionState : sValidConnectionStates) {
+            List<BluetoothDevice> deviceList =
+                    mService.getDevicesMatchingConnectionStates(new int[] {connectionState});
+            assertThat(deviceList).isNotNull();
+            for (BluetoothDevice device : deviceList) {
+                assertWithMessage("Mismatched connection state for device=" + device)
+                        .that(mService.getConnectionState(device))
+                        .isEqualTo(connectionState);
+            }
         }
     }
 
@@ -420,158 +293,35 @@
     @MediumTest
     @Test
     public void getConnectionStateChangedIntent() {
-        waitForProfileConnect();
-        assertTrue(mIsProfileReady);
-        assertNotNull(mService);
+        List<BluetoothDevice> bondedDeviceList =
+                mService.getDevicesMatchingConnectionStates(
+                        sValidConnectionStates.stream().mapToInt(Integer::intValue).toArray());
 
-        // Find out how many Hearing Aid bonded devices
-        List<BluetoothDevice> bondedDeviceList = new ArrayList();
-        int numDevices = 0;
-        for (int connectionState : mValidConnectionStates) {
-            List<BluetoothDevice> deviceList;
+        int numDevices = bondedDeviceList.size();
+        Assume.assumeTrue(numDevices > 0);
 
-            deviceList = mService.getDevicesMatchingConnectionStates(new int[]{connectionState});
-            bondedDeviceList.addAll(deviceList);
-            numDevices += deviceList.size();
-        }
-
-        if (numDevices <= 0) return;
-        Log.d(TAG, "Number Hearing Aids devices bonded=" + numDevices);
-
-        mIntentCallbackDeviceList = new ArrayList();
-
-        // Set up the Connection State Changed receiver
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-        mIntentReceiver = new HearingAidIntentReceiver();
-        mContext.registerReceiver(mIntentReceiver, filter);
-
-        Log.d(TAG, "getConnectionStateChangedIntent: disable adapter and wait");
-        assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
-
-        Log.d(TAG, "getConnectionStateChangedIntent: enable adapter and wait");
-        assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
-
-        int sanityCount = WAIT_FOR_INTENT_TIMEOUT_MS;
-        while ((numDevices != mIntentCallbackDeviceList.size()) && (sanityCount > 0)) {
-            final int SLEEP_QUANTUM_MS = 100;
-            sleep(SLEEP_QUANTUM_MS);
-            sanityCount -= SLEEP_QUANTUM_MS;
-        }
-
-        // Tear down
-        mContext.unregisterReceiver(mIntentReceiver);
-
-        Log.d(TAG, "getConnectionStateChangedIntent: number of bonded device="
-              + numDevices + ", mIntentCallbackDeviceList.size()="
-              + mIntentCallbackDeviceList.size());
-        for (BluetoothDevice device : mIntentCallbackDeviceList) {
-            assertTrue(bondedDeviceList.contains(device));
-        }
-    }
-
-    private boolean waitForProfileConnect() {
-        mProfileConnectionlock.lock();
+        BroadcastReceiver mockReceiver = mock(BroadcastReceiver.class);
+        sContext.registerReceiver(
+                mockReceiver,
+                new IntentFilter(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED));
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
         try {
-            // Wait for the Adapter to be disabled
-            while (!mIsProfileReady) {
-                if (!mConditionProfileConnection.await(
-                    PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-                    // Timeout
-                    Log.e(TAG, "Timeout while waiting for Profile Connect");
-                    break;
-                } // else spurious wakeups
-            }
-        } catch(InterruptedException e) {
-            Log.e(TAG, "waitForProfileConnect: interrrupted");
+            assertThat(BlockingBluetoothAdapter.disable(true)).isTrue();
+            assertThat(BlockingBluetoothAdapter.enable()).isTrue();
+
+            verify(mockReceiver, timeout(WAIT_FOR_INTENT_TIMEOUT.toMillis()).times(numDevices))
+                    .onReceive(any(), captor.capture());
         } finally {
-            mProfileConnectionlock.unlock();
-        }
-        return mIsProfileReady;
-    }
-
-    private boolean waitForProfileDisconnect() {
-        mConditionProfileConnection = mProfileConnectionlock.newCondition();
-        mProfileConnectionlock.lock();
-        try {
-            while (mIsProfileReady) {
-                if (!mConditionProfileConnection.await(
-                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-                    // Timeout
-                    Log.e(TAG, "Timeout while waiting for Profile Disconnect");
-                    break;
-                } // else spurious wakeups
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "waitForProfileDisconnect: interrrupted");
-        } finally {
-            mProfileConnectionlock.unlock();
-        }
-        return !mIsProfileReady;
-    }
-
-    private final class HearingAidsServiceListener
-            implements BluetoothProfile.ServiceListener {
-
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mProfileConnectionlock.lock();
-            mService = (BluetoothHearingAid) proxy;
-            mIsProfileReady = true;
-            try {
-                mConditionProfileConnection.signal();
-            } finally {
-                mProfileConnectionlock.unlock();
-            }
+            sContext.unregisterReceiver(mockReceiver);
         }
 
-        public void onServiceDisconnected(int profile) {
-            mProfileConnectionlock.lock();
-            mIsProfileReady = false;
-            mService = null;
-            try {
-                mConditionProfileConnection.signal();
-            } finally {
-                mProfileConnectionlock.unlock();
-            }
+        for (Intent intent : captor.getAllValues()) {
+            assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1))
+                    .isIn(sValidConnectionStates);
+            assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1))
+                    .isIn(sValidConnectionStates);
+            assertThat((BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
+                    .isIn(bondedDeviceList);
         }
     }
-
-    private class HearingAidIntentReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
-                int previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
-                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
-                Log.d(TAG,"HearingAidIntentReceiver.onReceive: device=" + device
-                      + ", state=" + state + ", previousState=" + previousState);
-
-                checkValidConnectionState(state);
-                checkValidConnectionState(previousState);
-
-                mIntentCallbackDeviceList.add(device);
-            }
-        }
-    }
-
-    private void checkDeviceListAndStates(List<BluetoothDevice> deviceList, int connectionState) {
-        Log.d(TAG, "checkDeviceListAndStates(): size=" + deviceList.size()
-              + ", connectionState=" + connectionState);
-        for (BluetoothDevice device : deviceList) {
-            int deviceConnectionState = mService.getConnectionState(device);
-            assertEquals("Mismatched connection state for " + device,
-                         connectionState, deviceConnectionState);
-        }
-    }
-
-    private void checkValidConnectionState(int connectionState) {
-        assertTrue(mValidConnectionStates.contains(connectionState));
-    }
-
-    private static void sleep(long t) {
-        try {
-            Thread.sleep(t);
-        } catch (InterruptedException e) {}
-    }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
index 13bdf4d..99dda27 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanFilterTest.java
@@ -17,6 +17,7 @@
 package android.bluetooth.cts;
 
 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -32,6 +33,7 @@
 import android.bluetooth.le.ScanFilter;
 import android.bluetooth.le.ScanResult;
 import android.bluetooth.le.TransportBlockFilter;
+import android.bluetooth.test_utils.Permissions;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Parcel;
@@ -337,11 +339,13 @@
                 .setTdsFlags(tdsFlag, tdsFlagMask)
                 .setTransportData(transportData, transportDataMask).build();
 
-        if (mBluetoothAdapter.getOffloadedTransportDiscoveryDataScanSupported()
-                != FEATURE_SUPPORTED) {
-            assertThrows(IllegalArgumentException.class,
-                    () -> mFilterBuilder.setTransportBlockFilter(transportBlockFilter));
-            return;
+        try (var p = Permissions.withPermissions(BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED)) {
+            if (mBluetoothAdapter.getOffloadedTransportDiscoveryDataScanSupported()
+                    != FEATURE_SUPPORTED) {
+                assertThrows(IllegalArgumentException.class,
+                        () -> mFilterBuilder.setTransportBlockFilter(transportBlockFilter));
+                return;
+            }
         }
 
         final ScanFilter filter = mFilterBuilder
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
index 1e6bd20..7827a96 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.BLUETOOTH_CONNECT;
 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -37,14 +38,13 @@
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.le.AdvertiseSettings;
 import android.bluetooth.le.AdvertisingSetParameters;
+import android.bluetooth.test_utils.Permissions;
 import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.os.ParcelUuid;
 import android.provider.Settings;
-import android.util.Log;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -62,9 +62,6 @@
 
 import java.time.Duration;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 
 @RunWith(AndroidJUnit4.class)
 public class SystemBluetoothTest {
@@ -82,10 +79,6 @@
     private final UiAutomation mUiAutomation =
             InstrumentationRegistry.getInstrumentation().getUiAutomation();
 
-    private ReentrantLock mDiscoveryStartedLock;
-    private Condition mConditionDiscoveryStarted;
-    private boolean mIsDiscoveryStarted;
-
     @Before
     public void setUp() throws Exception {
         Assume.assumeTrue(
@@ -156,21 +149,25 @@
                         "android.bluetooth.cts", android.Manifest.permission.ACCESS_FINE_LOCATION);
             }
 
-            mDiscoveryStartedLock = new ReentrantLock();
-            mConditionDiscoveryStarted = mDiscoveryStartedLock.newCondition();
-
             IntentFilter filter = new IntentFilter();
             filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
             filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-            mContext.registerReceiver(mDiscoveryStartedReceiver, filter);
 
-            mAdapter.startDiscovery();
-            assertThat(waitForDiscoveryStart()).isTrue();
+            BroadcastReceiver mockReceiver = mock(BroadcastReceiver.class);
+            mContext.registerReceiver(mockReceiver, filter);
+
+            try (var p = Permissions.withPermissions(BLUETOOTH_SCAN)) {
+                mAdapter.startDiscovery();
+                // Wait for any of ACTION_DISCOVERY_STARTED intent, while holding BLUETOOTH_SCAN
+                verify(mockReceiver, timeout(DISCOVERY_START_TIMEOUT)).onReceive(any(), any());
+            }
+
             long discoveryEndTime = mAdapter.getDiscoveryEndMillis();
             long currentTime = System.currentTimeMillis();
             assertThat(discoveryEndTime > currentTime).isTrue();
             assertThat(discoveryEndTime - currentTime < DEFAULT_DISCOVERY_TIMEOUT_MS).isTrue();
-            mContext.unregisterReceiver(mDiscoveryStartedReceiver);
+
+            mContext.unregisterReceiver(mockReceiver);
         } finally {
             if (recoverOffState) {
                 TestUtils.disableLocation(mContext);
@@ -455,42 +452,4 @@
         assertThat(mAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE))
                 .isEqualTo(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
     }
-
-    private boolean waitForDiscoveryStart() {
-        mDiscoveryStartedLock.lock();
-        try {
-            // Wait for discovery to be started
-            while (!mIsDiscoveryStarted) {
-                if (!mConditionDiscoveryStarted.await(
-                        DISCOVERY_START_TIMEOUT, TimeUnit.MILLISECONDS)) {
-                    Log.e(TAG, "Timeout while waiting for discovery to start");
-                    break;
-                }
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "waitForDiscoveryStart: interrupted");
-        } finally {
-            mDiscoveryStartedLock.unlock();
-        }
-        return mIsDiscoveryStarted;
-    }
-
-    private final BroadcastReceiver mDiscoveryStartedReceiver =
-            new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    String action = intent.getAction();
-                    if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
-                        Log.i(TAG, "Discovery started");
-                        mDiscoveryStartedLock.lock();
-                        mIsDiscoveryStarted = true;
-                        try {
-                            mConditionDiscoveryStarted.signal();
-                        } catch (IllegalMonitorStateException ex) {
-                        } finally {
-                            mDiscoveryStartedLock.unlock();
-                        }
-                    }
-                }
-            };
 }
diff --git a/tests/tests/car/OWNERS b/tests/tests/car/OWNERS
index d703344..b42a31c 100644
--- a/tests/tests/car/OWNERS
+++ b/tests/tests/car/OWNERS
@@ -2,4 +2,4 @@
 include platform/packages/services/Car:/OWNERS
 
 # IME related CTS files
-per-file src/android/car/view/inputmethod/cts/*=kanant@google.com,ycheo@google.com
+per-file src/android/car/view/inputmethod/cts/*=kanant@google.com
diff --git a/tests/tests/car/src/android/car/app/cts/OWNERS b/tests/tests/car/src/android/car/app/cts/OWNERS
index f718b81..b5271fc 100644
--- a/tests/tests/car/src/android/car/app/cts/OWNERS
+++ b/tests/tests/car/src/android/car/app/cts/OWNERS
@@ -1,4 +1,3 @@
 # ActivityManager and TaskView related CTS files
-ycheo@google.com
 gauravbhola@google.com
 kanant@google.com
diff --git a/tests/tests/car/src/android/car/cts/OWNERS b/tests/tests/car/src/android/car/cts/OWNERS
index 1b4a61d..a9f2d03 100644
--- a/tests/tests/car/src/android/car/cts/OWNERS
+++ b/tests/tests/car/src/android/car/cts/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 526266
+
 # Vehicle property related CTS files
 per-file CarPropertyManagerTest.java=shanyu@google.com,tylertrephan@google.com
 per-file VehiclePropertyIdsTest.java=shanyu@google.com,tylertrephan@google.com
@@ -7,11 +9,11 @@
 per-file CarAudioFocusTest.java=oscarazu@google.com
 
 # Input related CTS files
-per-file CarInputManagerSystemTest.java=kanant@google.com,ycheo@google.com
-per-file CarInputTest.java=kanant@google.com,ycheo@google.com
+per-file CarInputManagerSystemTest.java=kanant@google.com
+per-file CarInputTest.java=kanant@google.com
 
 # Display related CTS files
-per-file CarDisplayInputLockTest.java=ycheo@google.com
+per-file CarDisplayInputLockTest.java=gauravbhola@google.com,xiangw@google.com
 
 # Mainline CTS files
 per-file ApiVersionTest.java=gargmayank@google.com
@@ -27,10 +29,10 @@
 per-file CarBluetoothTest.java=salsavage@google.com
 
 # Occupant Zone CTS files
-per-file CarOccupantZoneManagerTest.java=xiangw@google.com,ycheo@google.com
+per-file CarOccupantZoneManagerTest.java=xiangw@google.com
 
 # Comms API CTS files
-per-file CarOccupantConnectionManagerTest.java=xiangw@google.com,ycheo@google.com
+per-file CarOccupantConnectionManagerTest.java=xiangw@google.com
 
 # EV CTS files
 per-file EvChargeStateTest.java=changyeon@google.com
@@ -50,8 +52,7 @@
 per-file CarMediaManagerTest.java=bkchoi@google.com
 
 # PackageManager related CTS files
-# TODO(b/282199666): Find an owner for CarPackageManagerTest
-# per-file CarPackageManagerTest.java=
+per-file CarPackageManagerTest.java=gauravbhola@google.com,gargmayank@google.com
 
 # Remote Access related CTS files
 per-file CarRemoteAccessManagerTest.java=ericjeong@google.com,shanyu@google.com
diff --git a/tests/tests/car/src/android/car/server/wm/cts/OWNERS b/tests/tests/car/src/android/car/server/wm/cts/OWNERS
index 04041f9..8075c5f 100644
--- a/tests/tests/car/src/android/car/server/wm/cts/OWNERS
+++ b/tests/tests/car/src/android/car/server/wm/cts/OWNERS
@@ -1,4 +1,3 @@
 # MultiUserMultiDisplay policy related CTS files
-ycheo@google.com
 gauravbhola@google.com
 kanant@google.com
diff --git a/tests/tests/car/src/android/car/view/cts/OWNERS b/tests/tests/car/src/android/car/view/cts/OWNERS
index 5b0bc9f..c7c7654 100644
--- a/tests/tests/car/src/android/car/view/cts/OWNERS
+++ b/tests/tests/car/src/android/car/view/cts/OWNERS
@@ -1,3 +1,3 @@
 # Display related CTS files
-ycheo@google.com
 gauravbhola@google.com
+xiangw@google.com
diff --git a/tests/tests/car_permission_tests/OWNERS b/tests/tests/car_permission_tests/OWNERS
index 7c485fb..e846a77 100644
--- a/tests/tests/car_permission_tests/OWNERS
+++ b/tests/tests/car_permission_tests/OWNERS
@@ -5,13 +5,13 @@
 per-file src/com/android/car/media/CarAudio*.java = oscarazu@google.com, ericjeong@google.com
 
 # Cluster
-per-file src/com/android/car/cluster/* = ycheo@google.com
+per-file src/com/android/car/cluster/* = bkchoi@google.com
 
 # Input
-per-file src/com/android/car/input/* = ycheo@google.com, kanant@google.com
+per-file src/com/android/car/input/* = kanant@google.com
 
 # OccupantZone
-per-file src/com/android/car/CarOccupantZoneManagerPermissionTest.java = ycheo@google.com, oscarazu@google.com, ericjeong@google.com
+per-file src/com/android/car/CarOccupantZoneManagerPermissionTest.java = xiangw@google.com, oscarazu@google.com, ericjeong@google.com
 
 # Power
 per-file src/com/android/car/power/* = ericjeong@google.com
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
index d6a3e58..9ff69da 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
@@ -43,6 +43,7 @@
 
 import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.UiAutomatorUtils2;
 
 import org.junit.After;
 import org.junit.Before;
@@ -395,11 +396,21 @@
         switch (consentReply) {
             case ALLOW:
                 Log.d(TAG, "Allow the consent dialog");
-                replySelector = By.res("android", "button1");
+                if (isWear()) {
+                    replySelector = By.desc(
+                            getContext().getResources().getString(android.R.string.ok));
+                } else {
+                    replySelector = By.res("android", "button1");
+                }
                 break;
             case DENY:
                 Log.d(TAG, "Deny the consent dialog");
-                replySelector = By.res("android", "button2");
+                if (isWear()) {
+                    replySelector = By.desc(
+                            getContext().getResources().getString(android.R.string.cancel));
+                } else {
+                    replySelector = By.res("android", "button2");
+                }
                 break;
             case NONE_TIMEOUT:
             default:
@@ -409,12 +420,16 @@
         }
 
         UiObject2 replyButton;
-        UiObject2 scrollable =
-                device.findObject(By.res("android:id/scrollView").scrollable(true));
-        while ((replyButton = device.findObject(replySelector)) == null) {
-            // Need to scroll the screen to get to the buttons on some form factors
-            // (e.g. on a watch).
-            scrollable.scroll(Direction.DOWN, 100);
+        if (isWear()) {
+            replyButton = UiAutomatorUtils2.waitFindObject(replySelector);
+        } else {
+            UiObject2 scrollable =
+                    device.findObject(By.res("android:id/scrollView").scrollable(true));
+            while ((replyButton = device.findObject(replySelector)) == null) {
+                // Need to scroll the screen to get to the buttons on some form factors
+                // (e.g. on a watch).
+                scrollable.scroll(Direction.DOWN, 100);
+            }
         }
 
         assertWithMessage("The button of consent dialog is not found")
diff --git a/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp b/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
index 3bda711..15fbe3c 100644
--- a/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
+++ b/tests/tests/graphics/jni/ImageReaderTestHelpers.cpp
@@ -41,7 +41,7 @@
 
 int ImageReaderHelper::initImageReader() {
   if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
-    ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p",
+    ALOGE("Cannot reinitialize image reader, mImgReader=%p, mImgReaderAnw=%p",
           mImgReader, mImgReaderAnw);
     return -1;
   }
@@ -84,9 +84,9 @@
     if (ret != AMEDIA_OK || outImage == nullptr) {
       // When the BufferQueue is in async mode, it is still possible that
       // AImageReader_acquireNextImage returns nothing after onFrameAvailable.
-      ALOGW("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
+      ALOGW("Failed to acquire image, ret=%d, outImage=%p.", ret, outImage);
     } else {
-      // Any exisitng in mAcquiredImage will be deleted and released
+      // Any existing in mAcquiredImage will be deleted and released
       // automatically.
       mAcquiredImage.reset(outImage);
     }
diff --git a/tests/tests/graphics/jni/ImageReaderTestHelpers.h b/tests/tests/graphics/jni/ImageReaderTestHelpers.h
index dcd08d9..2196aca 100644
--- a/tests/tests/graphics/jni/ImageReaderTestHelpers.h
+++ b/tests/tests/graphics/jni/ImageReaderTestHelpers.h
@@ -48,7 +48,7 @@
   uint32_t mMaxImages;
 
   std::mutex mMutex;
-  // Number of images that's avaiable for acquire.
+  // Number of images that are available to be acquired.
   size_t mAvailableImages{0};
   // Although AImageReader supports acquiring multiple images at a time, we
   // don't really need it in this test. We only acquire one image that a time.
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
index d4472e2..97dfac9 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
@@ -38,7 +38,7 @@
                 android:pathData="@string/rectangle200" />
 
             <group
-                android:name="ThridLevelGroup1"
+                android:name="ThirdLevelGroup1"
                 android:translateX="-100.0"
                 android:translateY="50.0" >
                 <path
@@ -47,7 +47,7 @@
                     android:pathData="@string/rectangle200" />
             </group>
             <group
-                android:name="ThridLevelGroup2"
+                android:name="ThirdLevelGroup2"
                 android:translateX="100.0"
                 android:translateY="50.0" >
                 <path
@@ -66,7 +66,7 @@
                 android:pathData="@string/rectangle200" />
 
             <group
-                android:name="ThridLevelGroup3"
+                android:name="ThirdLevelGroup3"
                 android:translateX="-100.0"
                 android:translateY="50.0" >
                 <path
@@ -75,7 +75,7 @@
                     android:pathData="@string/rectangle200" />
             </group>
             <group
-                android:name="ThridLevelGroup4"
+                android:name="ThirdLevelGroup4"
                 android:translateX="100.0"
                 android:translateY="50.0" >
                 <path
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
index 6fcb355..964047a 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
@@ -33,7 +33,7 @@
                 android:pathData="@string/rectangle200" />
 
             <group
-                android:name="ThridLevelGroup1"
+                android:name="ThirdLevelGroup1"
                 android:translateX="-100.0"
                 android:translateY="50.0" >
                 <path
@@ -42,7 +42,7 @@
                     android:pathData="@string/rectangle200" />
             </group>
             <group
-                android:name="ThridLevelGroup2"
+                android:name="ThirdLevelGroup2"
                 android:translateX="100.0"
                 android:translateY="50.0" >
                 <path
@@ -61,7 +61,7 @@
                 android:pathData="@string/rectangle200" />
 
             <group
-                android:name="ThridLevelGroup3"
+                android:name="ThirdLevelGroup3"
                 android:translateX="-100.0"
                 android:translateY="50.0" >
                 <path
@@ -70,7 +70,7 @@
                     android:pathData="@string/rectangle200" />
             </group>
             <group
-                android:name="ThridLevelGroup4"
+                android:name="ThirdLevelGroup4"
                 android:translateX="100.0"
                 android:translateY="50.0" >
                 <path
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index f829e80..52ae7c2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -47,8 +47,8 @@
     private static final int ALPHA_OPAQUE = 0xFF;
     private static final String NAME = "TESTNAME";
     private static final int WIDTH = 80;
-    private static final int HEIGTH = 120;
-    private static final int[] COLOR = new int[WIDTH * HEIGTH];
+    private static final int HEIGHT = 120;
+    private static final int[] COLOR = new int[WIDTH * HEIGHT];
 
     private NinePatch mNinePatch;
     private Bitmap mBitmap;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 86e7400..d4e4d52 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -1810,7 +1810,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment() {
+    public void testEqualsForTextMeasurement() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1818,7 +1818,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_textSize() {
+    public void testEqualsForTextMeasurement_textSize() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1829,7 +1829,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_textSkew() {
+    public void testEqualsForTextMeasurement_textSkew() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1840,7 +1840,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_textScale() {
+    public void testEqualsForTextMeasurement_textScale() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1851,7 +1851,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_letterSpacing() {
+    public void testEqualsForTextMeasurement_letterSpacing() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1862,7 +1862,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_localeList() {
+    public void testEqualsForTextMeasurement_localeList() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
@@ -1876,7 +1876,7 @@
     }
 
     @Test
-    public void testEqualsForTextMeasurment_typeface() {
+    public void testEqualsForTextMeasurement_typeface() {
         Paint p1 = new Paint();
         Paint p2 = new Paint();
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index dd4f3e1..c3335b4 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -564,7 +564,7 @@
 
     @Test
     public void testTypeface_SupportedCmapEncodingTest() {
-        // We support the following combinations of cmap platfrom/endcoding pairs.
+        // We support the following combinations of cmap platform/endcoding pairs.
         String[] fontPaths = {
             // Platform ID == 0, Encoding ID == 0
             "fonts/cmap_selection/CmapPlatform0Encoding0.ttf",
@@ -673,7 +673,7 @@
         assertEquals(GLYPH_3EM_WIDTH, measureText("b", italicFamily), 0f);
         assertEquals(GLYPH_1EM_WIDTH, measureText("c", italicFamily), 0f);
 
-        // Draw with the italic font which weigth is 700.
+        // Draw with the italic font and weight set to 700.
         final Typeface boldItalicFamily =
                 Typeface.create(family, 700 /* weight */, true /* italic */);
         assertEquals(GLYPH_1EM_WIDTH, measureText("a", boldItalicFamily), 0f);
diff --git a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
index 744fd8b..ecdc5bd 100644
--- a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
@@ -183,7 +183,7 @@
         // test if handling compression parameters correctly
         verifyParameters();
 
-        // test various cases by varing
+        // test various cases by varying
         // <ImageFormat, Bitmap, HasPaddings, Rect>
         for (int i = 0; i < JPEG_FORMATS.length; ++i) {
             for (int j = 0; j < mTestBitmaps.length; ++j) {
@@ -524,7 +524,7 @@
     }
 
     // Compress rect1 in testBitmap and rect2 in image.
-    // Then, compare the two resutls to check their MSE.
+    // Then, compare the two results to check their MSE.
     private void compressRects(Bitmap testBitmap, YuvImage image,
             Rect rect1, Rect rect2) {
         Bitmap expected = null;
diff --git a/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
index fe129e8..75af270 100644
--- a/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
+++ b/tests/tests/graphics/src/android/graphics/cts/utils/CamUtils.java
@@ -34,7 +34,7 @@
  *
  * <p>XYZ is commonly used as an intermediate color space for converting between one color space to
  * another. For example, to convert RGB to L*a*b*, first RGB is converted to XYZ, then XYZ is
- * convered to L*a*b*.
+ * converted to L*a*b*.
  *
  * <p>sRGB is a "specification originated from work in 1990s through cooperation by Hewlett-Packard
  * and Microsoft, and it was designed to be a standard definition of RGB for the internet, which it
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
index 1142c20..9bb4962 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PictureDrawableTest.java
@@ -65,7 +65,7 @@
         // Check the color has been set.
         assertEquals(0xff0f0b0c, destBitmap.getPixel(10, 10));
         pictureDrawable.draw(canvas);
-        // Check the target pixle's color, ensure it has been changed.
+        // Check the target pixel's color, ensure it has been changed.
         assertEquals(0xff0a0c0b, destBitmap.getPixel(10, 10));
     }
 
diff --git a/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java b/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
index dc90130..d1dd341 100644
--- a/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
+++ b/tests/tests/graphics/src/android/graphics/text/cts/LineBreakerTest.java
@@ -72,7 +72,7 @@
     }
 
     @Test
-    public void testSetBreakStrategy_shoulNotThrowExceptions() {
+    public void testSetBreakStrategy_shouldNotThrowExceptions() {
         assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_SIMPLE).build());
         assertNotNull(new LineBreaker.Builder().setBreakStrategy(BREAK_STRATEGY_HIGH_QUALITY)
                 .build());
diff --git a/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml b/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
index f7d7bd6..7971309 100644
--- a/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
+++ b/tests/tests/keystore/CtsKeystorePerformanceTestManifest.xml
@@ -25,8 +25,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.keystore.cts.performance"
                      android:label="CTS tests of android.keystore.cts.performance">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 
 </manifest>
diff --git a/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
index 12e24f2..803f962 100644
--- a/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
+++ b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
@@ -25,8 +25,6 @@
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.google.security.wycheproof"
                      android:label="CTS tests of com.google.security.wycheproof">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 
 </manifest>
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 9de76e0..3e7aecb 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -40,6 +40,7 @@
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.server.wm.ActivityManagerTestBase;
@@ -1366,6 +1367,32 @@
     }
 
     @Test
+    public void testAuthBoundKeysKeyPermanentlyInvalidatedException() throws Exception {
+        assumeTrue(TestUtils.hasSecureLockScreen(getContext()));
+
+        ImportedKey key = null;
+        try (DeviceLockSession dl = new DeviceLockSession()) {
+            KeyProtection importParams =
+                    TestUtils.getMinimalWorkingImportParametersForCipheringWith(BASIC_ALGORITHMS[0],
+                            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT,
+                            /* ivProvidedWhenEncrypting= */ false,
+                            /* isUnlockedDeviceRequired= */ false,
+                            /* isUserAuthRequired= */ true);
+            key = importDefaultKatKey(BASIC_ALGORITHMS[0], importParams);
+            assertTrue(TestUtils.keyExists(key.getAlias()));
+        } // DeviceLockSession#close() removes the secure lock screen.
+
+        // Try to use the key after removal of secure screen lock screen.
+        KatVector testVector = KAT_VECTORS.get(BASIC_ALGORITHMS[0]);
+        Cipher cipher = Cipher.getInstance(BASIC_ALGORITHMS[0]);
+        Key encryptionKey = key.getKeystoreBackedEncryptionKey();
+        // Removing the secure lock screen should have invalidated the auth-bound keys.
+        assertThrows(KeyPermanentlyInvalidatedException.class, () -> {
+            cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
+        });
+    }
+
+    @Test
     public void testInitDecryptFailsWhenNotAuthorizedToDecrypt() throws Exception {
         for (String transformation : EXPECTED_ALGORITHMS) {
             try {
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index a412109..5a42aa9 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -32,9 +32,7 @@
 import static android.keystore.cts.AuthorizationList.KM_PURPOSE_VERIFY;
 import static android.keystore.cts.RootOfTrust.KM_VERIFIED_BOOT_VERIFIED;
 import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_AGREE_KEY;
-import static android.security.keystore.KeyProperties.DIGEST_NONE;
 import static android.security.keystore.KeyProperties.DIGEST_SHA256;
-import static android.security.keystore.KeyProperties.DIGEST_SHA512;
 import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_NONE;
 import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_OAEP;
 import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1;
@@ -114,9 +112,11 @@
 import java.security.cert.CertificateParsingException;
 import java.security.cert.X509Certificate;
 import java.security.spec.ECGenParameterSpec;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -153,6 +153,7 @@
 
     private static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
     private static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
+    private static final int KM_ERROR_UNKNOWN_ERROR = -1000;
     private static final int KM_ERROR_PERMISSION_DENIED = 6;
 
     private Context getContext() {
@@ -282,16 +283,45 @@
         }
     }
 
+    private void assertAttestationKeyMintError(KeyStoreException keyStoreException,
+            boolean devicePropertiesAttestation) {
+        int errorCode = keyStoreException.getErrorCode();
+        List<Integer> expectedErrs = new ArrayList<Integer>();
+        expectedErrs.add(KM_ERROR_INVALID_INPUT_LENGTH);
+        if (devicePropertiesAttestation) {
+            expectedErrs.add(KM_ERROR_CANNOT_ATTEST_IDS);
+        }
+        if (TestUtils.getVendorApiLevel() < 35) {
+            // b/337427860, some devices returns UNKNOWN_ERROR if large challenge is
+            // passed. So allow an extra error code for earlier devices.
+            expectedErrs.add(KM_ERROR_UNKNOWN_ERROR);
+        }
+        String assertMessage = String.format(
+                "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
+                + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
+                + "too large (error code was %d, attestation properties %b)",
+                errorCode, devicePropertiesAttestation);
+        assertTrue(assertMessage, expectedErrs.contains(errorCode));
+    }
+
     private void assertPublicAttestationError(KeyStoreException keyStoreException,
             boolean devicePropertiesAttestation) {
         // Assert public failure information.
         int errorCode = keyStoreException.getNumericErrorCode();
+        List<Integer> expectedErrs = new ArrayList<Integer>();
+        expectedErrs.add(KeyStoreException.ERROR_INCORRECT_USAGE);
+        if (devicePropertiesAttestation) {
+            expectedErrs.add(KeyStoreException.ERROR_ID_ATTESTATION_FAILURE);
+        }
+        if (TestUtils.getVendorApiLevel() < 35) {
+            // b/337427860, some devices returns UNKNOWN_ERROR if large challenge is
+            // passed. So allow an extra error code for earlier devices.
+            expectedErrs.add(KeyStoreException.ERROR_KEYMINT_FAILURE);
+        }
         String assertMessage = String.format(
                 "Error code was %d, device properties attestation? %b",
                 errorCode, devicePropertiesAttestation);
-        assertTrue(assertMessage, KeyStoreException.ERROR_INCORRECT_USAGE == errorCode
-                || (devicePropertiesAttestation
-                && KeyStoreException.ERROR_ID_ATTESTATION_FAILURE == errorCode));
+        assertTrue(assertMessage, expectedErrs.contains(errorCode));
         assertFalse("Unexpected transient failure.", keyStoreException.isTransientFailure());
     }
 
@@ -320,16 +350,7 @@
                 fail("Attestation challenges larger than 128 bytes should be rejected");
             } catch (ProviderException e) {
                 KeyStoreException cause = (KeyStoreException) e.getCause();
-                int errorCode = cause.getErrorCode();
-                String assertMessage = String.format(
-                        "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
-                        + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
-                        + "too large (error code was %d, attestation properties %b)",
-                        errorCode, devicePropertiesAttestation);
-                assertTrue(assertMessage, KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode()
-                        || (devicePropertiesAttestation
-                            && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
-                );
+                assertAttestationKeyMintError(cause, devicePropertiesAttestation);
                 assertPublicAttestationError(cause, devicePropertiesAttestation);
             }
         }
@@ -356,7 +377,7 @@
             Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
             KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
                     .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
-                    .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                    .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                     .setAttestationChallenge(null)
                     .setKeyValidityStart(now)
                     .setKeyValidityForOriginationEnd(originationEnd)
@@ -398,18 +419,13 @@
         KeyGenParameterSpec.Builder builder =
             new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
                     .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+                    .setDigests(TestUtils.getDigestsForKeyMintImplementation(expectStrongBox))
                     .setAttestationChallenge(new byte[128])
                     .setKeyValidityStart(now)
                     .setKeyValidityForOriginationEnd(originationEnd)
                     .setKeyValidityForConsumptionEnd(consumptionEnd)
                     .setIsStrongBoxBacked(expectStrongBox);
 
-        if (expectStrongBox) {
-            builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
-        } else {
-            builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
-        }
-
         generateKeyPair(KEY_ALGORITHM_EC, builder.build());
 
         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
@@ -540,7 +556,7 @@
         String keystoreAlias = "test_key";
         KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
                 .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
-                .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                 .setAttestationChallenge(new byte[128])
                 .setUniqueIdIncluded(true)
                 .setIsStrongBoxBacked(isStrongBox)
@@ -585,7 +601,7 @@
         String keystoreAlias = "test_key";
         KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
                 .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
-                .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                 .setAttestationChallenge(new byte[128])
                 .setUniqueIdIncluded(true)
                 .setIsStrongBoxBacked(isStrongBox)
@@ -762,16 +778,7 @@
                 fail("Attestation challenges larger than 128 bytes should be rejected");
             } catch(ProviderException e){
                 KeyStoreException cause = (KeyStoreException) e.getCause();
-                int errorCode = cause.getErrorCode();
-                String assertMessage = String.format(
-                        "The KeyMint implementation may only return INVALID_INPUT_LENGTH or "
-                        + "CANNOT_ATTEST_IDSs as errors when the attestation challenge is "
-                        + "too large (error code was %d, attestation properties %b)",
-                        errorCode, devicePropertiesAttestation);
-                assertTrue(assertMessage, KM_ERROR_INVALID_INPUT_LENGTH == cause.getErrorCode()
-                        || (devicePropertiesAttestation
-                            && KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
-                );
+                assertAttestationKeyMintError(cause, devicePropertiesAttestation);
                 assertPublicAttestationError(cause, devicePropertiesAttestation);
             }
         }
@@ -797,7 +804,7 @@
             Date originationEnd = new Date(now.getTime() + ORIGINATION_TIME_OFFSET);
             Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
             KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
-                    .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                    .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                     .setAttestationChallenge(null)
                     .setKeyValidityStart(now)
                     .setKeyValidityForOriginationEnd(originationEnd)
@@ -835,22 +842,16 @@
         Date now = new Date();
         Date originationEnd = new Date(now.getTime() + ORIGINATION_TIME_OFFSET);
         Date consumptionEnd = new Date(now.getTime() + CONSUMPTION_TIME_OFFSET);
-        KeyGenParameterSpec.Builder builder =
-            new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
-                    .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
-                    .setAttestationChallenge("challenge".getBytes())
-                    .setKeyValidityStart(now)
-                    .setKeyValidityForOriginationEnd(originationEnd)
-                    .setKeyValidityForConsumptionEnd(consumptionEnd)
-                    .setIsStrongBoxBacked(expectStrongBox);
+        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
+                  .setDigests(TestUtils.getDigestsForKeyMintImplementation(expectStrongBox))
+                  .setAttestationChallenge("challenge".getBytes())
+                  .setKeyValidityStart(now)
+                  .setKeyValidityForOriginationEnd(originationEnd)
+                  .setKeyValidityForConsumptionEnd(consumptionEnd)
+                  .setIsStrongBoxBacked(expectStrongBox)
+                  .build();
 
-        if (expectStrongBox) {
-            builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
-        } else {
-            builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
-        }
-
-        generateKeyPair(KEY_ALGORITHM_RSA, builder.build());
+        generateKeyPair(KEY_ALGORITHM_RSA, spec);
 
         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
         keyStore.load(null);
@@ -1134,7 +1135,7 @@
         KeyGenParameterSpec.Builder builder =
             new KeyGenParameterSpec.Builder(keystoreAlias, purposes)
                         .setKeySize(keySize)
-                        .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                        .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                         .setAttestationChallenge(challenge)
                         .setDevicePropertiesAttestationIncluded(devicePropertiesAttestation)
                         .setIsStrongBoxBacked(isStrongBox);
@@ -1209,7 +1210,7 @@
         KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keystoreAlias,
                 purposes)
                         .setAlgorithmParameterSpec(new ECGenParameterSpec(ecCurve))
-                        .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+                        .setDigests(TestUtils.getDigestsForKeyMintImplementation(isStrongBox))
                         .setAttestationChallenge(challenge)
                         .setDevicePropertiesAttestationIncluded(devicePropertiesAttestation)
                         .setIsStrongBoxBacked(isStrongBox);
@@ -1322,8 +1323,11 @@
             Date startTime, boolean includesValidityDates,
             boolean devicePropertiesAttestation, Attestation attestation)
             throws NoSuchAlgorithmException, NameNotFoundException {
-        checkKeyIndependentAttestationInfo(challenge, purposes,
-                ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_512),
+        Set digests = ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_512);
+        if (attestation.getAttestationSecurityLevel() == KM_SECURITY_LEVEL_STRONG_BOX) {
+            digests = ImmutableSet.of(KM_DIGEST_NONE, KM_DIGEST_SHA_2_256);
+        }
+        checkKeyIndependentAttestationInfo(challenge, purposes, digests,
                 startTime, includesValidityDates,
                 devicePropertiesAttestation, attestation);
     }
diff --git a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
index 2204552..a30074c 100644
--- a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
@@ -16,6 +16,10 @@
 
 package android.keystore.cts.util;
 
+import static android.security.keystore.KeyProperties.DIGEST_NONE;
+import static android.security.keystore.KeyProperties.DIGEST_SHA256;
+import static android.security.keystore.KeyProperties.DIGEST_SHA512;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -121,6 +125,20 @@
         return getFeatureVersionKeystore(appContext);
     }
 
+    /**
+     * This function returns the valid digest algorithms supported for a Strongbox or default
+     * KeyMint implementation. The isStrongbox parameter specifies the underlying KeyMint
+     * implementation. If true, it indicates Strongbox KeyMint, otherwise TEE/Software KeyMint
+     * is assumed.
+     */
+    public static @KeyProperties.DigestEnum String[] getDigestsForKeyMintImplementation(
+            boolean isStrongbox) {
+        if (isStrongbox) {
+            return new String[]{DIGEST_NONE, DIGEST_SHA256};
+        }
+        return new String[]{DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512};
+    }
+
     // Returns 0 if not implemented. Otherwise returns the feature version.
     //
     public static int getFeatureVersionKeystore(Context appContext) {
diff --git a/tests/tests/libcorefileio/AndroidManifest.xml b/tests/tests/libcorefileio/AndroidManifest.xml
index c6a95b5..4e0ad52 100644
--- a/tests/tests/libcorefileio/AndroidManifest.xml
+++ b/tests/tests/libcorefileio/AndroidManifest.xml
@@ -22,18 +22,11 @@
 
     <application>
         <uses-library android:name="android.test.runner"/>
+        <!-- Use ':' to indicate that lockHoldingService needs to run in a separate process.
+             See https://developer.android.com/guide/topics/manifest/service-element#proc -->
         <service android:name="android.cts.LockHoldingService"
              android:process=":lockHoldingService"
              android:permission="android.permission.WRITE_EXTERNAL_STORAGE"/>
-        <receiver android:name="android.cts.FileChannelInterProcessLockTest$IntentReceiver"
-             android:exported="true">
-
-            <intent-filter>
-                <action android:name="android.cts.CtsLibcoreFileIOTestCases">
-                </action>
-            </intent-filter>
-
-        </receiver>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
index d949250..bc990e2 100644
--- a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
+++ b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
@@ -16,12 +16,19 @@
 
 package android.cts;
 
-import android.content.BroadcastReceiver;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
 import android.test.AndroidTestCase;
 
 import java.io.File;
@@ -33,8 +40,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 
-import static java.util.concurrent.TimeUnit.SECONDS;
-
 @SuppressWarnings("deprecation")
 public class FileChannelInterProcessLockTest extends AndroidTestCase {
 
@@ -55,11 +60,11 @@
      * the service. This provides ample amount of time for the service to receive the request from
      * the test, then act, and respond back.
      */
-    final static int MAX_WAIT_TIME = 20;
+    final static int MAX_WAIT_TIME = 10;
 
     @Override
     public void tearDown() throws Exception {
-        stopService();
+        IpcChannel.unbindService();
         super.tearDown();
     }
 
@@ -419,15 +424,12 @@
             ChannelType localChannelType, ChannelType remoteChannelType,
             boolean expectToGetLock) throws Exception {
         try {
-            IntentReceiver.resetReceiverState();
-
             // Request that the remote lock be obtained.
-            getContext().startService(new Intent(getContext(), LockHoldingService.class)
-                    .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType)
-                    .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType));
+            IpcChannel.bindService(getContext());
+            IpcChannel.requestRemoteLock(remoteLockType, remoteChannelType);
 
             // Wait for a signal that the remote lock is definitely held.
-            assertTrue(IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+            assertTrue(IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
 
             // Try to acquire the local lock in all cases and check whether it could be acquired or
             // not as expected.
@@ -440,7 +442,7 @@
             }
             // Release the remote lock.
         } finally {
-            stopService();
+            IpcChannel.unbindService();
         }
     }
 
@@ -458,30 +460,24 @@
             ChannelType localChannelType, ChannelType remoteChannelType,
             boolean expectToWait) throws Exception {
         try {
-            IntentReceiver.resetReceiverState();
-
             // The amount of time the remote service should hold lock.
-            long remoteLockHoldTimeMillis = 10000;
+            long remoteLockHoldTimeMillis = 5000;
 
             // The amount of time test should get to try to acquire the lock.
             long sufficientOverlappingTimeInMillis = 2000;
 
             // This is the allowable delta in the time between the time recorded after the service
             // released the lock and the time recorded after the test obtained the lock.
-            long lockReleasedAndReacquiredTimeDeltaInMillis = 1000;
+            long lockReleasedAndReacquiredTimeDeltaInMillis = 500;
 
             // Tell the service to acquire a remote lock.
-            Intent sendIntent = new Intent(getContext(), LockHoldingService.class)
-                    .putExtra(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, remoteLockHoldTimeMillis)
-                    .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType)
-                    .putExtra(LockHoldingService.CHANNEL_TYPE_KEY, remoteChannelType)
-                    .putExtra(LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, true);
-
-            getContext().startService(sendIntent);
+            IpcChannel.bindService(getContext());
+            IpcChannel.requestRemoteLockAndRelease(remoteLockType,
+                    remoteChannelType, remoteLockHoldTimeMillis);
 
             // Wait for the service to hold the lock and notify for the same.
             assertTrue("No remote lock held notification",
-                    IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+                    IpcChannel.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
 
             long localLockNotObtainedTime = System.currentTimeMillis();
 
@@ -491,9 +487,9 @@
 
             // Wait until the remote lock has definitely been released.
             assertTrue("No remote lock release notification",
-                    IntentReceiver.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS));
+                    IpcChannel.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS));
 
-            Bundle remoteLockReleasedBundle = IntentReceiver.lockReleasedBundle;
+            Bundle remoteLockReleasedBundle = IpcChannel.lockReleasedBundle;
             long remoteLockNotReleasedTime =
                     remoteLockReleasedBundle.getLong(LockHoldingService.LOCK_NOT_YET_RELEASED_TIMESTAMP);
             long remoteLockReleasedTime =
@@ -544,24 +540,10 @@
             // Asserting if the fileLock is valid.
             assertTrue(fileLock.isValid());
         } finally {
-            stopService();
+            IpcChannel.unbindService();
         }
     }
 
-    /**
-     * Requests and waits for the service to stop
-     */
-    void stopService() throws Exception {
-        getContext().stopService(new Intent(getContext(), LockHoldingService.class));
-        // onStopLatch can be null if we never start the service, possibly because of
-        // an earlier failure in the test.
-        if (IntentReceiver.onStopLatch != null) {
-            assertTrue(IntentReceiver.onStopLatch.await(MAX_WAIT_TIME, SECONDS));
-        }
-
-        deleteDir(getContext());
-    }
-
     static enum LockType {
 
         /** Equivalent to {@code tryLock()} */
@@ -747,57 +729,136 @@
     }
 
     /**
-     * Listens to broadcasts sent by the LockHoldingService and records information / provides
-     * latches so the test code can synchronize until it is informed the service has acted on
-     * requests it has sent.
+     * Handles the comms with the LockHoldingService.
+     *
+     * Binds to the service and sends requests and receives callbacks from it.
+     *
+     * It records information / provides latches so the test code can synchronize until it is
+     * informed the service has acted on requests it has sent.
      */
-    public static class IntentReceiver extends BroadcastReceiver {
+    public static class IpcChannel {
 
-        static CountDownLatch onStartLatch;
+        static Context context;
 
-        static CountDownLatch onStopLatch;
-
+        static CountDownLatch onBindLatch;
+        static CountDownLatch onUnbindLatch;
         static CountDownLatch lockHeldLatch;
-
         static volatile Bundle lockHeldBundle;
-
         static CountDownLatch lockReleasedLatch;
-
         static volatile Bundle lockReleasedBundle;
 
+        static volatile boolean bound = false;
+        static Messenger messenger;
+        static Messenger responseMessenger;
+        static ServiceConnection serviceConnection;
+
+        static Handler responseMessageHandler;
+
+        private static Context getContext() {
+            return context;
+        }
+
         /**
-         * Reset the IntentReceiver for a new test. Assumes no intents will be received from prior
-         *  tests.
+         * Reset the IpcChannel for a new test. Assumes no intents will be received from prior
+         * tests.
          */
-        public static synchronized void resetReceiverState() {
-            onStartLatch = new CountDownLatch(1);
-            onStopLatch = new CountDownLatch(1);
+        static synchronized void resetReceiverState(Context testContext) {
+            context = testContext;
+            bound = false;
+            onBindLatch = new CountDownLatch(1);
+            onUnbindLatch = new CountDownLatch(1);
             lockHeldLatch = new CountDownLatch(1);
             lockReleasedLatch = new CountDownLatch(1);
             lockHeldBundle = null;
             lockReleasedBundle = null;
+
+            responseMessageHandler = new Handler(Looper.getMainLooper()) {
+                @Override
+                public void handleMessage(Message msg) {
+                    Bundle bundle = msg.getData();
+                    if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_HELD)) {
+                        lockHeldBundle = bundle;
+                        lockHeldLatch.countDown();
+                    } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_LOCK_RELEASED)) {
+                        lockReleasedBundle = bundle;
+                        lockReleasedLatch.countDown();
+                    } else if (bundle.getBoolean(LockHoldingService.NOTIFICATION_READY_FOR_SHUTDOWN)) {
+                        onUnbindLatch.countDown();
+                    } else {
+                        super.handleMessage(msg);
+                    }
+                }
+            };
+            responseMessenger = new Messenger(responseMessageHandler);
+
+            serviceConnection = new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName className, IBinder service) {
+                    messenger = new Messenger(service);
+                    bound = true;
+                    onBindLatch.countDown();
+                }
+
+                @Override
+                public void onBindingDied(ComponentName className) {
+                    getContext().unbindService(this);
+                    bound = false;
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName className) {
+                    getContext().unbindService(this);
+                    bound = false;
+                }
+            };
         }
 
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String msg = intent.getStringExtra(LockHoldingService.NOTIFICATION_KEY);
-            switch (msg) {
-                case LockHoldingService.NOTIFICATION_START:
-                    onStartLatch.countDown();
-                    break;
-                case LockHoldingService.NOTIFICATION_STOP:
-                    onStopLatch.countDown();
-                    break;
-                case LockHoldingService.NOTIFICATION_LOCK_HELD:
-                    lockHeldBundle = intent.getExtras();
-                    lockHeldLatch.countDown();
-                    break;
-                case LockHoldingService.NOTIFICATION_LOCK_RELEASED:
-                    lockReleasedBundle = intent.getExtras();
-                    lockReleasedLatch.countDown();
-                    break;
+        static void bindService(Context testContext) throws Exception {
+            resetReceiverState(testContext);
+            getContext().bindService(new Intent(getContext(), LockHoldingService.class),
+                    serviceConnection, Context.BIND_AUTO_CREATE);
+            assertTrue(onBindLatch.await(MAX_WAIT_TIME, SECONDS));
+        }
+
+        static void requestRemoteLock(LockType lockType, ChannelType channelType) throws Exception {
+            Message msg = Message.obtain(null,
+                    LockHoldingService.LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY, 0, 0);
+            Bundle bundle = msg.getData();
+            bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType);
+            bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType);
+            msg.replyTo = responseMessenger;
+            messenger.send(msg);
+        }
+
+        static void requestRemoteLockAndRelease(LockType lockType, ChannelType channelType,
+                long lockHoldTimeMillis) throws Exception {
+            Message msg = Message.obtain(null,
+                    LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY, 0, 0);
+            Bundle bundle = msg.getData();
+            bundle.putSerializable(LockHoldingService.LOCK_TYPE_KEY, lockType);
+            bundle.putSerializable(LockHoldingService.CHANNEL_TYPE_KEY, channelType);
+            bundle.putLong(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, lockHoldTimeMillis);
+            msg.replyTo = responseMessenger;
+            messenger.send(msg);
+        }
+
+        /**
+         * Requests and waits for the service to stop
+         */
+        static void unbindService() throws Exception {
+            if (bound) {
+                Message msg = Message.obtain(null, LockHoldingService.PREPARE_FOR_SHUTDOWN, 0, 0);
+                msg.replyTo = responseMessenger;
+                messenger.send(msg);
+
+                assertTrue(onUnbindLatch.await(MAX_WAIT_TIME, SECONDS));
+                getContext().unbindService(serviceConnection);
+                bound = false;
             }
+            messenger = null;
+            deleteDir(getContext());
         }
     }
+
 }
 
diff --git a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
index 0df8846..6182235 100644
--- a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
+++ b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
@@ -16,18 +16,23 @@
 
 package android.cts;
 
+import static android.cts.FileChannelInterProcessLockTest.ChannelType;
+import static android.cts.FileChannelInterProcessLockTest.LockType;
+
 import android.app.Service;
 import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
 import android.util.Log;
 
 import java.io.IOException;
 import java.nio.channels.FileLock;
 import java.util.concurrent.ExecutionException;
 
-import static android.cts.FileChannelInterProcessLockTest.ChannelType;
-import static android.cts.FileChannelInterProcessLockTest.LockType;
-
 /**
  * A Service that listens for commands from the FileChannelInterProcessLockTest to acquire locks of
  * different types. It exists to test the behavior when file locks are acquired/released across
@@ -51,16 +56,6 @@
     static final String NOTIFICATION_KEY = "notification";
 
     /**
-     * The value for the notification sent to the test after the service starts.
-     */
-    static final String NOTIFICATION_START = "onStart";
-
-    /**
-     * The value for the notification sent to the test just before the service stops.
-     */
-    static final String NOTIFICATION_STOP = "onStop";
-
-    /**
      * The value for the notification sent to the test after the lock is acquired.
      */
     static final String NOTIFICATION_LOCK_HELD = "lockHeld";
@@ -71,6 +66,11 @@
     static final String NOTIFICATION_LOCK_RELEASED = "lockReleased";
 
     /**
+     * The value for the notification sent to the test after the lock is released for shutdown
+     */
+    static final String NOTIFICATION_READY_FOR_SHUTDOWN = "readyForShutdown";
+
+    /**
      * The key of the Bundle extra used to send time for which the service should wait before
      * releasing the lock.
      */
@@ -87,72 +87,86 @@
     static final String CHANNEL_TYPE_KEY = "channelType";
 
     /**
-     * The key of the Bundle extra used to let he service know whether to release the lock after
-     * some time.
+     * The message code used to let he service know to release the lock after some time.
      */
-    static final String LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY = "releaseAndNotify";
+    static final int LOCK_BEHAVIOR_RELEASE_AND_NOTIFY = 1;
 
-    static final String ACTION_TYPE_FOR_INTENT_COMMUNICATION
-            = "android.cts.CtsLibcoreFileIOTestCases";
+    /**
+     * The message code used to let he service know to lock without releasing.
+     */
+    static final int LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY = 2;
+
+    /**
+     * The message code used to let the service know to release the lock before test end, if still
+     * held.
+     */
+    static final int PREPARE_FOR_SHUTDOWN = 3;
 
     final String LOG_MESSAGE_TAG = "CtsLibcoreFileIOTestCases";
 
     private FileLock fileLock = null;
 
-    public IBinder onBind(Intent intent) {
-        return null;
+    private class LockHoldingHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            try {
+                switch (msg.what) {
+                    case LOCK_BEHAVIOR_RELEASE_AND_NOTIFY:
+                        acquireLockAndThenWaitThenRelease(msg);
+                        break;
+                    case LOCK_BEHAVIOUR_ACQUIRE_ONLY_AND_NOTIFY:
+                        acquireLock(msg);
+                        break;
+                    case PREPARE_FOR_SHUTDOWN:
+                        prepareForShutdown(msg);
+                        break;
+                    default:
+                        super.handleMessage(msg);
+                }
+            } catch (Exception e) {
+                Log.e(LOG_MESSAGE_TAG, "Exception acquire lock", e);
+            }
+        }
     }
 
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startID) {
-        try {
-            if (intent.getBooleanExtra(LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, false)) {
-                acquireLockAndThenWaitThenRelease(intent);
-            } else {
-                acquireLock(intent);
-            }
-        } catch (Exception e) {
-            Log.e(LOG_MESSAGE_TAG, "Exception acquire lock", e);
-        }
-        return START_STICKY;
+    private Messenger messenger;
+
+    public IBinder onBind(Intent intent) {
+        messenger = new Messenger(new LockHoldingHandler());
+        return messenger.getBinder();
     }
 
     /**
      * Acquires the lock asked by the test indefinitely.
      */
-    private void acquireLock(Intent intent) throws IOException,
-            InterruptedException, ExecutionException {
-        LockType lockType = (LockType) intent.getSerializableExtra(LOCK_TYPE_KEY);
-        ChannelType channelType = (ChannelType) intent.getSerializableExtra(CHANNEL_TYPE_KEY);
+    private void acquireLock(Message msg) throws IOException,
+            InterruptedException, ExecutionException, RemoteException {
+        Bundle bundle = msg.getData();
+        LockType lockType = (LockType) bundle.get(LOCK_TYPE_KEY);
+        ChannelType channelType = (ChannelType) bundle.get(CHANNEL_TYPE_KEY);
 
         // Acquire the lock based on the information contained in the intent received.
         this.fileLock = FileChannelInterProcessLockTest.acquire(this, lockType, channelType);
-        Intent responseIntent = new Intent()
-                .setPackage("android.libcorefileio.cts")
-                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
-                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
-        sendBroadcast(responseIntent);
+
+        notifyLockHeld(msg);
     }
 
     /**
-     * Acquires and holds the lock for a time specified by the test. Sends a broadcast message after
+     * Acquires and holds the lock for a time specified by the test. Sends a response message after
      * releasing the lock.
      */
-    private void acquireLockAndThenWaitThenRelease(Intent intent)
-            throws IOException, InterruptedException, ExecutionException {
-        long lockHoldTimeMillis = intent.getLongExtra(TIME_TO_HOLD_LOCK_KEY, 0);
+    private void acquireLockAndThenWaitThenRelease(Message msg)
+            throws IOException, InterruptedException, ExecutionException, RemoteException {
+        Bundle bundle = msg.getData();
+        long lockHoldTimeMillis = bundle.getLong(TIME_TO_HOLD_LOCK_KEY, 0);
+        LockType lockType = (LockType) bundle.get(LOCK_TYPE_KEY);
+        ChannelType channelType = (ChannelType) bundle.get(CHANNEL_TYPE_KEY);
 
         // Acquire the lock.
-        LockType lockType = (LockType) intent.getSerializableExtra(LOCK_TYPE_KEY);
-        ChannelType channelType = (ChannelType) intent.getSerializableExtra(CHANNEL_TYPE_KEY);
         this.fileLock = FileChannelInterProcessLockTest.acquire(this, lockType, channelType);
 
         // Signal the lock is now held.
-        Intent heldIntent = new Intent()
-                .setPackage("android.libcorefileio.cts")
-                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
-                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
-        sendBroadcast(heldIntent);
+        notifyLockHeld(msg);
 
         Thread.sleep(lockHoldTimeMillis);
 
@@ -164,17 +178,35 @@
         long lockReleasedTimestamp = System.currentTimeMillis();
 
         // Signal the lock is released and some information about timing.
-        Intent releaseIntent = new Intent()
-                .setPackage("android.libcorefileio.cts")
-                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_RELEASED)
-                .putExtra(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp)
-                .putExtra(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp)
-                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
-        sendBroadcast(releaseIntent);
+        notifyLockReleased(msg, lockNotReleasedTimestamp, lockReleasedTimestamp);
     }
 
-    @Override
-    public void onDestroy() {
+    private void notifyLockHeld(Message msg) throws RemoteException {
+        Message rsp = msg.obtain();
+        Bundle rspBundle = rsp.getData();
+        rspBundle.putBoolean(NOTIFICATION_LOCK_HELD, true);
+        msg.replyTo.send(rsp);
+    }
+
+    private void notifyLockReleased(Message msg, long lockNotReleasedTimestamp,
+            long lockReleasedTimestamp) throws RemoteException {
+        Message rsp = msg.obtain();
+        Bundle rspBundle = rsp.getData();
+        rspBundle.putBoolean(NOTIFICATION_LOCK_RELEASED, true);
+        rspBundle.putLong(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp);
+        rspBundle.putLong(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp);
+        msg.replyTo.send(rsp);
+    }
+
+    private void prepareForShutdown(Message msg) throws RemoteException {
+        doReleaseLock();
+        Message rsp = msg.obtain();
+        Bundle rspBundle = rsp.getData();
+        rspBundle.putBoolean(NOTIFICATION_READY_FOR_SHUTDOWN, true);
+        msg.replyTo.send(rsp);
+    }
+
+    private void doReleaseLock() {
         try {
             if (fileLock != null) {
                 fileLock.release();
@@ -182,10 +214,11 @@
         } catch (IOException e) {
             Log.e(LOG_MESSAGE_TAG, e.getMessage());
         }
-        Intent intent = new Intent()
-                .setPackage("android.libcorefileio.cts")
-                .putExtra(NOTIFICATION_KEY, NOTIFICATION_STOP)
-                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
-        sendBroadcast(intent);
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        doReleaseLock();
+        return false;
     }
 }
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
index 0c5e089..9a7b3bc 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioPlaybackConfigurationTest.java
@@ -493,6 +493,10 @@
             "android.media.AudioManager.AudioPlaybackCallback#isMuted",
             "android.media.AudioManager.AudioPlaybackCallback#getMutedBy"})
     public void testAudioTrackMuteFromAppOpsNotification() throws Exception {
+        if (isWatch()) {
+            Log.w(TAG, "Skip testAudioTrackMuteFromAppOpsNotification for Wear");
+            return;
+        }
         if (!isValidPlatform("testAudioTrackMuteFromAppOpsNotification")) return;
         if (hasAudioSilentProperty()) {
             Log.w(TAG, "Device has ro.audio.silent set, skipping "
@@ -509,6 +513,10 @@
             "android.media.AudioManager.AudioPlaybackCallback#isMuted",
             "android.media.AudioManager.AudioPlaybackCallback#getMutedBy"})
     public void testMediaPlayerMuteFromAppOpsNotification() throws Exception {
+        if (isWatch()) {
+            Log.w(TAG, "Skip testMediaPlayerMuteFromAppOpsNotification for Wear");
+            return;
+        }
         if (!isValidPlatform("testMediaPlayerMuteFromAppOpsNotification")) return;
         if (hasAudioSilentProperty()) {
             Log.w(TAG, "Device has ro.audio.silent set, skipping "
@@ -700,6 +708,9 @@
                 assertTrue("onPlaybackConfigChanged play, format and device expected",
                         callback.waitForCallbacks(3,
                                 TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS));
+                if (mAt != null) {
+                    Thread.sleep(TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS);
+                }
             } else {
                 Thread.sleep(TEST_TIMING_TOLERANCE_MS + PLAY_ROUTING_TIMING_TOLERANCE_MS);
             }
@@ -1022,4 +1033,8 @@
         }
         return true;
     }
+
+    private boolean isWatch() {
+        return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
 }
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
index 91e2bb9..3090b9e 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RemoteSubmixTest.java
@@ -19,6 +19,7 @@
 import static android.media.AudioAttributes.ALLOW_CAPTURE_BY_ALL;
 
 import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -26,6 +27,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
 
 import android.media.AudioAttributes;
 import android.media.AudioAttributes.AttributeUsage;
@@ -44,6 +46,7 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.uiautomator.UiDevice;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -82,6 +85,9 @@
     private AudioManager mAudioManager;
     private MediaProjectionActivity mActivity;
     private MediaProjection mMediaProjection;
+    private Map<Integer, Integer> mStreamVolume = new HashMap<Integer, Integer>();
+    private Map<Integer, String> mStreamNames = new HashMap<Integer, String>();
+
     @Rule
     public ActivityTestRule<MediaProjectionActivity> mActivityRule =
             new ActivityTestRule<>(MediaProjectionActivity.class);
@@ -91,6 +97,14 @@
         mActivity = mActivityRule.getActivity();
         mAudioManager = mActivity.getSystemService(AudioManager.class);
         mMediaProjection = mActivity.waitForMediaProjection();
+        mStreamNames.put(AudioManager.STREAM_RING, "RING");
+        mStreamNames.put(AudioManager.STREAM_NOTIFICATION, "NOTIFICATION");
+        mStreamNames.put(AudioManager.STREAM_SYSTEM, "SYSTEM");
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        unmuteStreams();
     }
 
     private AudioRecord createPlaybackCaptureRecord() throws Exception {
@@ -153,28 +167,41 @@
         return buffer;
     }
 
+    /**
+     * Mute device audio streams
+     */
+    private void muteStreams() {
+        for (Map.Entry<Integer, String> map : mStreamNames.entrySet()) {
+            // Get current device stream volume level
+            mStreamVolume.put(map.getKey(), mAudioManager.getStreamVolume(map.getKey()));
+            // Mute device streams
+            mAudioManager.adjustStreamVolume(
+                    map.getKey(), AudioManager.ADJUST_MUTE, 0 /*no flag used*/);
+            assumeThat("Stream " + map.getValue() + " can not be muted",
+                    mAudioManager.getStreamVolume(map.getKey()), is(0));
+        }
+    }
+
+    /**
+     * Unmute device audio streams
+     */
+    private void unmuteStreams() {
+        for (Map.Entry<Integer, Integer> map : mStreamVolume.entrySet()) {
+            // Restore device stream volume
+            mAudioManager.setStreamVolume(map.getKey(), map.getValue(), 0 /*no flag used*/);
+            assertEquals("Stream " + map.getValue() + " can not be unmuted", (int) map.getValue(),
+                    mAudioManager.getStreamVolume(map.getKey()));
+        }
+        mStreamVolume.clear();
+    }
+
     public void testPlaybackCapture(boolean testWithScreenLock) throws Exception {
         MediaPlayer mediaPlayer = createMediaPlayer(
                 ALLOW_CAPTURE_BY_ALL, R.raw.sine1320hz5sec, AudioAttributes.USAGE_MEDIA);
         AudioRecord audioRecord = createPlaybackCaptureRecord();
         ByteBuffer rawBuffer = null;
 
-        int[] streams = {AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION,
-                AudioManager.STREAM_SYSTEM};
-
-        // Get current device stream volume level
-        Map<Integer, Integer> streamVolume = new HashMap<Integer, Integer>();
-        for (int stream : streams) {
-            streamVolume.put(stream, mAudioManager.getStreamVolume(stream));
-        }
         try {
-            for (int stream : streams) {
-                // Mute device streams
-                mAudioManager.adjustStreamVolume(
-                        stream, AudioManager.ADJUST_MUTE, 0 /*no flag used*/);
-                assertEquals(mAudioManager.getStreamVolume(stream), 0);
-            }
-
             audioRecord.startRecording();
             mediaPlayer.start();
 
@@ -204,12 +231,6 @@
                         .executeShellCommand("wm dismiss-keyguard");
             }
 
-            for (Map.Entry<Integer, Integer> map : streamVolume.entrySet()) {
-                // Restore device stream volume
-                mAudioManager.setStreamVolume(map.getKey(), map.getValue(), 0 /*no flag used*/);
-                assertEquals(mAudioManager.getStreamVolume(map.getKey()), (int) map.getValue());
-            }
-
             audioRecord.release();
             mediaPlayer.release();
         }
@@ -242,6 +263,7 @@
 
     @Test
     public void testRemoteSubmixRecordingContinuity() {
+        muteStreams();
         for (int i = 0; i < TEST_ITERATIONS; i++) {
             try {
                 testPlaybackCapture(/* testWithScreenLock */ false);
@@ -254,6 +276,7 @@
 
     @Test
     public void testRemoteSubmixRecordingContinuityWithScreenLock() {
+        muteStreams();
         for (int i = 0; i < TEST_ITERATIONS; i++) {
             try {
                 testPlaybackCapture(/* testWithScreenLock */ true);
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
index 660c97c..f4ace49 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/RoutingTest.java
@@ -630,7 +630,12 @@
         assertNull(mediaPlayer.getPreferredDevice());
 
         // resets to default
+        mediaPlayer.pause();
+        //Wait for state to change before setPreferDevice
+        SystemClock.sleep(200);
         assertTrue(mediaPlayer.setPreferredDevice(null));
+        mediaPlayer.start();
+        assertTrue(mediaPlayer.isPlaying());
 
         // test each device
         AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
@@ -639,12 +644,22 @@
                 // Device with type as TYPE_TELEPHONY requires a privileged permission.
                 continue;
             }
+            mediaPlayer.pause();
+            //Wait for state to change before setPreferDevice
+            SystemClock.sleep(200);
             assertTrue(mediaPlayer.setPreferredDevice(deviceList[index]));
+            mediaPlayer.start();
+            assertTrue(mediaPlayer.isPlaying());
             assertTrue(mediaPlayer.getPreferredDevice() == deviceList[index]);
         }
 
         // Check defaults again
+        mediaPlayer.pause();
+        //Wait for state to change before setPreferDevice
+        SystemClock.sleep(200);
         assertTrue(mediaPlayer.setPreferredDevice(null));
+        mediaPlayer.start();
+        assertTrue(mediaPlayer.isPlaying());
         assertNull(mediaPlayer.getPreferredDevice());
 
         mediaPlayer.stop();
@@ -737,7 +752,12 @@
         for (AudioDeviceInfo device : devices) {
             if (routedDevice.getId() != device.getId() &&
                     device.getType() != AudioDeviceInfo.TYPE_TELEPHONY) {
+                mediaPlayer.pause();
+                //Wait for state to change before setPreferDevice
+                SystemClock.sleep(200);
                 mediaPlayer.setPreferredDevice(device);
+                mediaPlayer.start();
+                assertTrue(mediaPlayer.isPlaying());
                 listener.setCallExpected(true);
                 listener.await(WAIT_ROUTING_CHANGE_TIME_MS);
                 break;
diff --git a/tests/tests/media/common/src/android/media/cts/TestUtils.java b/tests/tests/media/common/src/android/media/cts/TestUtils.java
index 552cf65..6b6fc42 100644
--- a/tests/tests/media/common/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/common/src/android/media/cts/TestUtils.java
@@ -25,15 +25,15 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
-import android.text.TextUtils;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Assert;
 import org.junit.AssumptionViolatedException;
 
+import java.util.Locale;
 import java.util.Objects;
 
 /**
@@ -154,15 +154,113 @@
     }
 
     /*
-     * Report whether we are in MTS mode (vs in CTS) mode.
+     * decide whether we are in CTS, MCTS, or MTS mode.
+     * return the appropriate constant value
+     */
+    public static final int TESTMODE_CTS = 0;
+    public static final int TESTMODE_MCTS = 1;
+    public static final int TESTMODE_MTS = 2;
+
+    /**
+     * Report the current testing mode, as an enumeration.
+     * Testing mode is determined by argument 'media-testing-mode'
+     * which specifies 'cts', 'mcts', or 'mts'
+     * If missing, we use the older boolean "mts-media" to generate either 'cts' or 'mts'
+     *
+     * This is most often specified in a CtsMedia* app's AndroidTest.xml, using
+     * a line like:
+     * <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+     * ...
+     * <option name="instrumentation-arg" key="media-testing-mode" value="CTS" />
+     * </test>
+     *
+     * @return {@code} one of the values TESTMODE_CTS, TESTMODE_MCTS, or TESTMODE_MTS.
+     *
+     */
+    public static int currentTestMode() {
+        Bundle bundle = InstrumentationRegistry.getArguments();
+        String value = bundle.getString("media-testing-mode");
+        if (value == null) {
+            value = bundle.getString("mts-media");
+            if (value == null || !value.equals("true")) {
+                value = "CTS";
+            } else {
+                value = "MTS";
+            }
+        }
+        int mode;
+        value = value.toUpperCase(Locale.ROOT);
+        if (value.equals("CTS")) {
+            mode = TESTMODE_CTS;
+        } else if (value.equals("MCTS")) {
+            mode = TESTMODE_MCTS;
+        } else if (value.equals("MTS")) {
+            mode = TESTMODE_MTS;
+        } else {
+            mode = TESTMODE_CTS;
+        }
+        return mode;
+    }
+
+    /**
+     * Report the current testing mode, as a string.
+     * Testing mode is determined by argument 'media-testing-mode'
+     * which specifies 'cts', 'mcts', or 'mts'
+     * If missing, we use the older boolean "mts-media" to generate either 'cts' or 'mts'
+     *
+     * @return {@code} "CTS", "MCTS", or "MTS" corresponding to the mode.
+     */
+    public static String currentTestModeName() {
+        Bundle bundle = InstrumentationRegistry.getArguments();
+        String value = bundle.getString("media-testing-mode");
+        if (value == null) {
+            value = bundle.getString("mts-media");
+            if (value == null || !value.equals("true")) {
+                value = "CTS";
+            } else {
+                value = "MTS";
+            }
+        }
+        value = value.toUpperCase(Locale.ROOT);
+        if (value.equals("CTS")) {
+            return "CTS";
+        } else if (value.equals("MCTS")) {
+            return "MCTS";
+        } else if (value.equals("MTS")) {
+            return "MTS";
+        } else {
+            // same default as currentTestMode()
+            return "CTS";
+        }
+    }
+
+    /**
+     * Report whether this test run should evaluate module functionality.
      * Some tests (or parts of tests) are restricted to a particular mode.
+     *
+     * @return {@code} true is the current test mode is MCTS or MTS.
+     */
+    public static boolean isTestingModules() {
+        int mode = currentTestMode();
+        switch (mode) {
+            case TESTMODE_MCTS:
+            case TESTMODE_MTS:
+                return true;
+            default:
+                break;
+        }
+        return false;
+    }
+
+    /**
+     * Report whether we are in MTS mode (vs CTS or MCTS) mode.
+     * Some tests (or parts of tests) are restricted to a particular mode.
+     *
+     * @return {@code} true is the current test mode is MTS.
      */
     public static boolean isMtsMode() {
-        Bundle bundle = InstrumentationRegistry.getArguments();
-        // null if not set
-        boolean isMTS = TextUtils.equals("true", bundle.getString("mts-media"));
-
-        return isMTS;
+        int mode = currentTestMode();
+        return mode == TESTMODE_MTS;
     }
 
     /*
@@ -180,18 +278,22 @@
      */
     public static boolean isTestableCodecInCurrentMode(String name) {
         if (name == null) {
-            return false;
-        }
-        if (!isMtsMode()) {
-            // CTS mode -- test everything
             return true;
         }
-        // MTS mode, just the codecs that live in the modules
-        if (isMainlineCodec(name)) {
-            return true;
+        int mode = currentTestMode();
+        boolean result = false;
+        switch (mode) {
+            case TESTMODE_CTS:
+                result = !isMainlineCodec(name);
+                break;
+            case TESTMODE_MCTS:
+            case TESTMODE_MTS:
+                result = isMainlineCodec(name);
+                break;
         }
-        Log.d(TAG, "Test mode MTS does not test codec " + name);
-        return false;
+        Log.d(TAG, "codec " + name + (result ? " is " : " is not ")
+                   + "tested in mode " + currentTestModeName());
+        return result;
     }
 
     /*
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
index bf4facc..b78e96c 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
@@ -62,7 +62,7 @@
 
     private static final String TAG = DecodeAccuracyTest.class.getSimpleName();
     private static final Field[] fields = R.raw.class.getFields();
-    private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
+    private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 105;
     private static final int OFFSET = 10;
     private static final long PER_TEST_TIMEOUT_MS = 60000;
     private static final String[] VIDEO_FILES = {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java
new file mode 100644
index 0000000..ed6f820
--- /dev/null
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderLowLatencyTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.decoder.cts;
+
+import static android.media.decoder.cts.DecoderTest.getAssetFileDescriptorFor;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.cts.MediaCodecWrapper;
+import android.media.cts.MediaHeavyPresubmitTest;
+import android.media.cts.MediaTestBase;
+import android.media.cts.NdkMediaCodec;
+import android.media.cts.SdkMediaCodec;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+import android.view.Surface;
+
+import androidx.test.filters.SdkSuppress;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.MediaUtils;
+import com.android.compatibility.common.util.NonMainlineTest;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@MediaHeavyPresubmitTest
+@AppModeFull(reason = "There should be no instant apps specific behavior related to decoders")
+@RunWith(Parameterized.class)
+public class DecoderLowLatencyTest extends MediaTestBase {
+    private static final String TAG = "DecoderLowLatencyTest";
+    private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
+
+    public String mTestFile;
+    public int mFrameCount;
+    public boolean mUseNdk;
+
+    public DecoderLowLatencyTest(String testFile, int frameCount, boolean useNdk) {
+        mTestFile = testFile;
+        mFrameCount = frameCount;
+        mUseNdk = useNdk;
+    }
+
+    @Before
+    @Override
+    public void setUp() throws Throwable {
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() {
+        super.tearDown();
+    }
+
+    static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+        final List<Object[]> argsList = new ArrayList<>();
+        int argLength = exhaustiveArgsList.get(0).length;
+        boolean[] boolStates = {true, false};
+        for (Object[] arg : exhaustiveArgsList) {
+            for(boolean useNdk: boolStates) {
+                Object[] testArgs = new Object[argLength + 1];
+                System.arraycopy(arg, 0, testArgs, 0, argLength);
+                testArgs[argLength] = useNdk;
+                argsList.add(testArgs);
+            }
+        }
+        return argsList;
+    }
+
+    @Parameterized.Parameters(name = "{index}_{0}")
+    public static Collection<Object[]> input() {
+        final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
+                // test video, frame count
+                // AVC
+                {"video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300},
+
+                // HEVC
+                {"video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300},
+
+                // Vp9
+                {"video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm",
+                        300},
+                {"bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm",
+                        300},
+                {"bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm",
+                        300},
+
+                // AV1
+                {"video_480x360_webm_av1_400kbps_30fps_vorbis_stereo_128kbps_48000hz.webm", 300},
+                {"video_1280x720_webm_av1_2000kbps_30fps_vorbis_stereo_128kbps_48000hz.webm", 300},
+                {"video_1920x1080_webm_av1_7000kbps_60fps_vorbis_stereo_128kbps_48000hz.webm", 300},
+                {"video_3840x2160_webm_av1_18000kbps_60fps_vorbis_stereo_128kbps_48000hz.webm",
+                        300},
+        }));
+        return prepareParamList(exhaustiveArgsList);
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
+    @NonMainlineTest
+    @Test
+    public void testLowLatencyVideo() throws Exception {
+        AssetFileDescriptor fd = getAssetFileDescriptorFor(mTestFile);
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        fd.close();
+
+        MediaFormat format = null;
+        int trackIndex = -1;
+        for (int i = 0; i < extractor.getTrackCount(); i++) {
+            format = extractor.getTrackFormat(i);
+            if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
+                trackIndex = i;
+                break;
+            }
+        }
+
+        assertTrue("No video track was found", trackIndex >= 0);
+
+        extractor.selectTrack(trackIndex);
+        format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency,
+                true /* enable */);
+
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+        String decoderName = mcl.findDecoderForFormat(format);
+        if (decoderName == null) {
+            MediaUtils.skipTest("no low latency decoder for " + format);
+            return;
+        }
+        String entry = (mUseNdk ? "NDK" : "SDK");
+        Log.v(TAG, "found " + entry + " decoder " + decoderName + " for format: " + format);
+
+        Surface surface = getActivity().getSurfaceHolder().getSurface();
+        MediaCodecWrapper decoder = null;
+        if (mUseNdk) {
+            decoder = new NdkMediaCodec(decoderName);
+        } else {
+            decoder = new SdkMediaCodec(MediaCodec.createByCodecName(decoderName));
+        }
+        format.removeFeature(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency);
+        format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1);
+        decoder.configure(format, 0 /* flags */, surface);
+        decoder.start();
+
+        if (!mUseNdk) {
+            decoder.getInputBuffers();
+        }
+        ByteBuffer[] codecOutputBuffers = decoder.getOutputBuffers();
+        String decoderOutputFormatString = null;
+
+        // start decoding
+        final long kTimeOutUs = 1000000;  // 1 second
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        int bufferCounter = 0;
+        long[] latencyMs = new long[mFrameCount];
+        boolean waitingForOutput = false;
+        long startTimeMs = System.currentTimeMillis();
+        while (bufferCounter < mFrameCount) {
+            if (!waitingForOutput) {
+                int inputBufferId = decoder.dequeueInputBuffer(kTimeOutUs);
+                if (inputBufferId < 0) {
+                    Log.v(TAG, "no input buffer");
+                    break;
+                }
+
+                ByteBuffer dstBuf = decoder.getInputBuffer(inputBufferId);
+
+                int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);
+                long presentationTimeUs = 0;
+                if (sampleSize < 0) {
+                    Log.v(TAG, "had input EOS, early termination at frame " + bufferCounter);
+                    break;
+                } else {
+                    presentationTimeUs = extractor.getSampleTime();
+                }
+
+                startTimeMs = System.currentTimeMillis();
+                decoder.queueInputBuffer(
+                        inputBufferId,
+                        0 /* offset */,
+                        sampleSize,
+                        presentationTimeUs,
+                        0 /* flags */);
+
+                extractor.advance();
+                waitingForOutput = true;
+            }
+
+            int outputBufferId = decoder.dequeueOutputBuffer(info, kTimeOutUs);
+
+            if (outputBufferId >= 0) {
+                waitingForOutput = false;
+                //Log.d(TAG, "got output, size " + info.size + ", time " + info.presentationTimeUs);
+                latencyMs[bufferCounter++] = System.currentTimeMillis() - startTimeMs;
+                // TODO: render the frame and find the rendering time to calculate the total delay
+                decoder.releaseOutputBuffer(outputBufferId, false /* render */);
+            } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                codecOutputBuffers = decoder.getOutputBuffers();
+                Log.d(TAG, "output buffers have changed.");
+            } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                decoderOutputFormatString = decoder.getOutputFormatString();
+                Log.d(TAG, "output format has changed to " + decoderOutputFormatString);
+            } else {
+                fail("No output buffer returned without frame delay, status " + outputBufferId);
+            }
+        }
+
+        assertTrue("No INFO_OUTPUT_FORMAT_CHANGED from decoder", decoderOutputFormatString != null);
+
+        long latencyMean = 0;
+        long latencyMax = 0;
+        int maxIndex = 0;
+        for (int i = 0; i < bufferCounter; ++i) {
+            latencyMean += latencyMs[i];
+            if (latencyMs[i] > latencyMax) {
+                latencyMax = latencyMs[i];
+                maxIndex = i;
+            }
+        }
+        if (bufferCounter > 0) {
+            latencyMean /= bufferCounter;
+        }
+        Log.d(TAG, entry + " latency average " + latencyMean + " ms, max " + latencyMax +
+                " ms at frame " + maxIndex);
+
+        DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, "video_decoder_latency");
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        int width = format.getInteger(MediaFormat.KEY_WIDTH);
+        int height = format.getInteger(MediaFormat.KEY_HEIGHT);
+        log.addValue("codec_name", decoderName, ResultType.NEUTRAL, ResultUnit.NONE);
+        log.addValue("mime_type", mime, ResultType.NEUTRAL, ResultUnit.NONE);
+        log.addValue("width", width, ResultType.NEUTRAL, ResultUnit.NONE);
+        log.addValue("height", height, ResultType.NEUTRAL, ResultUnit.NONE);
+        log.addValue("video_res", mTestFile, ResultType.NEUTRAL, ResultUnit.NONE);
+        log.addValue("decode_to", surface == null ? "buffer" : "surface",
+                ResultType.NEUTRAL, ResultUnit.NONE);
+
+        log.addValue("average_latency", latencyMean, ResultType.LOWER_BETTER, ResultUnit.MS);
+        log.addValue("max_latency", latencyMax, ResultType.LOWER_BETTER, ResultUnit.MS);
+
+        log.submit(getInstrumentation());
+
+        decoder.stop();
+        decoder.release();
+        extractor.release();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index b29e416..c93c0f0 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -3839,6 +3839,21 @@
         Thread.sleep(200);
         mMediaCodecPlayer.stopDrainingAudioOutputBuffers(false);
 
+        // Wait until underrun recovers, otherwise false detection of end of playback occurs
+        {
+            long underrunRecoveryTimeoutMs = 200;
+            long startTimeMs = System.currentTimeMillis();
+            AudioTimestamp previousTimestamp;
+            do {
+              assertTrue(String.format("No underrun recovery after %d milliseconds",
+                              underrunRecoveryTimeoutMs),
+                      System.currentTimeMillis() - startTimeMs < underrunRecoveryTimeoutMs);
+              previousTimestamp = mMediaCodecPlayer.getTimestamp();
+              Thread.sleep(50);
+            } while (mMediaCodecPlayer.getTimestamp().framePosition
+                    == previousTimestamp.framePosition);
+        }
+
         // Sleep till framePosition stabilizes, i.e. playback is complete
         {
             long endOfPlayackTimeoutMs = 20000;
@@ -4503,206 +4518,4 @@
         PackageManager pm = mContext.getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
     }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
-    @Test
-    public void testLowLatencyVp9At1280x720() throws Exception {
-        testLowLatencyVideo(
-                "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
-                false /* useNdk */);
-        testLowLatencyVideo(
-                "video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm", 300,
-                true /* useNdk */);
-    }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
-    @Test
-    public void testLowLatencyVp9At1920x1080() throws Exception {
-        testLowLatencyVideo(
-                "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
-                false /* useNdk */);
-        testLowLatencyVideo(
-                "bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm", 300,
-                true /* useNdk */);
-    }
-
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
-    @Test
-    public void testLowLatencyVp9At3840x2160() throws Exception {
-        testLowLatencyVideo(
-                "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
-                false /* useNdk */);
-        testLowLatencyVideo(
-                "bbb_s2_3840x2160_webm_vp9_0p51_20mbps_60fps_vorbis_6ch_384kbps_32000hz.webm", 300,
-                true /* useNdk */);
-    }
-
-    @NonMainlineTest
-    @Test
-    public void testLowLatencyAVCAt1280x720() throws Exception {
-        testLowLatencyVideo(
-                "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
-                false /* useNdk */);
-        testLowLatencyVideo(
-                "video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4", 300,
-                true /* useNdk */);
-    }
-
-    @NonMainlineTest
-    @Test
-    public void testLowLatencyHEVCAt480x360() throws Exception {
-        testLowLatencyVideo(
-                "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
-                false /* useNdk */);
-        testLowLatencyVideo(
-                "video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4", 300,
-                true /* useNdk */);
-    }
-
-    private void testLowLatencyVideo(String testVideo, int frameCount, boolean useNdk)
-            throws Exception {
-        AssetFileDescriptor fd = getAssetFileDescriptorFor(testVideo);
-        MediaExtractor extractor = new MediaExtractor();
-        extractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
-        fd.close();
-
-        MediaFormat format = null;
-        int trackIndex = -1;
-        for (int i = 0; i < extractor.getTrackCount(); i++) {
-            format = extractor.getTrackFormat(i);
-            if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
-                trackIndex = i;
-                break;
-            }
-        }
-
-        assertTrue("No video track was found", trackIndex >= 0);
-
-        extractor.selectTrack(trackIndex);
-        format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency,
-                true /* enable */);
-
-        MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
-        String decoderName = mcl.findDecoderForFormat(format);
-        if (decoderName == null) {
-            MediaUtils.skipTest("no low latency decoder for " + format);
-            return;
-        }
-        String entry = (useNdk ? "NDK" : "SDK");
-        Log.v(TAG, "found " + entry + " decoder " + decoderName + " for format: " + format);
-
-        Surface surface = getActivity().getSurfaceHolder().getSurface();
-        MediaCodecWrapper decoder = null;
-        if (useNdk) {
-            decoder = new NdkMediaCodec(decoderName);
-        } else {
-            decoder = new SdkMediaCodec(MediaCodec.createByCodecName(decoderName));
-        }
-        format.removeFeature(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency);
-        format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1);
-        decoder.configure(format, 0 /* flags */, surface);
-        decoder.start();
-
-        if (!useNdk) {
-            decoder.getInputBuffers();
-        }
-        ByteBuffer[] codecOutputBuffers = decoder.getOutputBuffers();
-        String decoderOutputFormatString = null;
-
-        // start decoding
-        final long kTimeOutUs = 1000000;  // 1 second
-        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        int bufferCounter = 0;
-        long[] latencyMs = new long[frameCount];
-        boolean waitingForOutput = false;
-        long startTimeMs = System.currentTimeMillis();
-        while (bufferCounter < frameCount) {
-            if (!waitingForOutput) {
-                int inputBufferId = decoder.dequeueInputBuffer(kTimeOutUs);
-                if (inputBufferId < 0) {
-                    Log.v(TAG, "no input buffer");
-                    break;
-                }
-
-                ByteBuffer dstBuf = decoder.getInputBuffer(inputBufferId);
-
-                int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);
-                long presentationTimeUs = 0;
-                if (sampleSize < 0) {
-                    Log.v(TAG, "had input EOS, early termination at frame " + bufferCounter);
-                    break;
-                } else {
-                    presentationTimeUs = extractor.getSampleTime();
-                }
-
-                startTimeMs = System.currentTimeMillis();
-                decoder.queueInputBuffer(
-                        inputBufferId,
-                        0 /* offset */,
-                        sampleSize,
-                        presentationTimeUs,
-                        0 /* flags */);
-
-                extractor.advance();
-                waitingForOutput = true;
-            }
-
-            int outputBufferId = decoder.dequeueOutputBuffer(info, kTimeOutUs);
-
-            if (outputBufferId >= 0) {
-                waitingForOutput = false;
-                //Log.d(TAG, "got output, size " + info.size + ", time " + info.presentationTimeUs);
-                latencyMs[bufferCounter++] = System.currentTimeMillis() - startTimeMs;
-                // TODO: render the frame and find the rendering time to calculate the total delay
-                decoder.releaseOutputBuffer(outputBufferId, false /* render */);
-            } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                codecOutputBuffers = decoder.getOutputBuffers();
-                Log.d(TAG, "output buffers have changed.");
-            } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                decoderOutputFormatString = decoder.getOutputFormatString();
-                Log.d(TAG, "output format has changed to " + decoderOutputFormatString);
-            } else {
-                fail("No output buffer returned without frame delay, status " + outputBufferId);
-            }
-        }
-
-        assertTrue("No INFO_OUTPUT_FORMAT_CHANGED from decoder", decoderOutputFormatString != null);
-
-        long latencyMean = 0;
-        long latencyMax = 0;
-        int maxIndex = 0;
-        for (int i = 0; i < bufferCounter; ++i) {
-            latencyMean += latencyMs[i];
-            if (latencyMs[i] > latencyMax) {
-                latencyMax = latencyMs[i];
-                maxIndex = i;
-            }
-        }
-        if (bufferCounter > 0) {
-            latencyMean /= bufferCounter;
-        }
-        Log.d(TAG, entry + " latency average " + latencyMean + " ms, max " + latencyMax +
-                " ms at frame " + maxIndex);
-
-        DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, "video_decoder_latency");
-        String mime = format.getString(MediaFormat.KEY_MIME);
-        int width = format.getInteger(MediaFormat.KEY_WIDTH);
-        int height = format.getInteger(MediaFormat.KEY_HEIGHT);
-        log.addValue("codec_name", decoderName, ResultType.NEUTRAL, ResultUnit.NONE);
-        log.addValue("mime_type", mime, ResultType.NEUTRAL, ResultUnit.NONE);
-        log.addValue("width", width, ResultType.NEUTRAL, ResultUnit.NONE);
-        log.addValue("height", height, ResultType.NEUTRAL, ResultUnit.NONE);
-        log.addValue("video_res", testVideo, ResultType.NEUTRAL, ResultUnit.NONE);
-        log.addValue("decode_to", surface == null ? "buffer" : "surface",
-                ResultType.NEUTRAL, ResultUnit.NONE);
-
-        log.addValue("average_latency", latencyMean, ResultType.LOWER_BETTER, ResultUnit.MS);
-        log.addValue("max_latency", latencyMax, ResultType.LOWER_BETTER, ResultUnit.MS);
-
-        log.submit(getInstrumentation());
-
-        decoder.stop();
-        decoder.release();
-        extractor.release();
-    }
 }
diff --git a/tests/tests/media/extractor/AndroidTest.xml b/tests/tests/media/extractor/AndroidTest.xml
index e88c69c..6df771d 100644
--- a/tests/tests/media/extractor/AndroidTest.xml
+++ b/tests/tests/media/extractor/AndroidTest.xml
@@ -41,7 +41,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.1" />
+        <option name="media-folder-name" value="CtsMediaExtractorTestCases-2.2" />
         <option name="dynamic-config-module" value="CtsMediaExtractorTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/extractor/DynamicConfig.xml b/tests/tests/media/extractor/DynamicConfig.xml
index 0056677..766524c 100644
--- a/tests/tests/media/extractor/DynamicConfig.xml
+++ b/tests/tests/media/extractor/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-    <value>https://dl.google.com/android/xts/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.1.zip</value>
+    <value>https://dl.google.com/android/xts/cts/tests/tests/media/extractor/CtsMediaExtractorTestCases-2.2.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/media/extractor/copy_media.sh b/tests/tests/media/extractor/copy_media.sh
index 8b83bdf..b4e5ba0 100755
--- a/tests/tests/media/extractor/copy_media.sh
+++ b/tests/tests/media/extractor/copy_media.sh
@@ -17,4 +17,4 @@
 [ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
 source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
 get_adb_options "$@"
-copy_media "extractor" "CtsMediaExtractorTestCases-2.1"
+copy_media "extractor" "CtsMediaExtractorTestCases-2.2"
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
index d4e3ff4..5177551 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/MediaExtractorTest.java
@@ -372,6 +372,22 @@
         assertEquals("video/av01", mimeType);
     }
 
+    // DolbyVisionMediaExtractor for trimmed Dolby Vision file.
+    // Please check https://issuetracker.google.com/329121650 for details.
+    @Test
+    public void testTrimmedDolbyVisionFileTrackDuration() throws Exception {
+        TestMediaDataSource dataSource = setDataSource("video_dovi_dvhe_08_trimmed.mp4");
+
+        final int trackCount = mExtractor.getTrackCount();
+        assertTrue("There should be at least one track", 0 < trackCount);
+
+        long expectedTrackDurationUs = 3_026_666;
+        for (int i = 0; i < trackCount; i++) {
+            MediaFormat trackFormat = mExtractor.getTrackFormat(i);
+            assertEquals(expectedTrackDurationUs, trackFormat.getLong(MediaFormat.KEY_DURATION));
+        }
+    }
+
     //MPEG-H 3D Audio single stream (mha1)
     @Test
     public void testMpegh3dAudioMediaExtractorMha1() throws Exception {
diff --git a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
index 8b847e2..31c069e 100644
--- a/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
+++ b/tests/tests/media/extractor/src/android/media/extractor/cts/WorkDir.java
@@ -20,6 +20,6 @@
 
 class WorkDir extends WorkDirBase {
     public static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaExtractorTestCases-2.1");
+        return getMediaDirString("CtsMediaExtractorTestCases-2.2");
     }
 }
diff --git a/tests/tests/media/misc/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
index ed3133f..546a15b 100644
--- a/tests/tests/media/misc/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -41,7 +41,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaMiscTestCases-2.2" />
+        <option name="media-folder-name" value="CtsMediaMiscTestCases-2.3" />
         <option name="dynamic-config-module" value="CtsMediaMiscTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/media/misc/DynamicConfig.xml b/tests/tests/media/misc/DynamicConfig.xml
index ed21ce3..2eec449 100644
--- a/tests/tests/media/misc/DynamicConfig.xml
+++ b/tests/tests/media/misc/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-    <value>https://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.2.zip</value>
+    <value>https://dl.google.com/android/xts/cts/tests/tests/media/misc/CtsMediaMiscTestCases-2.3.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/media/misc/copy_media.sh b/tests/tests/media/misc/copy_media.sh
index c838197..16538a1 100755
--- a/tests/tests/media/misc/copy_media.sh
+++ b/tests/tests/media/misc/copy_media.sh
@@ -17,4 +17,4 @@
 [ -z "$MEDIA_ROOT_DIR" ] && MEDIA_ROOT_DIR=$(dirname $0)/..
 source $MEDIA_ROOT_DIR/common/copy_media_utils.sh
 get_adb_options "$@"
-copy_media "misc" "CtsMediaMiscTestCases-2.2"
+copy_media "misc" "CtsMediaMiscTestCases-2.3"
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
index 8c5bf2f..020fd09 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
@@ -1242,17 +1242,15 @@
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
             codeName = "VanillaIceCream")
     public void testGetImageAtIndexAvifWithCrop() throws Exception {
-        // sample_1960x1120_crop_20_20_1920_1080.avif is a 1960x1120 AVIF image with the crop window
-        // set to left: 20 top: 20 crop width: 1920 crop height: 1080. The cropped image should
+        // sample_720x480_crop_20_20_680_440.avif is a 720x480 AVIF image with the crop window
+        // set to left: 20 top: 20 crop width: 680 crop height: 440. The cropped image should
         // contain the same pixels as other sample AVIF images. So in order to verify the cropping,
         // it is sufficient to pass checkColor to true to testGetImage.  If the cropping was
         // incorrect, then checking of color bars will fail. The expected width and height should be
         // that of the cropped image.
-        if (!MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, 1960, 1120, 30)) {
-            MediaUtils.skipTest("No AV1 codec for 1960x1120");
-            return;
-        }
-        testGetImage("sample_1960x1120_crop_20_20_1920_1080.avif", 1920, 1080, "image/avif",
+        assumeTrue("No AV1 codec for 720x480",
+                MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AV1, 720, 480, 30));
+        testGetImage("sample_720x480_crop_20_20_680_440.avif", 680, 440, "image/avif",
                 0 /*rotation*/, 1 /*imageCount*/, 0 /*primary*/, false /*useGrid*/,
                 true /*checkColor*/);
     }
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
index 6cbab7c..e8e3e18 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
@@ -20,6 +20,6 @@
 
 class WorkDir extends WorkDirBase {
     public static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaMiscTestCases-2.2");
+        return getMediaDirString("CtsMediaMiscTestCases-2.3");
     }
 }
diff --git a/tests/tests/mediacujtest/common/Android.bp b/tests/tests/mediacujtest/common/Android.bp
index 67b6f4c..4a9ed91 100644
--- a/tests/tests/mediacujtest/common/Android.bp
+++ b/tests/tests/mediacujtest/common/Android.bp
@@ -39,6 +39,6 @@
         "src/**/*.java",
     ],
     plugins: ["auto_value_plugin"],
+    platform_apis: true,
     min_sdk_version: "30",
-    sdk_version: "current",
 }
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
index 6181f8e..3b246cb 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/CujTestBase.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 
 import android.app.Activity;
+import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -93,6 +94,13 @@
   }
 
   /**
+   * Whether the device supports split-screen feature.
+   */
+  public static boolean deviceSupportSplitScreenMode(final Activity activity) {
+    return ActivityTaskManager.supportsSplitScreenMultiWindow(activity);
+  }
+
+  /**
    * Whether the device is a watch.
    */
   public static boolean isWatchDevice(final Activity activity) {
diff --git a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
index df7fcb7..1a97ce8 100644
--- a/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
+++ b/tests/tests/mediacujtest/common/src/android/media/cujcommon/cts/MainActivity.java
@@ -71,7 +71,7 @@
     mExoplayerView = findViewById(R.id.exoplayer);
     mLockControllerButton = findViewById(R.id.lock_controller);
     mLockControllerButton.setVisibility(View.INVISIBLE);
-    mExoRewindButton = findViewById(R.id.exo_rew_with_amount);
+    mExoRewindButton = findViewById(androidx.media3.ui.R.id.exo_rew_with_amount);
     mExoplayerView.setPlayer(mPlayer);
   }
 
diff --git a/tests/tests/mediacujtest/largetest/AndroidManifest.xml b/tests/tests/mediacujtest/largetest/AndroidManifest.xml
index 8b2be7a..a58d3dd 100644
--- a/tests/tests/mediacujtest/largetest/AndroidManifest.xml
+++ b/tests/tests/mediacujtest/largetest/AndroidManifest.xml
@@ -40,9 +40,6 @@
     android:label="Media E2E tests InstrumentationRunner"
     android:name="androidx.test.runner.AndroidJUnitRunner"
     android:targetPackage="android.media.cujlargetest.cts">
-    <meta-data
-      android:name="listener"
-      android:value="com.android.cts.runner.CtsTestRunListener" />
   </instrumentation>
 </manifest>
 
diff --git a/tests/tests/mediacujtest/smalltest/AndroidManifest.xml b/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
index a748dbe..3d98870 100644
--- a/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
+++ b/tests/tests/mediacujtest/smalltest/AndroidManifest.xml
@@ -38,8 +38,5 @@
     android:label="Media E2E tests InstrumentationRunner"
     android:name="androidx.test.runner.AndroidJUnitRunner"
     android:targetPackage="android.media.cujsmalltest.cts">
-    <meta-data
-      android:name="listener"
-      android:value="com.android.cts.runner.CtsTestRunListener" />
   </instrumentation>
 </manifest>
diff --git a/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java b/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
index 64c3081..6930263 100644
--- a/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
+++ b/tests/tests/mediacujtest/smalltest/src/android/media/cujsmalltest/cts/CtsMediaShortFormPlaybackTest.java
@@ -309,7 +309,8 @@
           deviceSupportPipMode(mActivity));
     }
     if (mCujTestParam.playerListener().isSplitScreenTest()) {
-      Assume.assumeFalse("Skipping " + mTestType + " on television", isTelevisionDevice(mActivity));
+      Assume.assumeTrue("Skipping " + mTestType + " as device doesn't support split screen feature",
+          deviceSupportSplitScreenMode(mActivity));
     }
     if (mCujTestParam.playerListener().getTestType()
         .equals(TestType.LOCK_PLAYBACK_CONTROLLER_TEST)) {
diff --git a/tests/tests/mediaediting/AndroidManifest.xml b/tests/tests/mediaediting/AndroidManifest.xml
index 789cd48..72e76c1 100644
--- a/tests/tests/mediaediting/AndroidManifest.xml
+++ b/tests/tests/mediaediting/AndroidManifest.xml
@@ -31,8 +31,6 @@
   <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
        android:targetPackage="android.media.mediaediting.cts"
        android:label="Media editing tests InstrumentationRunner">
-      <meta-data android:name="listener"
-           android:value="com.android.cts.runner.CtsTestRunListener"/>
   </instrumentation>
 
 </manifest>
diff --git a/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java b/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
index 6517f2f..d3749c9 100644
--- a/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
+++ b/tests/tests/mediaediting/src/android/media/mediaediting/cts/AndroidTestUtil.java
@@ -628,7 +628,9 @@
         if (image == null) {
           break;
         }
-        bitmaps.add(BitmapPixelTestUtil.createGrayscaleArgb8888BitmapFromYuv420888Image(image));
+        bitmaps.add(
+            BitmapPixelTestUtil.createGrayscaleBitmapFromYuv420888Image(
+                image, Bitmap.Config.ARGB_8888));
         image.close();
       }
     }
diff --git a/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java b/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
index 94ae747..f72b1b6 100644
--- a/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
+++ b/tests/tests/mediaediting/src/android/media/mediaediting/cts/TranscodeQualityTest.java
@@ -196,6 +196,12 @@
             .setRequestCalculateSsim(true)
             .build()
             .run(testId, editedMediaItem);
+
+    if (!isWithinCddRequirements) {
+        Assume.assumeFalse("Skipping transcodeTest for " + testId,
+            result.fallbackDetails != null
+            && result.fallbackDetails.fallbackOutputHeight != height);
+    }
     assertThat(result.ssim).isGreaterThan(EXPECTED_MINIMUM_SSIM);
   }
 }
diff --git a/tests/tests/networksecurityconfig/manifest.xml b/tests/tests/networksecurityconfig/manifest.xml
index 2950baf..93250d7 100644
--- a/tests/tests/networksecurityconfig/manifest.xml
+++ b/tests/tests/networksecurityconfig/manifest.xml
@@ -28,7 +28,5 @@
   <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                    android:targetPackage="android.security.net.config.cts"
                    android:label="">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
     </instrumentation>
 </manifest>
diff --git a/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
index c875c2f..85ec4a0 100644
--- a/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
+++ b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
@@ -163,4 +163,18 @@
             assertNotInCpuinfo(features, feature);
         }
     }
+
+    public void testNoSerial() throws IOException {
+        String serial = getFieldFromCpuinfo("Serial");
+        if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArm64CpuIn32BitMode()) {
+            // A 64-bit arm kernel shouldn't have a serial field at all.
+            assertTrue(serial == null);
+        } else if (CpuFeatures.isArmCpu()) {
+            // By default a 32-bit kernel will have a serial field, but it
+            // should be set to all zeros. See http://b/313425671.
+            if (serial != null) {
+                assertEquals("0000000000000000", serial);
+            }
+        }
+    }
 }
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 3d53c5d..beeb7f7 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -33,6 +33,7 @@
 
 import android.app.PendingIntent;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.os.Environment;
@@ -422,7 +423,11 @@
         mStorageManager.registerStorageVolumeCallback(mContext.getMainExecutor(), callback);
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .executeShellCommand("sm unmount emulated;" + UserHandle.myUserId());
-        assertTrue(unmounted.await(30, TimeUnit.SECONDS));
+        if (isAutomotive(mContext)) {
+            assertTrue(unmounted.await(45, TimeUnit.SECONDS));
+        } else {
+            assertTrue(unmounted.await(30, TimeUnit.SECONDS));
+        }
 
         // Now unregister and verify we don't hear future events
         mStorageManager.unregisterStorageVolumeCallback(callback);
@@ -1086,6 +1091,11 @@
         }
     }
 
+    private boolean isAutomotive(Context context) {
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
     @Test
     public void testComputeStorageCacheBytes() throws Exception {
         File mockFile = mock(File.class);
diff --git a/tests/tests/security/res/raw/blocklist_diginotar.pem b/tests/tests/security/res/raw/blocklist_diginotar.pem
new file mode 100644
index 0000000..b972b4b
--- /dev/null
+++ b/tests/tests/security/res/raw/blocklist_diginotar.pem
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFijCCA3KgAwIBAgIQDHbanJEMTiye/hXQWJM8TDANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp
+Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww
+HhcNMDcwNTE2MTcxOTM2WhcNMjUwMzMxMTgxOTIxWjBfMQswCQYDVQQGEwJOTDES
+MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg
+MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B
+8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY
+tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl
+HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj
+zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU
+JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM
+ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv
+a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p
+K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi
+puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT
+yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO
+owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC
+jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy
+fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo
+Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo
+M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM
+Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed
+2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH
+/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl
+nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE
+O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU
+9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9
+j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr
+-----END CERTIFICATE-----
diff --git a/tests/tests/security/res/raw/blacklist_test_chain.pem b/tests/tests/security/res/raw/blocklist_test_chain.pem
similarity index 100%
rename from tests/tests/security/res/raw/blacklist_test_chain.pem
rename to tests/tests/security/res/raw/blocklist_test_chain.pem
diff --git a/tests/tests/security/res/raw/blacklist_test_valid_ca.pem b/tests/tests/security/res/raw/blocklist_test_valid_ca.pem
similarity index 100%
rename from tests/tests/security/res/raw/blacklist_test_valid_ca.pem
rename to tests/tests/security/res/raw/blocklist_test_valid_ca.pem
diff --git a/tests/tests/security/res/raw/blacklist_test_valid_chain.pem b/tests/tests/security/res/raw/blocklist_test_valid_chain.pem
similarity index 100%
rename from tests/tests/security/res/raw/blacklist_test_valid_chain.pem
rename to tests/tests/security/res/raw/blocklist_test_valid_chain.pem
diff --git a/tests/tests/security/res/raw/test_blacklist_ca.pem b/tests/tests/security/res/raw/test_blocklist_ca.pem
similarity index 100%
rename from tests/tests/security/res/raw/test_blacklist_ca.pem
rename to tests/tests/security/res/raw/test_blocklist_ca.pem
diff --git a/tests/tests/security/src/android/security/cts/CertBlacklistTest.java b/tests/tests/security/src/android/security/cts/CertBlocklistTest.java
similarity index 62%
rename from tests/tests/security/src/android/security/cts/CertBlacklistTest.java
rename to tests/tests/security/src/android/security/cts/CertBlocklistTest.java
index d7a199e..fde5bc9 100644
--- a/tests/tests/security/src/android/security/cts/CertBlacklistTest.java
+++ b/tests/tests/security/src/android/security/cts/CertBlocklistTest.java
@@ -16,70 +16,80 @@
 
 package android.security.cts;
 
-import android.content.Context;
 import android.test.AndroidTestCase;
 
 import java.io.InputStream;
-import java.util.Collection;
+import java.security.KeyStore;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.security.KeyStore;
+import java.util.Collection;
+
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
 /**
- * End to end version of org.conscrypt.CertBlacklistTest that tests the platform default
+ * End to end version of org.conscrypt.CertBlocklistTest that tests the platform default
  * {@link X509TrustManager}.
  *
- * The test blacklisted CA's private key can be found in
- * external/conscrypt/src/test/resources/blacklist_ca_key.pem
+ * The test blocklisted CA's private key can be found in
+ * external/conscrypt/src/test/resources/blocklist_ca_key.pem
  */
-public class CertBlacklistTest extends AndroidTestCase {
+public class CertBlocklistTest extends AndroidTestCase {
 
-    private static final int BLACKLIST_CA = R.raw.test_blacklist_ca;
-    private static final int BLACKLISTED_CHAIN = R.raw.blacklist_test_chain;
-    private static final int BLACKLIST_FALLBACK_VALID_CA = R.raw.blacklist_test_valid_ca;
-    private static final int BLACKLISTED_VALID_CHAIN = R.raw.blacklist_test_valid_chain;
+    private static final int BLOCKLIST_CA = R.raw.test_blocklist_ca;
+    private static final int BLOCKLIST_DIGINOTAR = R.raw.blocklist_diginotar;
+    private static final int BLOCKLISTED_CHAIN = R.raw.blocklist_test_chain;
+    private static final int BLOCKLIST_FALLBACK_VALID_CA = R.raw.blocklist_test_valid_ca;
+    private static final int BLOCKLISTED_VALID_CHAIN = R.raw.blocklist_test_valid_chain;
 
     /**
-     * Checks that the blacklisted CA is rejected even if it used as a root of trust
+     * Checks that the blocklisted CA is rejected even if it used as a root of trust
      */
-    public void testBlacklistedCaUntrusted() throws Exception {
-        X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
-        assertUntrusted(new X509Certificate[] {blacklistedCa}, getTrustManager(blacklistedCa));
+    public void testBlocklistedCaUntrusted() throws Exception {
+        X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+        assertUntrusted(new X509Certificate[] {blocklistedCa}, getTrustManager(blocklistedCa));
     }
 
     /**
-     * Checks that a chain that is rooted in a blacklisted trusted CA is rejected.
+     * Checks that a known compromised CA certificate is blocked.
      */
-    public void testBlacklistedRootOfTrust() throws Exception {
-        // Chain is leaf -> blacklisted
-        X509Certificate[] chain = loadCertificates(BLACKLISTED_CHAIN);
-        X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
-        assertUntrusted(chain, getTrustManager(blacklistedCa));
+    public void testBlocklistedDiginotar() throws Exception {
+        // Public Key SHA1 = 410f36363258f30b347d12ce4863e433437806a8
+        X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_DIGINOTAR);
+        assertUntrusted(new X509Certificate[] {blocklistedCa}, getTrustManager(blocklistedCa));
     }
 
     /**
-     * Tests that the path building correctly routes around a blacklisted cert where there are
+     * Checks that a chain that is rooted in a blocklisted trusted CA is rejected.
+     */
+    public void testBlocklistedRootOfTrust() throws Exception {
+        // Chain is leaf -> blocklisted
+        X509Certificate[] chain = loadCertificates(BLOCKLISTED_CHAIN);
+        X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+        assertUntrusted(chain, getTrustManager(blocklistedCa));
+    }
+
+    /**
+     * Tests that the path building correctly routes around a blocklisted cert where there are
      * other valid paths available. This prevents breakage where a cert was cross signed by a
-     * blacklisted CA but is still valid due to also being cross signed by CAs that remain trusted.
+     * blocklisted CA but is still valid due to also being cross signed by CAs that remain trusted.
      * Path:
      *
-     * leaf -> intermediate -> blacklisted_ca
+     * leaf -> intermediate -> blocklisted_ca
      *               \
      *                -------> trusted_ca
      */
-    public void testBlacklistedIntermediateFallback() throws Exception {
-        X509Certificate[] chain = loadCertificates(BLACKLISTED_VALID_CHAIN);
-        X509Certificate blacklistedCa = loadCertificate(BLACKLIST_CA);
-        X509Certificate validCa = loadCertificate(BLACKLIST_FALLBACK_VALID_CA);
-        assertTrusted(chain, getTrustManager(blacklistedCa, validCa));
+    public void testBlocklistedIntermediateFallback() throws Exception {
+        X509Certificate[] chain = loadCertificates(BLOCKLISTED_VALID_CHAIN);
+        X509Certificate blocklistedCa = loadCertificate(BLOCKLIST_CA);
+        X509Certificate validCa = loadCertificate(BLOCKLIST_FALLBACK_VALID_CA);
+        assertTrusted(chain, getTrustManager(blocklistedCa, validCa));
         // Check that without the trusted_ca the chain is invalid (since it only chains to a
-        // blacklisted ca)
-        assertUntrusted(chain, getTrustManager(blacklistedCa));
+        // blocklisted ca)
+        assertUntrusted(chain, getTrustManager(blocklistedCa));
     }
 
     private X509Certificate loadCertificate(int resId) throws Exception {
diff --git a/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java b/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
index f0a6d89..046429e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BackgroundCallAudioTest.java
@@ -226,7 +226,7 @@
     }
 
     public void testAudioProcessingFromCallScreeningAllowPlaceEmergencyCall() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -271,7 +271,7 @@
     }
 
     public void testAudioProcessingFromIncomingActivePlaceEmergencyCall() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -379,7 +379,7 @@
     }
 
     public void testAudioProcessOutgoingActiveEmergencyCallPlaced() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
index 39b8774..961ebb7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallRedirectionServiceTest.java
@@ -218,7 +218,7 @@
     }
 
     public void testCantRedirectEmergencyCall() throws Exception {
-        if (!shouldTestTelecom(mContext)) {
+        if (!shouldTestTelecom(mContext) || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         Bundle extras = new Bundle();
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 4890bdf..1e2f40b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -863,7 +863,7 @@
     }
 
     public void testOnCannedTextResponsesLoaded() {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java b/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
index 57ec66c..ec68a42 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExternalCallTest.java
@@ -118,7 +118,7 @@
      * CAPABILITY_CAN_PLACE_CALL capability is removed.
      */
     public void testPullCallCapabilityRemovedInEmergencyCall() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -140,7 +140,7 @@
      * ongoing emergency call, the request is not completed.
      */
     public void testTryToPullCallWhileInEmergencyCall() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
         setupForEmergencyCalling(TEST_EMERGENCY_NUMBER);
@@ -166,7 +166,7 @@
      * test to check external call and pull external call with call and connection states check
      */
     public void testExternalCallAndPullCall() throws Exception {
-        if (!mShouldTestTelecom  || !TestUtils.hasTelephonyFeature(mContext)) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java b/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
index cb2ecd5..7d20eae 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TelecomManagerTest.java
@@ -151,7 +151,7 @@
     }
 
     public void testIsInEmergencyCall_ongoingEmergencyCall() throws Exception {
-        if (!mShouldTestTelecom) {
+        if (!mShouldTestTelecom || !TestUtils.hasTelephonyFeature(mContext)) {
             return;
         }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java b/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
index ca0cee2..b63e1de 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/AsyncSmsMessageListener.java
@@ -34,6 +34,15 @@
             new LinkedBlockingQueue<>(1);
 
     /**
+     * Clear internal cache data.
+     */
+    public void clear() {
+        mMessages.clear();
+        mSentMessageResults.clear();
+        mDeliveredMessageResults.clear();
+    }
+
+    /**
      * Offer a SMS message to the queue of SMS messages waiting to be processed.
      */
     public void offerSmsMessage(String smsMessage) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
index 16bb603..f24024f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
@@ -126,6 +126,10 @@
             new ShortCodeTest("be", "6566", SMS_CATEGORY_PREMIUM_SHORT_CODE),
             new ShortCodeTest("be", "7777", SMS_CATEGORY_PREMIUM_SHORT_CODE),
 
+            new ShortCodeTest("bf", "35696", SMS_CATEGORY_NOT_SHORT_CODE),
+            new ShortCodeTest("bf", "3681", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+            new ShortCodeTest("bf", "3558", SMS_CATEGORY_FREE_SHORT_CODE),
+
             new ShortCodeTest("bg", "112", SMS_CATEGORY_NOT_SHORT_CODE),
             new ShortCodeTest("bg", "116117", SMS_CATEGORY_FREE_SHORT_CODE),
             new ShortCodeTest("bg", "1234", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
@@ -349,10 +353,12 @@
             new ShortCodeTest("il", "6688", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
             new ShortCodeTest("il", "6681", SMS_CATEGORY_FREE_SHORT_CODE),
 
-            new ShortCodeTest("ir", "7007924", SMS_CATEGORY_NOT_SHORT_CODE),
-            new ShortCodeTest("ir", "700799", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
+            new ShortCodeTest("ir", "300086178", SMS_CATEGORY_NOT_SHORT_CODE),
+            new ShortCodeTest("ir", "30008790",SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
             new ShortCodeTest("ir", "700792", SMS_CATEGORY_FREE_SHORT_CODE),
             new ShortCodeTest("ir", "700791", SMS_CATEGORY_FREE_SHORT_CODE),
+            new ShortCodeTest("ir", "100016", SMS_CATEGORY_FREE_SHORT_CODE),
+            new ShortCodeTest("ir", "30008360", SMS_CATEGORY_FREE_SHORT_CODE),
 
             new ShortCodeTest("it", "112", SMS_CATEGORY_NOT_SHORT_CODE),
             new ShortCodeTest("it", "116117", SMS_CATEGORY_FREE_SHORT_CODE),
@@ -655,7 +661,7 @@
 
             new ShortCodeTest("ye", "50824", SMS_CATEGORY_NOT_SHORT_CODE),
             new ShortCodeTest("ye", "5084", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
-            new ShortCodeTest("ye", "5081", SMS_CATEGORY_FREE_SHORT_CODE),
+            new ShortCodeTest("ye", "5079", SMS_CATEGORY_FREE_SHORT_CODE),
 
             new ShortCodeTest("za", "330092", SMS_CATEGORY_NOT_SHORT_CODE),
             new ShortCodeTest("za", "33001", SMS_CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index a723a7f..0abdfd9 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -993,6 +993,9 @@
             SmsManager.getSmsManagerForSubscriptionId(sTestSub)
                         .setStorageMonitorMemoryStatusOverride(false);
 
+            // Clear cached data before starting test.
+            AsyncSmsMessageListener.getInstance().clear();
+
             //Message received
             sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                     .receiveSmsWaitForAcknowledgeMemoryFull(123456789, SmsMessage.FORMAT_3GPP,
@@ -1021,6 +1024,9 @@
         }
         setupImsServiceForSms();
 
+        // Clear cached data before starting test.
+        AsyncSmsMessageListener.getInstance().clear();
+
         // Message received
         sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                 .receiveSmsWaitForAcknowledge(123456789, SmsMessage.FORMAT_3GPP,
@@ -1047,6 +1053,9 @@
 
         setupImsServiceForSms();
 
+        // Clear cached data before starting test.
+        AsyncSmsMessageListener.getInstance().clear();
+
         // Message received
         sServiceConnector.getCarrierService().getMmTelFeature().getSmsImplementation()
                 .receiveSmsWaitForAcknowledge(123456789, SmsMessage.FORMAT_3GPP,
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
index 6ed80ce..a268438 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
@@ -62,7 +62,7 @@
                     mTuner, getExecutor(), getFilterCallback());
 
             // Open dvr playback as data source
-            mDvrPlayback = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+            mDvrPlayback = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
 
             return mFilter.acquireSharedFilterToken();
         }
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
index e714508..93cdf00 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerResourceTestService.java
@@ -69,6 +69,9 @@
         mFeInfo = infos.get(frontendIndex);
         mFeSettings = TunerTest.createFrontendSettings(mFeInfo);
 
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        mTuner.applyFrontend(mFeInfo);
+
         // tune
         return  mTuner.tune(mFeSettings);
     }
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index 16b3be3..0d07786 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -1111,7 +1112,8 @@
             return;
         }
 
-        assertEquals(lnb.setVoltage(Lnb.VOLTAGE_5V), Tuner.RESULT_SUCCESS);
+        int targetLnbVoltage = getTargetLnbVoltage();
+        assertEquals(lnb.setVoltage(targetLnbVoltage), Tuner.RESULT_SUCCESS);
         assertEquals(lnb.setTone(Lnb.TONE_NONE), Tuner.RESULT_SUCCESS);
         assertEquals(
                 lnb.setSatellitePosition(Lnb.POSITION_A), Tuner.RESULT_SUCCESS);
@@ -1597,14 +1599,14 @@
 
     @Test
     public void testOpenDvrRecorder() throws Exception {
-        DvrRecorder d = mTuner.openDvrRecorder(100, getExecutor(), getRecordListener());
+        DvrRecorder d = mTuner.openDvrRecorder(188, getExecutor(), getRecordListener());
         assertNotNull(d);
         d.close();
     }
 
     @Test
     public void testOpenDvPlayback() throws Exception {
-        DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+        DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
         assertNotNull(d);
         d.close();
     }
@@ -1662,17 +1664,17 @@
         assertFalse(ids.isEmpty());
         int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
         FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
-        FrontendSettings feSettings = createFrontendSettings(info);
 
-        // first tune with mTuner to acquire resource
-        int res = mTuner.tune(feSettings);
+        // first apply frontend with mTuner to acquire resource
+        int res = mTuner.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
         assertNotNull(mTuner.getFrontendInfo());
 
-        // now tune with a higher priority tuner to have mTuner's resource reclaimed
+        // now apply frontend with a higher priority tuner to have mTuner's resource reclaimed
         Tuner higherPrioTuner = new Tuner(mContext, null, 200);
-        res = higherPrioTuner.tune(feSettings);
+        res = higherPrioTuner.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
+
         assertNotNull(higherPrioTuner.getFrontendInfo());
 
         higherPrioTuner.close();
@@ -1688,8 +1690,8 @@
         FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
         FrontendSettings feSettings = createFrontendSettings(info);
 
-        // first tune with mTuner to acquire resource
-        int res = mTuner.tune(feSettings);
+        // first apply frontend with mTuner to acquire resource
+        int res = mTuner.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
         assertNotNull(mTuner.getFrontendInfo());
 
@@ -1749,9 +1751,11 @@
         tunerResourceTestServer = connection.getService();
 
         // CASE1 - normal reclaim
-        //
-        // first tune with mTuner to acquire resource
-        int res = mTuner.tune(feSettings);
+
+        // first apply frontend with mTuner to acquire resource
+        int res = mTuner.applyFrontend(info);
+        assertEquals(Tuner.RESULT_SUCCESS, res);
+
         boolean tunerReclaimed = false;
         assertEquals(Tuner.RESULT_SUCCESS, res);
         assertNotNull(mTuner.getFrontendInfo());
@@ -1827,27 +1831,27 @@
 
     @Test
     public void testShareFrontendFromTuner() throws Exception {
-        Tuner tuner100 = new Tuner(mContext, null, 100);
-        List<Integer> ids = tuner100.getFrontendIds();
+        List<Integer> ids = mTuner.getFrontendIds();
         assumeNotNull(ids);
         assertFalse(ids.isEmpty());
         int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
-        FrontendInfo info = tuner100.getFrontendInfoById(ids.get(targetFrontendId));
+        FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
         FrontendSettings feSettings = createFrontendSettings(info);
+
         int[] statusTypes = {1};
-        boolean exceptionThrown = false;
-        int res;
+        boolean exceptionThrown;
+
+        Tuner tuner100 = new Tuner(mContext, null, 100);
+        Tuner tuner200 = new Tuner(mContext, null, 200);
+        Tuner tuner300 = new Tuner(mContext, null, 300);
 
         // CASE1: check resource reclaim while sharee's priority < owner's priority
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        int res = tuner200.applyFrontend(info);
+        assertEquals(Tuner.RESULT_SUCCESS, res);
+
         // let tuner100 share from tuner200
-        Tuner tuner200 = new Tuner(mContext, null, 200);
-        res = tuner200.tune(feSettings);
-        assertEquals(Tuner.RESULT_SUCCESS, res);
-
-        info = tuner200.getFrontendInfoById(ids.get(targetFrontendId));
-        res = tuner200.tune(feSettings);
-        assertEquals(Tuner.RESULT_SUCCESS, res);
-
         tuner100.shareFrontendFromTuner(tuner200);
         // call openFilter to trigger ITunerDemux.setFrontendDataSourceById()
         Filter f = tuner100.openFilter(
@@ -1859,7 +1863,6 @@
         TunerTestOnTuneEventListener cb200 = new TunerTestOnTuneEventListener();
 
         // tune again on the owner
-        info = tuner200.getFrontendInfoById(ids.get(1));
         tuner100.setOnTuneEventListener(getExecutor(), cb100);
         tuner200.setOnTuneEventListener(getExecutor(), cb200);
         res = tuner200.tune(feSettings);
@@ -1870,8 +1873,7 @@
         tuner200.clearOnTuneEventListener();
 
         // now let the higher priority tuner steal the resource
-        Tuner tuner300 = new Tuner(mContext, null, 300);
-        res = tuner300.tune(feSettings);
+        res = tuner300.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
 
         // confirm owner & sharee's resource gets reclaimed by confirming an exception is thrown
@@ -1898,7 +1900,9 @@
 
         // CASE2: check resource reclaim fail when sharee's priority > new requester
         tuner100 = new Tuner(mContext, null, 100);
-        res = tuner100.tune(feSettings);
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        res = tuner100.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
 
         tuner300 = new Tuner(mContext, null, 300);
@@ -1908,7 +1912,9 @@
         assertNotNull(f);
 
         tuner200 = new Tuner(mContext, null, 200);
-        res = tuner200.tune(feSettings);
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        res = tuner200.applyFrontend(info);
         assertNotEquals(Tuner.RESULT_SUCCESS, res);
 
         // confirm the original tuner is still intact
@@ -1926,19 +1932,21 @@
         assertFalse(ids.isEmpty());
         int targetFrontendId = sTunerCtsConfiguration.getTargetFrontendId().intValueExact();
         FrontendInfo info = mTuner.getFrontendInfoById(ids.get(targetFrontendId));
-        FrontendSettings feSettings = createFrontendSettings(info);
+        createFrontendSettings(info);
 
         // SCENARIO 1 - transfer and close the previous owner
 
-        // First create a tuner and tune() to acquire frontend resource
+        // First create a tuner and applyFrontend() to acquire frontend resource
         Tuner tunerA = new Tuner(mContext, null, 100);
-        int res = tunerA.tune(feSettings);
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        int res = tunerA.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
 
         // Create another tuner and share frontend from tunerA
         Tuner tunerB = new Tuner(mContext, null, 500);
         tunerB.shareFrontendFromTuner(tunerA);
-        DvrRecorder d = tunerB.openDvrRecorder(100, getExecutor(), getRecordListener());
+        DvrRecorder d = tunerB.openDvrRecorder(188, getExecutor(), getRecordListener());
         assertNotNull(d);
 
         // Call transferOwner in the wrong configurations and confirm it fails
@@ -1962,9 +1970,11 @@
 
         // SCENARIO 2 - transfer and closeFrontend and tune on the previous owner
 
-        // First create a tuner and tune() to acquire frontend resource
+        // First create a tuner and applyFrontend() to acquire frontend resource
         tunerA = new Tuner(mContext, null, 200);
-        res = tunerA.tune(feSettings);
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        res = tunerA.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
 
         // Create another tuner and share frontend from tunerA
@@ -1981,7 +1991,9 @@
         // Confirm tune works without going through Tuner.close() even after transferOwner()
         // The purpose isn't to get tunerB's frontend revoked, but doing so as singletuner
         // based test has wider coverage
-        res = tunerA.tune(feSettings); // this should reclaim tunerB
+
+        // apply target frontend only, for case when there are multiple instances in frontend type
+        res = tunerA.applyFrontend(info);
         assertEquals(Tuner.RESULT_SUCCESS, res);
 
         // Confirm tuberB is revoked
@@ -2071,8 +2083,9 @@
         // Open Lnb and check the callback
         TunerTestLnbCallback lnbCB1 = new TunerTestLnbCallback();
         Lnb lnbA = tunerA.openLnb(getExecutor(), lnbCB1);
-        assertNotNull(lnbA);
-        lnbA.setVoltage(Lnb.VOLTAGE_5V);
+        assumeTrue(lnbA != null);
+        int targetLnbVoltage = getTargetLnbVoltage();
+        lnbA.setVoltage(targetLnbVoltage);
         lnbA.setTone(Lnb.TONE_CONTINUOUS);
         lnbA.sendDiseqcMessage(new byte[] {1, 2});
         assertTrue(lnbCB1.getOnDiseqcMessageCalled());
@@ -2706,7 +2719,7 @@
         assertTrue(token2 == null);
 
         // Use DvrPlayback as data source
-        DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+        DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
         assertNotNull(d);
 
         Settings settings = SectionSettingsWithTableInfo
@@ -2848,7 +2861,7 @@
         assertTrue(token != null);
 
         // Use DvrPlayer as data source
-        DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+        DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
         assertNotNull(d);
 
         assertTrue(mSharedFilterTestServer.verifySharedFilter(token));
@@ -2887,7 +2900,7 @@
 
             f.configure(config);
 
-            DvrPlayback d = mTuner.openDvrPlayback(100, getExecutor(), getPlaybackListener());
+            DvrPlayback d = mTuner.openDvrPlayback(188, getExecutor(), getPlaybackListener());
             assertNotNull(d);
             d.configure(getDvrSettings());
 
@@ -2937,29 +2950,33 @@
             int type = mTuner.getFrontendInfoById(ids.get(i)).getType();
             if (TunerVersionChecker.isHigherOrEqualVersionTo(
                         TunerVersionChecker.TUNER_VERSION_2_0)) {
-                int defaultMax = -1;
+                int defaultMax = mTuner.getMaxNumberOfFrontends(type);
                 int status;
-                // Check default value
-                defaultMax = mTuner.getMaxNumberOfFrontends(type);
-                assertTrue(defaultMax > 0);
-                // Set to -1
-                status = mTuner.setMaxNumberOfFrontends(type, -1);
-                assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
-                // Set to defaultMax + 1
-                status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1);
-                assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
-                // Set to 0
-                status = mTuner.setMaxNumberOfFrontends(type, 0);
-                assertEquals(Tuner.RESULT_SUCCESS, status);
-                // Check after set
-                int currentMax = -1;
-                currentMax = mTuner.getMaxNumberOfFrontends(type);
-                assertEquals(currentMax, 0);
-                // Reset to default
-                status = mTuner.setMaxNumberOfFrontends(type, defaultMax);
-                assertEquals(Tuner.RESULT_SUCCESS, status);
-                currentMax = mTuner.getMaxNumberOfFrontends(type);
-                assertEquals(defaultMax, currentMax);
+                // Use try block to ensure restoring the max Tuner
+                try {
+                    // Check default value
+                    assertTrue(defaultMax > 0);
+                    // Set to -1
+                    status = mTuner.setMaxNumberOfFrontends(type, -1);
+                    assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
+                    // Set to defaultMax + 1
+                    status = mTuner.setMaxNumberOfFrontends(type, defaultMax + 1);
+                    assertEquals(Tuner.RESULT_INVALID_ARGUMENT, status);
+                    // Set to 0
+                    status = mTuner.setMaxNumberOfFrontends(type, 0);
+                    assertEquals(Tuner.RESULT_SUCCESS, status);
+                    // Check after set
+                    int currentMax = mTuner.getMaxNumberOfFrontends(type);
+                    assertEquals(currentMax, 0);
+                } catch (Exception e) {
+                    throw (e);
+                } finally {
+                    // Reset to default
+                    status = mTuner.setMaxNumberOfFrontends(type, defaultMax);
+                    assertEquals(Tuner.RESULT_SUCCESS, status);
+                    int currentMax = mTuner.getMaxNumberOfFrontends(type);
+                    assertEquals(defaultMax, currentMax);
+                }
             } else {
                 int defaultMax = mTuner.getMaxNumberOfFrontends(type);
                 assertEquals(defaultMax, -1);
@@ -2979,45 +2996,64 @@
                 assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
                 assertNotNull(mTuner.getFrontendInfo());
 
-                // validate that set max cannot be set to lower value than current usage
-                assertEquals(Tuner.RESULT_INVALID_ARGUMENT,
+                // Use try block to ensure restoring the max Tuner
+                try {
+                    // validate that set max cannot be set to lower value than current usage
+                    assertEquals(Tuner.RESULT_INVALID_ARGUMENT,
                             mTuner.setMaxNumberOfFrontends(type1, 0));
 
-                // validate max value is reflected in the tune behavior
-                mTuner.closeFrontend();
-                assertEquals(Tuner.RESULT_SUCCESS,
+                    // validate max value is reflected in the tune behavior
+                    mTuner.closeFrontend();
+                    assertEquals(Tuner.RESULT_SUCCESS,
                             mTuner.setMaxNumberOfFrontends(type1, 0));
-                assertEquals(Tuner.RESULT_UNAVAILABLE,
+                    assertEquals(Tuner.RESULT_UNAVAILABLE,
                             mTuner.tune(feSettings1));
 
-                assertEquals(Tuner.RESULT_SUCCESS,
+                    assertEquals(Tuner.RESULT_SUCCESS,
                             mTuner.setMaxNumberOfFrontends(type1, originalMax1));
-                assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
-                assertNotNull(mTuner.getFrontendInfo());
-                mTuner.closeFrontend();
+                    assertEquals(Tuner.RESULT_SUCCESS, mTuner.tune(feSettings1));
+                    assertNotNull(mTuner.getFrontendInfo());
+                    mTuner.closeFrontend();
+                } catch (Exception e) {
+                    throw(e);
+                } finally {
+                    assertEquals(Tuner.RESULT_SUCCESS,
+                            mTuner.setMaxNumberOfFrontends(type1, originalMax1));
+                }
             }
 
             // validate max number on one frontend type has no impact on other
             if (ids.size() >= 2) {
-                FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(1));
-                int type2 = info2.getType();
-                int originalMax2 = mTuner.getMaxNumberOfFrontends(type2);
+                int type2 = type1;
+                for (int i = 0; i < ids.size(); i++) {
+                    FrontendInfo info2 = mTuner.getFrontendInfoById(ids.get(i));
+                    type2 = info2.getType();
+                    if (type1 != type2) break;
+                }
 
-                assertEquals(Tuner.RESULT_SUCCESS,
-                        mTuner.setMaxNumberOfFrontends(type2, 0));
-                assertEquals(Tuner.RESULT_SUCCESS,
-                        mTuner.tune(feSettings1));
-                assertNotNull(mTuner.getFrontendInfo());
-
-                // set it back to the original max
-                assertEquals(Tuner.RESULT_SUCCESS,
-                        mTuner.setMaxNumberOfFrontends(type2, originalMax2));
-                mTuner.closeFrontend();
-
+                if (type1 != type2) {
+                    int originalMax2 = mTuner.getMaxNumberOfFrontends(type2);
+                    // Use try block to ensure restoring the max Tuner
+                    try {
+                        assertEquals(Tuner.RESULT_SUCCESS,
+                                mTuner.setMaxNumberOfFrontends(type2, 0));
+                        assertEquals(Tuner.RESULT_SUCCESS,
+                                mTuner.tune(feSettings1));
+                        assertNotNull(mTuner.getFrontendInfo());
+                        mTuner.closeFrontend();
+                    } catch (Exception e) {
+                        throw (e);
+                    } finally {
+                        // set it back to the original max
+                        assertEquals(Tuner.RESULT_SUCCESS,
+                                mTuner.setMaxNumberOfFrontends(type2, originalMax2));
+                    }
+                }
             }
         }
     }
 
+
     public static Filter createTsSectionFilter(
             Tuner tuner, Executor e, FilterCallback cb) {
         Filter f = tuner.openFilter(Filter.TYPE_TS, Filter.SUBTYPE_SECTION, 1000, e, cb);
diff --git a/tests/tests/view/src/android/view/cts/OWNERS b/tests/tests/view/src/android/view/cts/OWNERS
index fae65c5..b544980 100644
--- a/tests/tests/view/src/android/view/cts/OWNERS
+++ b/tests/tests/view/src/android/view/cts/OWNERS
@@ -13,3 +13,5 @@
 per-file *PointerCapture* = file:platform/frameworks/base:/INPUT_OWNERS
 per-file *MotionEvent* = file:platform/frameworks/base:/INPUT_OWNERS
 per-file *VelocityTracker* = file:platform/frameworks/base:/INPUT_OWNERS
+
+per-file *NativeHeapLeakDetector* = file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
index 59c5d534..b05d74e 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiClass.java
@@ -114,6 +114,37 @@
         mApiMethods.add(method);
     }
 
+    /** Look for a matching constructor and mark it as covered by the given test method */
+    public void markConstructorCoveredTest(
+            List<String> parameterTypes, String testMethod) {
+        if (mSuperClass != null) {
+            // Mark matching constructors in the superclass
+            mSuperClass.markConstructorCoveredTest(parameterTypes, testMethod);
+        }
+        Optional<ApiConstructor> apiConstructor = getConstructor(parameterTypes);
+        apiConstructor.ifPresent(constructor -> constructor.setCoveredTest(testMethod));
+    }
+
+
+    /** Look for a matching method and if found and mark it as covered by the given test method */
+    public void markMethodCoveredTest(
+            String name, List<String> parameterTypes, String testMethod) {
+        if (mSuperClass != null) {
+            // Mark matching methods in the super class
+            mSuperClass.markMethodCoveredTest(name, parameterTypes, testMethod);
+        }
+        if (!mInterfaceMap.isEmpty()) {
+            // Mark matching methods in the interfaces
+            for (ApiClass mInterface : mInterfaceMap.values()) {
+                if (mInterface != null) {
+                    mInterface.markMethodCoveredTest(name, parameterTypes, testMethod);
+                }
+            }
+        }
+        Optional<ApiMethod> apiMethod = getMethod(name, parameterTypes);
+        apiMethod.ifPresent(method -> method.setCoveredTest(testMethod));
+    }
+
     /** Look for a matching constructor and mark it as covered */
     public void markConstructorCovered(List<String> parameterTypes, String coveredbyApk) {
         if (mSuperClass != null) {
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
index af9c99e..1f765e7 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiConstructor.java
@@ -35,6 +35,9 @@
     // A list of test APKs (aka CTS modules) that use this method.
     private final Map<String, Boolean> mCoveredWith = new ConcurrentHashMap<>();
 
+    // A list of CTS test methods that call this API constructor.
+    private final Map<String, Boolean> mCoveredTests = new ConcurrentHashMap<>();
+
     public ApiConstructor(String name, List<String> parameterTypes, boolean deprecated) {
         mName = name;
         mParameterTypes = new ArrayList<String>(parameterTypes);
@@ -69,7 +72,16 @@
         mCoveredWith.put(coveredWithModule, true);
     }
 
+    /** Adds a test method that is calling this API. */
+    public void setCoveredTest(String testMethod) {
+        mCoveredTests.put(testMethod, true);
+    }
+
     public Set<String> getCoveredWith() {
         return mCoveredWith.keySet();
     }
+
+    public Set<String> getCoveredTests() {
+        return mCoveredTests.keySet();
+    }
 }
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
index 43746c5..eb900ce 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/ApiMethod.java
@@ -46,6 +46,9 @@
     // A list of test APKs (aka CTS modules) that use this method.
     private final Map<String, Boolean> mCoveredWith = new ConcurrentHashMap<>();
 
+    // A list of CTS test methods that call this API method.
+    private final Map<String, Boolean> mCoveredTests = new ConcurrentHashMap<>();
+
     public ApiMethod(
             String name,
             List<String> parameterTypes,
@@ -110,6 +113,10 @@
         return mCoveredWith.keySet();
     }
 
+    public Set<String> getCoveredTests() {
+        return mCoveredTests.keySet();
+    }
+
     public void setCovered(String coveredWithModule) {
         if (coveredWithModule.endsWith(".apk")) {
             coveredWithModule = coveredWithModule.substring(0, coveredWithModule.length() - 4);
@@ -117,4 +124,9 @@
 
         mCoveredWith.put(coveredWithModule, true);
     }
+
+    /** Adds a test method that is calling this API. */
+    public void setCoveredTest(String coveredTest) {
+        mCoveredTests.put(coveredTest, true);
+    }
 }
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java b/tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java
similarity index 94%
rename from tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java
rename to tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java
index f33a839..8169c25 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CoverageComparator.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicommon/CoverageComparator.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.cts.apicoverage;
-
-import com.android.cts.apicommon.HasCoverage;
+package com.android.cts.apicommon;
 
 import java.util.Comparator;
 
 public class CoverageComparator implements Comparator<HasCoverage> {
+
+    /** Compares whether two coverage entities are same. */
     public int compare(HasCoverage entity, HasCoverage otherEntity) {
         int lhsPct = Math.round(entity.getCoveragePercentage());
         int rhsPct = Math.round(otherEntity.getCoveragePercentage());
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
index 2ab69dd..3450a7b 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
@@ -21,6 +21,7 @@
 import com.android.cts.apicommon.ApiCoverage;
 import com.android.cts.apicommon.ApiMethod;
 import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
 
 import java.io.OutputStream;
 import java.io.PrintStream;
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
index 8302882..ec656d5 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
@@ -21,6 +21,7 @@
 import com.android.cts.apicommon.ApiCoverage;
 import com.android.cts.apicommon.ApiMethod;
 import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
 
 import java.io.File;
 import java.io.OutputStream;
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java b/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java
new file mode 100644
index 0000000..60d2359
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/ApiMap.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apimap;
+
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiXmlHandler;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+import com.android.cts.ctsprofiles.Utils;
+
+import org.apache.commons.math3.util.Pair;
+import org.objectweb.asm.ClassReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+public final class ApiMap {
+
+    private static final int FORMAT_XML = 1;
+
+    private static final int FORMAT_HTML = 2;
+
+    private static final Set<String> IGNORE_PACKAGES = new HashSet<>();
+
+    private static void printUsage() {
+        System.out.println("Usage: api-map [OPTION]... [jar]...");
+        System.out.println();
+        System.out.println("Generates a report about what Android framework methods are called ");
+        System.out.println("from the given jars.");
+        System.out.println();
+        System.out.println("Options:");
+        System.out.println("  -o FILE                output file");
+        System.out.println("  -f [xml|html]          format of output");
+        System.out.println("  -a PATH                path to the API XML file");
+        System.out.println("  -j PARALLELISM         number of tasks to run in parallel, defaults"
+                + " to number of cpus");
+        System.out.println();
+        System.exit(1);
+    }
+
+    /** Entry of the CTS-M automation tool. */
+    public static void main(String[] args)
+            throws IOException, TransformerException, ParserConfigurationException, SAXException {
+        List<Path> jars = new ArrayList<>();
+        File outputFile = null;
+        int format = FORMAT_XML;
+        String apiXmlPath = "";
+        int parallelism = Runtime.getRuntime().availableProcessors();
+
+        List<Path> notFoundJars = new ArrayList<>();
+        int numJars = 0;
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].startsWith("-")) {
+                if ("-o".equals(args[i])) {
+                    outputFile = new File(Objects.requireNonNull(getExpectedArg(args, ++i)));
+                } else if ("-f".equals(args[i])) {
+                    String formatSpec = getExpectedArg(args, ++i);
+                    if ("xml".equalsIgnoreCase(formatSpec)) {
+                        format = FORMAT_XML;
+                    } else if ("html".equalsIgnoreCase(formatSpec)) {
+                        format = FORMAT_HTML;
+                    } else {
+                        printUsage();
+                    }
+                } else if ("-a".equals(args[i])) {
+                    apiXmlPath = getExpectedArg(args, ++i);
+                } else if ("-j".equals(args[i])) {
+                    parallelism = Integer.parseInt(
+                            Objects.requireNonNull(getExpectedArg(args, ++i)));
+                } else {
+                    printUsage();
+                }
+            } else {
+                Path file = Paths.get(args[i]);
+                numJars++;
+                if (Files.exists(file)) {
+                    jars.add(file);
+                } else {
+                    notFoundJars.add(file);
+                }
+            }
+        }
+
+        if (outputFile == null) {
+            printUsage();
+            throw new IllegalArgumentException("missing output file");
+        }
+
+        if (!notFoundJars.isEmpty()) {
+            String msg = String.format(Locale.US, "%d/%d jars not found: %s",
+                    notFoundJars.size(), numJars, notFoundJars);
+            throw new IllegalArgumentException(msg);
+        }
+
+        ApiCoverage apiCoverage = getApiCoverage(apiXmlPath);
+        apiCoverage.resolveSuperClasses();
+        ExecutorService service = Executors.newFixedThreadPool(parallelism);
+        List<Future<CallGraphManager>> tasks = new ArrayList<>();
+
+        for (Path module : jars) {
+            tasks.add(scanJarFile(
+                    service, module, module.getFileName().toString(), apiCoverage));
+        }
+
+        XmlWriter xmlWriter = new XmlWriter();
+        for (Future<CallGraphManager> task : tasks) {
+            try {
+                CallGraphManager callGraphManager = task.get();
+                xmlWriter.generateXtsAnnotationMapData(callGraphManager.getModule());
+            } catch (ExecutionException e) {
+                System.out.println("Task was completed unsuccessfully.");
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                System.out.println("Thread was interrupted before the task completed.");
+            }
+        }
+        service.shutdown();
+
+        xmlWriter.generateApiMapData(apiCoverage);
+        FileOutputStream output = new FileOutputStream(outputFile);
+        if (format == FORMAT_XML) {
+            xmlWriter.dumpXml(output);
+        } else {
+            HtmlWriter.printHtmlReport(xmlWriter, output);
+        }
+    }
+
+    /** Gets the argument or prints out the usage and exits. */
+    private static String getExpectedArg(String[] args, int index) {
+        if (index < args.length) {
+            return args[index];
+        } else {
+            printUsage();
+            return null;
+        }
+    }
+
+    /**
+     * Scans classes inside the jar file and adds coverage statistics.
+     *
+     * @param service executor service
+     * @param filePath jar file to be analyzed
+     * @param moduleName test module name
+     * @param apiCoverage object to which the coverage statistics will be added to
+     */
+    private static Future<CallGraphManager> scanJarFile(
+            ExecutorService service,
+            Path filePath,
+            String moduleName,
+            ApiCoverage apiCoverage) {
+        return service.submit(() -> {
+            ModuleProfile moduleProfile = new ModuleProfile(moduleName);
+            try (ZipFile zipSrc = new ZipFile(filePath.toString())) {
+                Enumeration<? extends ZipEntry> srcEntries = zipSrc.entries();
+                while (srcEntries.hasMoreElements()) {
+                    ZipEntry entry = srcEntries.nextElement();
+                    ZipEntry newEntry = new ZipEntry(entry.getName());
+                    newEntry.setTime(entry.getTime());
+                    BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry));
+                    String className = entry.getName();
+                    if (!className.endsWith(".class")) {
+                        continue;
+                    }
+                    Pair<String, String> packageClass = Utils.getPackageClass(
+                            className.substring(0, className.length() - 6));
+                    String packageName = packageClass.getFirst();
+                    if (ignorePackage(packageName)) {
+                        continue;
+                    }
+                    ClassReader cr = new ClassReader(bis);
+                    ClassProfile classProfile = moduleProfile.getOrCreateClass(
+                            packageClass.getFirst(), packageClass.getSecond(), apiCoverage);
+                    ClassAnalyzer visitor = new ClassAnalyzer(
+                            classProfile, moduleProfile, apiCoverage);
+                    cr.accept(visitor, 0);
+                }
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            CallGraphManager callGraphManager = new CallGraphManager(moduleProfile);
+            callGraphManager.resolveCoveredApis(apiCoverage);
+            return callGraphManager;
+        });
+    }
+
+    private static ApiCoverage getApiCoverage(String apiXmlPath)
+            throws SAXException, IOException {
+        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+        ApiXmlHandler currentXmlHandler = new ApiXmlHandler();
+        xmlReader.setContentHandler(currentXmlHandler);
+
+        File currentXml = new File(apiXmlPath);
+        try (FileReader fileReader = new FileReader(currentXml)) {
+            xmlReader.parse(new InputSource(fileReader));
+        }
+        return currentXmlHandler.getApi();
+    }
+
+    private static boolean ignorePackage(String packageName) {
+        for (String ignorePackage: IGNORE_PACKAGES) {
+            if (packageName.startsWith(ignorePackage)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java b/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java
new file mode 100644
index 0000000..f1eca85
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/CallGraphManager.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apimap;
+
+import com.android.cts.apicommon.ApiClass;
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+
+/** A class for collecting APIs covered by a CTS module. */
+public class CallGraphManager {
+
+    // Cache API calls for each CTS method.
+    private final Map<String, CoveredApiCache> mCoveredApiCaches = new HashMap<>();
+
+    private final ModuleProfile mModule;
+
+    /** Cache the covered API list for a CTS method. */
+    static class CoveredApiCache {
+
+        private final Map<String, MethodProfile> mApiConstructors = new HashMap<>();
+
+        private final Map<String, MethodProfile> mApiMethods = new HashMap<>();
+
+        public void mergeApis(CoveredApiCache apis) {
+            addMethods(apis.getApiMethods());
+            addConstructors(apis.getApiConstructors());
+        }
+
+        public void addMethods(Map<String, MethodProfile> methods) {
+            mApiMethods.putAll(methods);
+        }
+
+        public void addConstructors(Map<String, MethodProfile> constructors) {
+            mApiConstructors.putAll(constructors);
+        }
+
+        public Map<String, MethodProfile> getApiConstructors() {
+            return mApiConstructors;
+        }
+
+        public Map<String, MethodProfile> getApiMethods() {
+            return mApiMethods;
+        }
+    }
+
+    public CallGraphManager(ModuleProfile moduleProfile) {
+        mModule = moduleProfile;
+    }
+
+    public ModuleProfile getModule() {
+        return mModule;
+    }
+
+    /**
+     * Maps detected APIs to CTS test methods and marks them as covered by this CTS module.
+     */
+    public void resolveCoveredApis(ApiCoverage apiCoverage) {
+        for (ClassProfile classProfile : mModule.getClasses()) {
+            if (!classProfile.isNonAbstractTestClass()) {
+                continue;
+            }
+            for (MethodProfile methodProfile : classProfile.getTestMethods().values()) {
+                TarJan tarjan = new TarJan(methodProfile, mCoveredApiCaches.keySet());
+                Stack<Integer> stack = new Stack<>();
+                Set<Integer> visitedComponents = new HashSet<>();
+                String methodSignature = methodProfile.getMethodSignatureWithClass();
+                stack.add(tarjan.getComponentID(methodSignature));
+                visitedComponents.add(tarjan.getComponentID(methodSignature));
+                // Do recursive search for API calls.
+                resolveMethodCoveredApis(stack, visitedComponents, tarjan);
+                markCoveredApisWithCaller(methodSignature, apiCoverage);
+            }
+        }
+        markCoveredApisWithoutCaller(apiCoverage);
+    }
+
+    /** Collects covered APIs for a test method via memorized search. */
+    private CoveredApiCache resolveMethodCoveredApis(
+            Stack<Integer> stack,
+            Set<Integer> visitedComponents,
+            TarJan tarjan) {
+        List<MethodProfile> methods = tarjan.getComponent(stack.peek());
+        String methodSignature = methods.get(0).getMethodSignatureWithClass();
+        CoveredApiCache coveredApis = mCoveredApiCaches.get(methodSignature);
+        if (coveredApis != null) {
+            return coveredApis;
+        }
+        coveredApis = new CoveredApiCache();
+        for (MethodProfile method: methods) {
+            coveredApis.addMethods(method.getApiMethodCalls());
+            coveredApis.addConstructors(method.getApiConstructorCalls());
+        }
+        for (MethodProfile method: methods) {
+            for (MethodProfile methodCall : method.getCommonMethodCalls().values()) {
+                String methodCallSignature = methodCall.getMethodSignatureWithClass();
+                int componentID = tarjan.getComponentID(methodCallSignature);
+                if (visitedComponents.contains(componentID)) {
+                    continue;
+                }
+                visitedComponents.add(componentID);
+                stack.add(componentID);
+                CoveredApiCache apis = resolveMethodCoveredApis(stack, visitedComponents, tarjan);
+                coveredApis.mergeApis(apis);
+                stack.pop();
+            }
+        }
+        for (MethodProfile method: methods) {
+            mCoveredApiCaches.put(method.getMethodSignatureWithClass(), coveredApis);
+        }
+        return coveredApis;
+    }
+
+    /** Searches for the API class based on the given package name and class name. */
+    private ApiClass getApiClass(
+            String packageName, String className, ApiCoverage apiCoverage) {
+        ApiPackage apiPackage = apiCoverage.getPackage(packageName);
+        if (apiPackage != null) {
+            return apiPackage.getClass(className);
+        }
+        return null;
+    }
+
+    /** Marks that APIs are covered by this CTS module. */
+    private void markCoveredApisWithoutCaller(ApiCoverage apiCoverage) {
+        for (ClassProfile classProfile: mModule.getClasses()) {
+            if (!classProfile.isApiClass()) {
+                continue;
+            }
+            ApiClass apiClass = getApiClass(
+                    classProfile.getPackageName(),
+                    classProfile.getClassName(),
+                    apiCoverage
+            );
+            if (apiClass == null) {
+                continue;
+            }
+            for (MethodProfile methodProfile: classProfile.getMethods().values()) {
+                if (methodProfile.getMethodName().equals("<init>")) {
+                    apiClass.markConstructorCovered(
+                            methodProfile.getMethodParams(),
+                            mModule.getModuleName()
+                    );
+                } else {
+                    apiClass.markMethodCovered(
+                            methodProfile.getMethodName(),
+                            methodProfile.getMethodParams(),
+                            mModule.getModuleName()
+                    );
+                }
+            }
+        }
+    }
+
+    /** Marks that APIs are called by the given CTS test method. */
+    private void markCoveredApisWithCaller(String methodSignature, ApiCoverage apiCoverage) {
+        CoveredApiCache apiCache = mCoveredApiCaches.get(methodSignature);
+        if (apiCache == null) {
+            return;
+        }
+        for (MethodProfile apiConstructor : apiCache.getApiConstructors().values()) {
+            ApiClass apiClass = getApiClass(
+                    apiConstructor.getPackageName(),
+                    apiConstructor.getClassName(),
+                    apiCoverage
+            );
+            if (apiClass != null) {
+                apiClass.markConstructorCoveredTest(
+                        apiConstructor.getMethodParams(),
+                        String.format("[%s] %s", mModule.getModuleName(), methodSignature)
+                );
+            }
+        }
+        for (MethodProfile apiMethod : apiCache.getApiMethods().values()) {
+            ApiClass apiClass = getApiClass(
+                    apiMethod.getPackageName(), apiMethod.getClassName(), apiCoverage);
+            if (apiClass != null) {
+                apiClass.markMethodCoveredTest(
+                        apiMethod.getMethodName(),
+                        apiMethod.getMethodParams(),
+                        String.format("[%s] %s", mModule.getModuleName(), methodSignature)
+                );
+            }
+        }
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java b/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java
new file mode 100644
index 0000000..de2fb6f
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/HtmlWriter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apimap;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Class that outputs an HTML report of the API mapping data. The format is as same as
+ * cts-api-coverage HTML reports.
+ */
+class HtmlWriter {
+
+    public static void printHtmlReport(XmlWriter xmlWriter, OutputStream htmlOut)
+            throws TransformerException, IOException {
+
+        final PipedOutputStream xmlOut = new PipedOutputStream();
+        final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
+
+        Thread t = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    xmlWriter.dumpXml(xmlOut);
+                } catch (FileNotFoundException | TransformerException e) {
+                    throw new RuntimeException(e);
+                }
+                // Close the output stream to avoid "Write dead end" errors.
+                try {
+                    xmlOut.close();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+        t.start();
+
+        InputStream xsl = ApiMap.class.getResourceAsStream("/api-coverage.xsl");
+        StreamSource xslSource = new StreamSource(xsl);
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Transformer transformer = factory.newTransformer(xslSource);
+
+        StreamSource xmlSource = new StreamSource(xmlIn);
+        StreamResult result = new StreamResult(htmlOut);
+        transformer.transform(xmlSource, result);
+    }
+}
+
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java b/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java
new file mode 100644
index 0000000..c4b8039
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/TarJan.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.cts.apimap;
+
+import com.android.cts.ctsprofiles.MethodProfile;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+/** A class to implement Tarjan's strongly connected components algorithm. */
+public final class TarJan {
+
+    private int mTime = 0;
+    private int mNewNodeIndex = 0;
+    private final Map<String, Node> mVertices = new HashMap<>();
+    private final Stack<Node> mStack = new Stack<>();
+    private final Set<String> mResolvedMethods;
+    private final Map<String, Integer> mComponentIDs = new HashMap<>();
+    private final Map<Integer, List<MethodProfile>> mComponentNodes = new HashMap<>();
+
+    private static final class Node {
+        final int mDfn;
+        final MethodProfile mMethod;
+        int mLow;
+        boolean mInStack;
+
+        Node(int index, MethodProfile method) {
+            mDfn = index;
+            mMethod = method;
+        }
+    }
+
+    public TarJan(MethodProfile testMethod, Set<String> resolvedMethods) {
+        mResolvedMethods = resolvedMethods;
+        tarjan(testMethod);
+    }
+
+    /** Gets the strongly connected component the given method belongs to. */
+    public int getComponentID(String methodSignature) {
+        return mComponentIDs.get(methodSignature);
+    }
+
+    /** Gets a list methods belong to the given strongly connected component. */
+    public List<MethodProfile> getComponent(int id) {
+        return mComponentNodes.get(id);
+    }
+
+    private Node tarjan(MethodProfile method) {
+        Node v = new Node(mTime++, method);
+        v.mLow = v.mDfn;
+        String methodSignature = method.getMethodSignatureWithClass();
+        mVertices.put(methodSignature, v);
+        mStack.add(v);
+        v.mInStack = true;
+
+        if (!mResolvedMethods.contains(methodSignature)) {
+            for (MethodProfile callee: method.getCommonMethodCalls().values()) {
+                String calleeSignature = callee.getMethodSignatureWithClass();
+                Node w = mVertices.get(calleeSignature);
+                if (w == null) {
+                    w = tarjan(callee);
+                    v.mLow = Math.min(v.mLow, w.mLow);
+                } else if (w.mInStack) {
+                    v.mLow = Math.min(v.mLow, w.mDfn);
+                }
+            }
+        }
+
+        if (v.mLow == v.mDfn) {
+            Node w;
+            mNewNodeIndex++;
+            mComponentNodes.put(mNewNodeIndex, new ArrayList<>());
+            do {
+                w = mStack.pop();
+                mComponentIDs.put(methodSignature, mNewNodeIndex);
+                mComponentNodes.get(mNewNodeIndex).add(w.mMethod);
+                w.mInStack = false;
+            } while (!w.equals(v));
+        }
+        return v;
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java b/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java
new file mode 100644
index 0000000..93b8f1e
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apimap/XmlWriter.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.apimap;
+
+import com.android.cts.apicommon.ApiClass;
+import com.android.cts.apicommon.ApiConstructor;
+import com.android.cts.apicommon.ApiCoverage;
+import com.android.cts.apicommon.ApiMethod;
+import com.android.cts.apicommon.ApiPackage;
+import com.android.cts.apicommon.CoverageComparator;
+import com.android.cts.ctsprofiles.ClassProfile;
+import com.android.cts.ctsprofiles.MethodProfile;
+import com.android.cts.ctsprofiles.ModuleProfile;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.ProcessingInstruction;
+
+import java.io.FileNotFoundException;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/** Class that outputs an XML report of API and xTS-annotation mapping data. */
+public class XmlWriter {
+
+    private final Document mDoc;
+
+    private final Element mXTSAnnotationMapElement;
+
+    private final Element mXTSApiMapElement;
+
+    public XmlWriter() throws ParserConfigurationException {
+        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();
+        mDoc = documentBuilder.newDocument();
+        ProcessingInstruction pi = mDoc.createProcessingInstruction(
+                "xml-stylesheet", "type=\"text/xsl\"  href=\"api-map.xsl\"?>");
+        SimpleDateFormat format = new SimpleDateFormat(
+                "EEE, MMM d, yyyy h:mm a z", Locale.CHINA);
+        String date = format.format(new Date(System.currentTimeMillis()));
+        Element rootElement = mDoc.createElement("api-coverage");
+        rootElement.setAttribute("generatedTime", date);
+        rootElement.setAttribute("title", "cts-m-automation");
+        mDoc.appendChild(rootElement);
+        mDoc.insertBefore(pi, rootElement);
+        mXTSAnnotationMapElement = mDoc.createElement("xts-annotation");
+        rootElement.appendChild(mXTSAnnotationMapElement);
+        mXTSApiMapElement = mDoc.createElement("api");
+        rootElement.appendChild(mXTSApiMapElement);
+    }
+
+    /** Dumps the document to an xml file. */
+    public void dumpXml(OutputStream outputStream)
+            throws FileNotFoundException, TransformerException {
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        transformer.setOutputProperty("indent", "yes");
+        DOMSource source = new DOMSource(mDoc);
+        StreamResult result = new StreamResult(outputStream);
+        transformer.transform(source, result);
+    }
+
+    /** Generates the data for API coverage. */
+    public void generateApiMapData(ApiCoverage apiCoverage) {
+        CoverageComparator comparator = new CoverageComparator();
+        List<ApiPackage> packages = new ArrayList<>(apiCoverage.getPackages());
+        packages.sort(comparator);
+        ApiStatistics statistics = new ApiStatistics();
+        for (ApiPackage pkg : packages) {
+            if (pkg.getTotalMethods() > 0) {
+                mXTSApiMapElement.appendChild(createApiPackageElement(pkg, statistics));
+            }
+        }
+        mXTSApiMapElement.appendChild(createApiTotalElement(
+                statistics.mTotalMethods, statistics.mTotalCoveredMethods));
+    }
+
+    /** Generates the data for xTS annotations. */
+    public void generateXtsAnnotationMapData(ModuleProfile module) {
+        Element moduleElement = mDoc.createElement("test-module");
+        moduleElement.setAttribute("module", module.getModuleName());
+        for (ClassProfile classProfile : module.getClasses()) {
+            if (!classProfile.isNonAbstractTestClass()) {
+                continue;
+            }
+            Element classElement = createTestClassElement(classProfile);
+            if (classElement.hasChildNodes()) {
+                moduleElement.appendChild(classElement);
+            }
+        }
+        if (moduleElement.hasChildNodes()) {
+            mXTSAnnotationMapElement.appendChild(moduleElement);
+        }
+    }
+
+    private Element createApiConstructorElement(
+            ApiConstructor constructor, ApiStatistics statistics) {
+        if (constructor.isDeprecated()) {
+            if (constructor.isCovered()) {
+                statistics.mTotalCoveredMethods -= 1;
+            }
+            statistics.mTotalMethods -= 1;
+        }
+        List<String> coveredWithList = new ArrayList<>(constructor.getCoveredWith());
+        Collections.sort(coveredWithList);
+        String coveredWith = String.join(",", coveredWithList);
+        Element element = mDoc.createElement("constructor");
+        element.setAttribute("name", constructor.getName());
+        element.setAttribute("deprecated", String.valueOf(constructor.isDeprecated()));
+        element.setAttribute("covered", String.valueOf(constructor.isCovered()));
+        element.setAttribute("with", coveredWith);
+        for (String parameterType : constructor.getParameterTypes()) {
+            Element paramElement = mDoc.createElement("parameter");
+            paramElement.setAttribute("type", parameterType);
+            element.appendChild(paramElement);
+        }
+        for (String test: constructor.getCoveredTests()) {
+            element.appendChild(createCoveredByElement(test));
+        }
+        return element;
+    }
+
+    private Element createApiMethodElement(ApiMethod method, ApiStatistics statistics) {
+        if (method.isDeprecated()) {
+            if (method.isCovered()) {
+                statistics.mTotalCoveredMethods -= 1;
+            }
+            statistics.mTotalMethods -= 1;
+        }
+        List<String> coveredWithList = new ArrayList<>(method.getCoveredWith());
+        Collections.sort(coveredWithList);
+        String coveredWith = String.join(",", coveredWithList);
+        Element element = mDoc.createElement("method");
+        element.setAttribute("name", method.getName());
+        element.setAttribute("returnType", method.getReturnType());
+        element.setAttribute("deprecated", String.valueOf(method.isDeprecated()));
+        element.setAttribute("static", String.valueOf(method.isStaticMethod()));
+        element.setAttribute("final", String.valueOf(method.isFinalMethod()));
+        element.setAttribute("visibility", method.getVisibility());
+        element.setAttribute("abstract", String.valueOf(method.isAbstractMethod()));
+        element.setAttribute("covered", String.valueOf(method.isCovered()));
+        element.setAttribute("with", coveredWith);
+        for (String parameterType : method.getParameterTypes()) {
+            Element paramElement = mDoc.createElement("parameter");
+            paramElement.setAttribute("type", parameterType);
+            element.appendChild(paramElement);
+        }
+        for (String test: method.getCoveredTests()) {
+            element.appendChild(createCoveredByElement(test));
+        }
+        return element;
+    }
+
+    private Element createCoveredByElement(String test) {
+        Element element = mDoc.createElement("covered-by");
+        element.setAttribute("name", test);
+        return element;
+    }
+
+    private Element createApiPackageElement(ApiPackage pkg, ApiStatistics statistics) {
+        Element element = mDoc.createElement("package");
+        element.setAttribute("name", pkg.getName());
+        element.setAttribute("numCovered", String.valueOf(pkg.getNumCoveredMethods()));
+        element.setAttribute("numTotal", String.valueOf(pkg.getTotalMethods()));
+        element.setAttribute("coveragePercentage", String.valueOf(
+                Math.round(pkg.getCoveragePercentage())));
+        statistics.mTotalMethods += pkg.getTotalMethods();
+        statistics.mTotalCoveredMethods += pkg.getNumCoveredMethods();
+        List<ApiClass> classes = new ArrayList<>(pkg.getClasses());
+        CoverageComparator comparator = new CoverageComparator();
+        classes.sort(comparator);
+        for (ApiClass apiClass : classes) {
+            if (apiClass.getTotalMethods() > 0) {
+                element.appendChild(createApiClassElement(apiClass, statistics));
+            }
+        }
+        return element;
+    }
+
+    private Element createApiClassElement(ApiClass apiClass, ApiStatistics statistics) {
+        Element element = mDoc.createElement("class");
+        element.setAttribute("name", apiClass.getName());
+        element.setAttribute("numCovered", String.valueOf(apiClass.getNumCoveredMethods()));
+        element.setAttribute("numTotal", String.valueOf(apiClass.getTotalMethods()));
+        element.setAttribute("deprecated", String.valueOf(apiClass.isDeprecated()));
+        element.setAttribute("coveragePercentage", String.valueOf(
+                Math.round(apiClass.getCoveragePercentage())));
+        for (ApiConstructor constructor : apiClass.getConstructors()) {
+            element.appendChild(createApiConstructorElement(constructor, statistics));
+        }
+        for (ApiMethod method : apiClass.getMethods()) {
+            element.appendChild(createApiMethodElement(method, statistics));
+        }
+        return element;
+    }
+
+    private Element createApiTotalElement(int totalMethods, int totalCoveredMethods) {
+        Element total = mDoc.createElement("total");
+        total.setAttribute("numCovered", String.valueOf(totalCoveredMethods));
+        total.setAttribute("numTotal", String.valueOf(totalMethods));
+        total.setAttribute("coveragePercentage", String.valueOf(
+                Math.round((float) totalCoveredMethods / totalMethods * 100.0f)));
+        return total;
+    }
+
+    private Element createTestClassElement(ClassProfile classProfile) {
+        Element classElement = mDoc.createElement("test-class");
+        classElement.setAttribute("package", classProfile.getPackageName());
+        classElement.setAttribute("name", classProfile.getClassName());
+        for (Map.Entry<String, Set<String>> xtsAnnotation :
+                classProfile.annotationManagement.getTestMetadata().entrySet()) {
+            classElement.appendChild(createXtsAnnotationElement(
+                    xtsAnnotation.getKey(),
+                    xtsAnnotation.getValue()));
+        }
+        for (MethodProfile testMethod : classProfile.getTestMethods().values()) {
+            Element methodElement = createTestMethodElement(testMethod);
+            if (methodElement.hasChildNodes()) {
+                classElement.appendChild(methodElement);
+            }
+        }
+        return classElement;
+    }
+
+    private Element createTestMethodElement(MethodProfile methodProfile) {
+        Element methodElement = mDoc.createElement("test-method");
+        methodElement.setAttribute("name", methodProfile.getMethodName());
+        for (Map.Entry<String, Set<String>> xtsAnnotation :
+                methodProfile.annotationManagement.getTestMetadata().entrySet()) {
+            methodElement.appendChild(createXtsAnnotationElement(
+                    xtsAnnotation.getKey(),
+                    xtsAnnotation.getValue()));
+        }
+        return methodElement;
+    }
+
+    private Element createXtsAnnotationElement(String name, Set<String> values) {
+        Element element = mDoc.createElement("cts-annotation");
+        element.setAttribute("name", name);
+        element.setAttribute("values", String.join(";", values));
+        return element;
+    }
+
+    static final class ApiStatistics {
+        int mTotalMethods = 0;
+        int mTotalCoveredMethods = 0;
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java
index d2931eb..3b169fc 100644
--- a/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java
+++ b/tools/cts-api-coverage/src/com/android/cts/ctsprofiles/ClassProfile.java
@@ -100,6 +100,10 @@
         return mModule;
     }
 
+    public Map<String, MethodProfile> getMethods() {
+        return mMethods;
+    }
+
     /** Creates a class method. */
     public MethodProfile getOrCreateMethod(
             String methodName, List<String> params) {
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
index 3641239..c89c6b2 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/loading/CtsConfigLoadingTest.java
@@ -95,6 +95,7 @@
                             "systems",
                             "sysui",
                             "telecom",
+                            "threadnetwork",
                             "tv",
                             "uitoolkit",
                             "uwb",