Merge "Allow compatibility-device-util-axt to be used with ExtendedMockito"
diff --git a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
index 24767d2..716b18f 100644
--- a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
@@ -123,7 +123,8 @@
         <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:text="@string/analog_headset_keycodes_label"/>
+            android:text="@string/analog_headset_keycodes_label"
+            android:id="@+id/headset_keycodes"/>
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b694e2f..704be2e 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -5419,6 +5419,16 @@
        input jack and BT01 input plug to the USB interface output jack.
        \nThe Virtual MIDI test does not require any MIDI interface hardware.
     </string>
+    <string name="analog_headset_test_info_tv">This test tests the following functionality with respect to wired analog headsets.\n
+        1. Correct audio playback.\n
+        2. Plug intents.\n
+        \nTo execute test:\n
+        1. Plug in an Android-compatible, analog headset. Verify connection/recognition.\n
+        2. Play test tone and verify correct behavior.\n
+        \nTo run this test it is necessary to have an Android device with a 3.5mm analog headset jack and a compatible analog headset.\n
+        \n(see <a href="https://source.android.com/devices/accessories/headset/plug-headset-spec">3.5 mm Headset: Accessory Specification</a> and
+        <a href="https://source.android.com/compatibility/android-cdd#7_8_2_1_analog_audio_ports">Android CDD § 7.8.2.1. Analog Audio Ports</a>)
+    </string>
 
     <string name="midiHasMIDILbl">Has MIDI Support</string>
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 83b32de..307eb6f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.media.AudioDeviceCallback;
@@ -153,6 +154,14 @@
         mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
         mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
 
+        if (isTelevision()) {
+            mButtonsPromptTxt.setVisibility(View.GONE);
+            mHeadsetHookText.setVisibility(View.GONE);
+            mHeadsetVolUpText.setVisibility(View.GONE);
+            mHeadsetVolDownText.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.headset_keycodes)).setVisibility(View.GONE);
+        }
+
         mResultsTxt = (TextView)findViewById(R.id.headset_results);
 
         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
@@ -168,7 +177,8 @@
 
         showKeyMessagesState();
 
-        setInfoResources(R.string.analog_headset_test, R.string.analog_headset_test_info, -1);
+        setInfoResources(R.string.analog_headset_test, isTelevision()
+                ? R.string.analog_headset_test_info_tv : R.string.analog_headset_test_info, -1);
 
         setPassFailButtonClickListeners();
         getPassButton().setEnabled(false);
@@ -182,11 +192,12 @@
             mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset));
             return true;
         } else {
-            boolean pass = isReportLogOkToPass()
-                    && mPlugIntentReceived
-                    && mHeadsetDeviceInfo != null
-                    && mPlaybackSuccess
-                    && (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
+            boolean pass = isReportLogOkToPass() &&
+                    mPlugIntentReceived &&
+                    mHeadsetDeviceInfo != null &&
+                    mPlaybackSuccess &&
+                    (isTelevision()
+                    || ((mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown));
             if (pass) {
                 mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
             } else if (!isReportLogOkToPass()) {
@@ -488,4 +499,8 @@
         }
         return super.onKeyDown(keyCode, event);
     }
+
+    private boolean isTelevision() {
+        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
 }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
index e53eb08..5cabd64 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
@@ -126,8 +126,8 @@
         @Override
         public boolean matches(MotionEvent actual) {
             return super.matches(actual)
-                    && ((int) actual.getX()) == mX
-                    && ((int) actual.getY()) == mY;
+                    && Math.round(actual.getX()) == mX
+                    && Math.round(actual.getY()) == mY;
         }
 
         @Override
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index a9543c2..1611e13 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -42,7 +42,13 @@
     private static final String LOG_TAG = "UiAutomatorUtils";
 
     /** Default swipe deadzone percentage. See {@link UiScrollable}. */
-    private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;
+    private static final double DEFAULT_SWIPE_DEADZONE_PCT_TV       = 0.1f;
+    private static final double DEFAULT_SWIPE_DEADZONE_PCT_ALL      = 0.25f;
+    /**
+     * On Wear, some cts tests like CtsPermission3TestCases that run on
+     * low performance device. Keep 0.05 to have better matching.
+     */
+    private static final double DEFAULT_SWIPE_DEADZONE_PCT_WEAR     = 0.05f;
 
     /** Minimum view height accepted (before needing to scroll more). */
     private static final float MIN_VIEW_HEIGHT_DP = 8;
@@ -78,6 +84,16 @@
                 ApplicationProvider.getApplicationContext().getResources().getDisplayMetrics()));
     }
 
+    private static double getSwipeDeadZonePct() {
+        if (FeatureUtil.isTV()) {
+            return DEFAULT_SWIPE_DEADZONE_PCT_TV;
+        } else if (FeatureUtil.isWatch()) {
+            return DEFAULT_SWIPE_DEADZONE_PCT_WEAR;
+        } else {
+            return DEFAULT_SWIPE_DEADZONE_PCT_ALL;
+        }
+    }
+
     public static UiObject2 waitFindObjectOrNull(BySelector selector, long timeoutMs)
             throws UiObjectNotFoundException {
         UiObject2 view = null;
@@ -101,8 +117,7 @@
             }
 
             if (view == null || view.getVisibleBounds().height() < minViewHeightPx) {
-                final double deadZone = !(FeatureUtil.isWatch() || FeatureUtil.isTV())
-                        ? 0.25 : DEFAULT_SWIPE_DEADZONE_PCT;
+                final double deadZone = getSwipeDeadZonePct();
                 UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
                 scrollable.setSwipeDeadZonePercentage(deadZone);
                 if (scrollable.exists()) {
diff --git a/libs/helpers/interfaces/Android.bp b/libs/helpers/interfaces/Android.bp
index 3cdb264..dcb38f5 100644
--- a/libs/helpers/interfaces/Android.bp
+++ b/libs/helpers/interfaces/Android.bp
@@ -23,7 +23,6 @@
 
     static_libs: [
         "cts-helpers-core",
-        "ub-uiautomator",
     ],
 
     sdk_version: "test_current",
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index f0669b9..a79a6b3 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -20,12 +20,17 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.app.ActivityOptions;
 import android.app.stubs.DisplayTestActivity;
 import android.app.stubs.OrientationTestUtils;
+import android.content.Intent;
 import android.graphics.Point;
 import android.server.wm.SetRequestedOrientationRule;
+import android.util.Pair;
 import android.view.Display;
 
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.ApiTest;
 
 import org.junit.Rule;
@@ -52,55 +57,62 @@
             return;
         }
 
-        final DisplayTestActivity activity =
-                mSetRequestedOrientationRule.launchActivityInFullscreen(DisplayTestActivity.class);
+        final Pair<Intent, ActivityOptions> launchArgs =
+                SetRequestedOrientationRule.buildFullScreenLaunchArgs(DisplayTestActivity.class);
 
-        // Get a {@link Display} instance before rotation.
-        final Display origDisplay = activity.getDisplay();
+        final DisplayTestActivity activity = (DisplayTestActivity) InstrumentationRegistry
+                .getInstrumentation()
+                .startActivitySync(launchArgs.first, launchArgs.second.toBundle());
+        try {
+            // Get a {@link Display} instance before rotation.
+            final Display origDisplay = activity.getDisplay();
 
-        // Capture the originally reported width and heights
-        final Point origSize = new Point();
-        origDisplay.getRealSize(origSize);
+            // Capture the originally reported width and heights
+            final Point origSize = new Point();
+            origDisplay.getRealSize(origSize);
 
-        // Change orientation
-        activity.configurationChangeObserver.startObserving();
-        OrientationTestUtils.switchOrientation(activity);
+            // Change orientation
+            activity.configurationChangeObserver.startObserving();
+            OrientationTestUtils.switchOrientation(activity);
 
-        final boolean closeToSquareBounds =
-                OrientationTestUtils.isCloseToSquareBounds(activity);
+            final boolean closeToSquareBounds =
+                    OrientationTestUtils.isCloseToSquareBounds(activity);
 
-        // Don't wait for the configuration to change if
-        // the display is square. In many cases it won't.
-        if (!closeToSquareBounds) {
-            activity.configurationChangeObserver.await();
-        }
+            // Don't wait for the configuration to change if
+            // the display is square. In many cases it won't.
+            if (!closeToSquareBounds) {
+                activity.configurationChangeObserver.await();
+            }
 
-        final Point newOrigSize = new Point();
-        origDisplay.getRealSize(newOrigSize);
+            final Point newOrigSize = new Point();
+            origDisplay.getRealSize(newOrigSize);
 
-        // Get a {@link Display} instance after rotation.
-        final Display updatedDisplay = activity.getDisplay();
-        final Point updatedSize = new Point();
-        updatedDisplay.getRealSize(updatedSize);
+            // Get a {@link Display} instance after rotation.
+            final Display updatedDisplay = activity.getDisplay();
+            final Point updatedSize = new Point();
+            updatedDisplay.getRealSize(updatedSize);
 
-        // For square screens the following assertions do not make sense and will always
-        // fail.
-        if (!closeToSquareBounds) {
-            // Ensure that the width and height of the original instance no longer are the
-            // same.
-            // Note that this will be false if the device width and height are identical.
-            // Note there are cases where width and height may not all be updated, such as
-            // on docked devices where the app is letterboxed. However, at least one
-            // dimension needs to be updated.
+            // For square screens the following assertions do not make sense and will always
+            // fail.
+            if (!closeToSquareBounds) {
+                // Ensure that the width and height of the original instance no longer are the
+                // same.
+                // Note that this will be false if the device width and height are identical.
+                // Note there are cases where width and height may not all be updated, such as
+                // on docked devices where the app is letterboxed. However, at least one
+                // dimension needs to be updated.
+                assertWithMessage(
+                        "size from original display instance should have changed")
+                        .that(origSize).isNotEqualTo(newOrigSize);
+            }
+
+            // Ensure that the width and height of the original instance have been updated to
+            // match the values that would be found in a new instance.
             assertWithMessage(
-                    "size from original display instance should have changed")
-                    .that(origSize).isNotEqualTo(newOrigSize);
+                    "size from original display instance should match current")
+                    .that(newOrigSize).isEqualTo(updatedSize);
+        } finally {
+            InstrumentationRegistry.getInstrumentation().runOnMainSync(activity::finish);
         }
-
-        // Ensure that the width and height of the original instance have been updated to
-        // match the values that would be found in a new instance.
-        assertWithMessage(
-                "size from original display instance should match current")
-                .that(newOrigSize).isEqualTo(updatedSize);
     }
 }
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index f7edaf7..cd1de26 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -36,7 +36,6 @@
 import com.android.compatibility.common.util.CddTest
 import com.google.common.truth.Truth.assertThat
 import kotlin.test.assertFailsWith
-import org.junit.Assume
 
 class NotificationTemplateTest : NotificationTemplateTestBase() {
 
@@ -143,7 +142,10 @@
     }
 
     fun testWideIcon_inBigPicture_cappedTo16By9() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
+
         val picture = createBitmap(40, 30)
         val icon = createBitmap(200, 100)
         val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -161,7 +163,10 @@
     }
 
     fun testWideIcon_inBigPicture_canShowExact4By3() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
+
         val picture = createBitmap(40, 30)
         val icon = createBitmap(400, 300)
         val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -179,7 +184,10 @@
     }
 
     fun testWideIcon_inBigPicture_neverNarrowerThanSquare() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
+
         val picture = createBitmap(40, 30)
         val icon = createBitmap(200, 300)
         val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -241,7 +249,10 @@
     }
 
     fun testBigPictureStyle_populatesExtrasCompatibly() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
+
         val bitmap = createBitmap(40, 30)
         val uri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
         val iconWithUri = Icon.createWithContentUri(uri)
@@ -276,7 +287,9 @@
 
     @CddTest(requirement = "3.8.3.1/C-2-1")
     fun testBigPictureStyle_bigPictureUriIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
         val pictureIcon = Icon.createWithContentUri(pictureUri)
@@ -296,7 +309,10 @@
 
     @CddTest(requirement = "3.8.3.1/C-2-1")
     fun testPromoteBigPicture_withBigPictureUriIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
+
         val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
         val pictureIcon = Icon.createWithContentUri(pictureUri)
         val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -316,7 +332,9 @@
     }
 
     fun testPromoteBigPicture_withoutLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -339,7 +357,9 @@
     }
 
     fun testPromoteBigPicture_withLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val icon = createBitmap(80, 65)
@@ -370,7 +390,9 @@
 
     @CddTest(requirement = "3.8.3.1/C-2-1")
     fun testPromoteBigPicture_withBigLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val inputWidth = 400
@@ -405,7 +427,9 @@
 
     @CddTest(requirement = "3.8.3.1/C-2-1")
     fun testBigPicture_withBigLargeIcon_withContentUri() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+    if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val iconUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
         val icon = Icon.createWithContentUri(iconUri)
@@ -808,10 +832,9 @@
      *
      * If the current platform does not support notification styles, skip this test without failure.
      */
-    private fun skipIfPlatformDoesNotSupportNotificationStyles() {
-        Assume.assumeFalse("Current platform does not support notification styles.",
-                mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
-                        mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+    private fun skipIfPlatformDoesNotSupportNotificationStyles(): Boolean {
+        return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
+                        mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
     }
 
     companion object {
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java b/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
index f882022..be64440 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
@@ -21,6 +21,7 @@
 import android.app.WindowConfiguration;
 import android.content.Intent;
 import android.util.Log;
+import android.util.Pair;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
@@ -30,19 +31,12 @@
 import org.junit.rules.ExternalResource;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
-import org.junit.runners.model.MultipleFailureException;
 import org.junit.runners.model.Statement;
 
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-
 /**
  * Rule for using setRequestedOrientation API in tests.
  */
 public class SetRequestedOrientationRule implements TestRule {
-    final Deque<AutoCloseable> mAutoCloseables = new ArrayDeque<>();
-
     @Override
     public Statement apply(Statement base,
             Description description) {
@@ -51,44 +45,35 @@
             public void evaluate() throws Throwable {
                 final DisableFixedToUserRotationRule mDisableFixedToUserRotationRule =
                         new DisableFixedToUserRotationRule();
+                mDisableFixedToUserRotationRule.before();
                 try {
-                    mDisableFixedToUserRotationRule.before();
-                    mAutoCloseables.push(mDisableFixedToUserRotationRule::after);
-                    mAutoCloseables.push(
-                            new IgnoreOrientationRequestSession(false /* don' ignore */));
-                    base.evaluate();
-                } finally {
-                    final ArrayList<Throwable> throwables = new ArrayList<>();
-                    while (!mAutoCloseables.isEmpty()) {
-                        try {
-                            mAutoCloseables.pop().close();
-                        } catch (Throwable t) {
-                            throwables.add(t);
-                        }
+                    try (IgnoreOrientationRequestSession session =
+                                 new IgnoreOrientationRequestSession(false /* don' ignore */)) {
+                        base.evaluate();
                     }
-                    MultipleFailureException.assertEmpty(throwables);
+                } finally {
+                    mDisableFixedToUserRotationRule.after();
                 }
             }
         };
     }
 
     /**
-     * Launch an activity in fullscreen.
+     * Builds launch args to launch Activity in fullscreen windowing mode.
      *
      * Activities which request orientation need to be in fullscreen windowing mode.
-     * The activity will be finished at the test end.
      */
-    public <T extends Activity> T launchActivityInFullscreen(Class<T> klass) {
+    public static <T extends Activity> Pair<Intent, ActivityOptions> buildFullScreenLaunchArgs(
+            Class<T> klass) {
         final Intent intent = new Intent(
                 InstrumentationRegistry.getInstrumentation().getTargetContext(),
                 klass);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
-        final T activity = (T) InstrumentationRegistry.getInstrumentation().startActivitySync(
-                intent, options.toBundle());
-        mAutoCloseables.push(activity::finish);
-        return activity;
+
+        return Pair.create(intent, options);
     }
 
     public static class DisableFixedToUserRotationRule extends ExternalResource {
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 daf4abb..cfff01c 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
@@ -16,21 +16,31 @@
 
 package android.mediav2.common.cts;
 
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
+import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.annotation.NonNull;
 import android.graphics.ImageFormat;
+import android.media.AudioFormat;
 import android.media.Image;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
+import android.media.MediaMuxer;
 import android.os.PersistableBundle;
 import android.util.Log;
 
 import com.android.compatibility.common.util.Preconditions;
 
+import org.junit.After;
 import org.junit.Before;
 
 import java.io.File;
@@ -38,19 +48,63 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Wrapper class for trying and testing encoder components.
- * @deprecated This class is marked for future removal. Use {@link EncoderTestBase} instead.
- * {@link EncoderTestBase} offers same functionality as the current class. Besides that, it has
- * utility functions for muxing, offers better control over configuration params, utility
- * functions for better test labelling.
- * TODO (b/260533828) remove this once all encoders are update to use {@link EncoderConfigParams}
  */
-@Deprecated(forRemoval = true)
 public class CodecEncoderTestBase extends CodecTestBase {
     private static final String LOG_TAG = CodecEncoderTestBase.class.getSimpleName();
 
+    protected final EncoderConfigParams[] mEncCfgParams;
+
+    protected EncoderConfigParams mActiveEncCfg;
+    protected RawResource mActiveRawRes;
+    protected boolean mIsLoopBack;
+    protected int mLoopBackFrameLimit;
+
+    protected byte[] mInputData;
+    protected int mInputBufferReadOffset;
+    protected int mNumBytesSubmitted;
+    protected long mInputOffsetPts;
+
+    protected ArrayList<MediaCodec.BufferInfo> mInfoList = new ArrayList<>();
+
+    protected boolean mMuxOutput;
+    protected String mMuxedOutputFile;
+    protected MediaMuxer mMuxer;
+    protected int mTrackID = -1;
+
+    public CodecEncoderTestBase(String encoder, String mime, EncoderConfigParams[] encCfgParams,
+            String allTestParams) {
+        super(encoder, mime, allTestParams);
+        mEncCfgParams = encCfgParams;
+    }
+
+    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_MP4 = new ArrayList<>(
+            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+                    MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
+                    MediaFormat.MIMETYPE_AUDIO_AAC));
+    static {
+        if (CodecTestBase.IS_AT_LEAST_U) {
+            MEDIATYPE_LIST_FOR_TYPE_MP4.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+        }
+    }
+    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_WEBM =
+            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
+                    MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
+    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_3GP =
+            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+                    MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
+                    MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
+    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_OGG =
+            Collections.singletonList(MediaFormat.MIMETYPE_AUDIO_OPUS);
+
+    public static final float ACCEPTABLE_WIRELESS_TX_QUALITY = 20.0f;  // psnr in dB
+    public static final float ACCEPTABLE_AV_SYNC_ERROR = 22.0f; // duration in ms
+
     /**
      * Selects encoder input color format in byte buffer mode. As of now ndk tests support only
      * 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
@@ -72,50 +126,90 @@
         return colorFormat;
     }
 
-    protected final int[] mBitrates;
-    protected final int[] mEncParamList1;
-    protected final int[] mEncParamList2;
-
-    protected RawResource mActiveRawRes;
-    protected byte[] mInputData;
-    protected int mInputBufferReadOffset;
-    protected int mNumBytesSubmitted;
-    protected long mInputOffsetPts;
-
-    protected ArrayList<MediaFormat> mFormats;
-    protected ArrayList<MediaCodec.BufferInfo> mInfoList;
-
-    protected int mWidth, mHeight;
-    protected int mBytesPerSample;
-    protected int mFrameRate;
-    protected int mMaxBFrames;
-    protected int mChannels;
-    protected int mSampleRate;
-    protected int mLoopBackFrameLimit;
-    protected boolean mIsLoopBack;
-
-    public CodecEncoderTestBase(String encoder, String mime, int[] bitrates, int[] encoderInfo1,
-            int[] encoderInfo2, RawResource rawResource, String allTestParams) {
-        super(encoder, mime, allTestParams);
-        mBitrates = bitrates;
-        mEncParamList1 = encoderInfo1;
-        mEncParamList2 = encoderInfo2;
-        mFormats = new ArrayList<>();
-        mInfoList = new ArrayList<>();
-        mWidth = 0;
-        mHeight = 0;
-        if (mime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
-            mFrameRate = 12;
-        } else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_H263)) {
-            mFrameRate = 12;
-        } else {
-            mFrameRate = 30;
+    public static void muxOutput(String filePath, int muxerFormat, MediaFormat format,
+            ByteBuffer buffer, ArrayList<MediaCodec.BufferInfo> infos) throws IOException {
+        MediaMuxer muxer = null;
+        try {
+            muxer = new MediaMuxer(filePath, muxerFormat);
+            int trackID = muxer.addTrack(format);
+            muxer.start();
+            for (MediaCodec.BufferInfo info : infos) {
+                muxer.writeSampleData(trackID, buffer, info);
+            }
+            muxer.stop();
+        } finally {
+            if (muxer != null) muxer.release();
         }
-        mMaxBFrames = 0;
-        mChannels = 0;
-        mSampleRate = 0;
-        mActiveRawRes = rawResource;
-        mBytesPerSample = mActiveRawRes.mBytesPerSample;
+    }
+
+    public static boolean isMediaTypeContainerPairValid(String mime, int format) {
+        boolean result = false;
+        if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) {
+            result = MEDIATYPE_LIST_FOR_TYPE_MP4.contains(mime) || mime.startsWith("application/");
+        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
+            result = MEDIATYPE_LIST_FOR_TYPE_WEBM.contains(mime);
+        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
+            result = MEDIATYPE_LIST_FOR_TYPE_3GP.contains(mime);
+        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
+            result = MEDIATYPE_LIST_FOR_TYPE_OGG.contains(mime);
+        }
+        return result;
+    }
+
+    public static int getMuxerFormatForMediaType(String mediaType) {
+        for (int muxFormat = MUXER_OUTPUT_FIRST; muxFormat <= MUXER_OUTPUT_LAST; muxFormat++) {
+            if (isMediaTypeContainerPairValid(mediaType, muxFormat)) {
+                return muxFormat;
+            }
+        }
+        fail("no configured muxer support for " + mediaType);
+        return MUXER_OUTPUT_LAST;
+    }
+
+    public static String getTempFilePath(String infix) throws IOException {
+        return File.createTempFile("tmp" + infix, ".bin").getAbsolutePath();
+    }
+
+    public static void validateEncodedPSNR(String inpMediaType, String inpFile,
+            String outMediaType, String outFile, boolean allowInpResize, boolean allowInpLoopBack,
+            double perFramePsnrThreshold)
+            throws IOException, InterruptedException {
+        CompareStreams cs = new CompareStreams(inpMediaType, inpFile, outMediaType, outFile,
+                allowInpResize, allowInpLoopBack);
+        validateEncodedPSNR(cs, perFramePsnrThreshold);
+        cs.cleanUp();
+    }
+
+    public static void validateEncodedPSNR(RawResource inp, String outMediaType, String outFile,
+            boolean allowInpResize, boolean allowInpLoopBack, double perFramePsnrThreshold)
+            throws IOException, InterruptedException {
+        CompareStreams cs = new CompareStreams(inp, outMediaType, outFile, allowInpResize,
+                allowInpLoopBack);
+        validateEncodedPSNR(cs, perFramePsnrThreshold);
+        cs.cleanUp();
+    }
+
+    public static void validateEncodedPSNR(@NonNull CompareStreams cs,
+            double perFramePsnrThreshold) throws IOException {
+        ArrayList<double[]> framesPSNR = cs.getFramesPSNR();
+        StringBuilder msg = new StringBuilder();
+        boolean isOk = true;
+        for (int j = 0; j < framesPSNR.size(); j++) {
+            double[] framePSNR = framesPSNR.get(j);
+            // https://www.itu.int/wftp3/av-arch/jctvc-site/2011_01_D_Daegu/JCTVC-D500.doc
+            // weighted psnr (6 * psnrY + psnrU + psnrV) / 8;
+            double weightPSNR = (6 * framePSNR[0] + framePSNR[1] + framePSNR[2]) / 8;
+            if (weightPSNR < perFramePsnrThreshold) {
+                msg.append(String.format(
+                        "Frame %d - PSNR Y: %f, PSNR U: %f, PSNR V: %f, Weighted PSNR: %f < "
+                                + "Threshold %f \n",
+                        j, framePSNR[0], framePSNR[1], framePSNR[2], weightPSNR,
+                        perFramePsnrThreshold));
+                isOk = false;
+            }
+        }
+        assertTrue("Encountered frames with PSNR less than configured threshold "
+                + perFramePsnrThreshold + "dB \n" + msg, isOk);
     }
 
     public static String bitRateModeToString(int mode) {
@@ -133,22 +227,96 @@
         }
     }
 
+    public static String rangeToString(int range) {
+        switch (range) {
+            case UNSPECIFIED:
+                return "unspecified";
+            case MediaFormat.COLOR_RANGE_FULL:
+                return "full";
+            case MediaFormat.COLOR_RANGE_LIMITED:
+                return "limited";
+            default:
+                return "unknown";
+        }
+    }
+
+    public static String colorStandardToString(int standard) {
+        switch (standard) {
+            case UNSPECIFIED:
+                return "unspecified";
+            case MediaFormat.COLOR_STANDARD_BT709:
+                return "bt709";
+            case MediaFormat.COLOR_STANDARD_BT601_PAL:
+                return "bt601pal";
+            case MediaFormat.COLOR_STANDARD_BT601_NTSC:
+                return "bt601ntsc";
+            case MediaFormat.COLOR_STANDARD_BT2020:
+                return "bt2020";
+            default:
+                return "unknown";
+        }
+    }
+
+    public static String colorTransferToString(int transfer) {
+        switch (transfer) {
+            case UNSPECIFIED:
+                return "unspecified";
+            case MediaFormat.COLOR_TRANSFER_LINEAR:
+                return "linear";
+            case MediaFormat.COLOR_TRANSFER_SDR_VIDEO:
+                return "sdr";
+            case MediaFormat.COLOR_TRANSFER_HLG:
+                return "hlg";
+            case MediaFormat.COLOR_TRANSFER_ST2084:
+                return "st2084";
+            default:
+                return "unknown";
+        }
+    }
+
+    public static String colorFormatToString(int colorFormat, int bitDepth) {
+        switch (colorFormat) {
+            case COLOR_FormatYUV420Flexible:
+                return "yuv420flexible";
+            case COLOR_FormatYUVP010:
+                return "yuvp010";
+            case COLOR_FormatSurface:
+                if (bitDepth == 8) {
+                    return "surfacergb888";
+                } else if (bitDepth == 10) {
+                    return "surfaceabgr2101010";
+                } else {
+                    return "unknown";
+                }
+            default:
+                return "unknown";
+        }
+    }
+
+    public static String audioEncodingToString(int enc) {
+        switch (enc) {
+            case AudioFormat.ENCODING_INVALID:
+                return "invalid";
+            case AudioFormat.ENCODING_PCM_16BIT:
+                return "pcm16";
+            case AudioFormat.ENCODING_PCM_FLOAT:
+                return "pcmfloat";
+            default:
+                return "unknown";
+        }
+    }
+
     @Before
     public void setUpCodecEncoderTestBase() {
         assertTrue("Testing a mime that is neither audio nor video is not supported \n"
                 + mTestConfig, mIsAudio || mIsVideo);
     }
 
-    @Override
-    protected void configureCodec(MediaFormat format, boolean isAsync,
-            boolean signalEOSWithLastFrame, boolean isEncoder) {
-        super.configureCodec(format, isAsync, signalEOSWithLastFrame, isEncoder);
-        if (mIsAudio) {
-            mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
-            mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
-        } else {
-            mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
-            mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+    @After
+    public void tearDown() {
+        if (mMuxer != null) {
+            mMuxer.release();
+            mMuxer = null;
         }
     }
 
@@ -158,6 +326,7 @@
         mInputBufferReadOffset = 0;
         mNumBytesSubmitted = 0;
         mInputOffsetPts = 0;
+        mInfoList.clear();
     }
 
     protected void setUpSource(String inpPath) throws IOException {
@@ -175,7 +344,7 @@
                 format == ImageFormat.YUV_420_888 || format == ImageFormat.YCBCR_P010);
         int bytesPerSample = (ImageFormat.getBitsPerPixel(format) * 2) / (8 * 3);  // YUV420
         assertEquals("Invalid bytes per sample \n" + mTestConfig + mTestEnv, bytesPerSample,
-                mBytesPerSample);
+                mActiveRawRes.mBytesPerSample);
 
         int imageWidth = image.getWidth();
         int imageHeight = image.getHeight();
@@ -237,13 +406,13 @@
     void fillByteBuffer(ByteBuffer inputBuffer) {
         int offset = 0, frmOffset = mInputBufferReadOffset;
         for (int plane = 0; plane < 3; plane++) {
-            int width = mWidth;
-            int height = mHeight;
+            int width = mActiveEncCfg.mWidth;
+            int height = mActiveEncCfg.mHeight;
             int tileWidth = mActiveRawRes.mWidth;
             int tileHeight = mActiveRawRes.mHeight;
             if (plane != 0) {
-                width = mWidth / 2;
-                height = mHeight / 2;
+                width = mActiveEncCfg.mWidth / 2;
+                height = mActiveEncCfg.mHeight / 2;
                 tileWidth = mActiveRawRes.mWidth / 2;
                 tileHeight = mActiveRawRes.mHeight / 2;
             }
@@ -253,14 +422,16 @@
                     for (int i = 0; i < width; i += tileWidth) {
                         int colsToCopy = Math.min(width - i, tileWidth);
                         inputBuffer.position(
-                                offset + (k + j) * width * mBytesPerSample + i * mBytesPerSample);
-                        inputBuffer.put(mInputData, frmOffset + j * tileWidth * mBytesPerSample,
-                                colsToCopy * mBytesPerSample);
+                                offset + (k + j) * width * mActiveRawRes.mBytesPerSample
+                                        + i * mActiveRawRes.mBytesPerSample);
+                        inputBuffer.put(mInputData,
+                                frmOffset + j * tileWidth * mActiveRawRes.mBytesPerSample,
+                                colsToCopy * mActiveRawRes.mBytesPerSample);
                     }
                 }
             }
-            offset += width * height * mBytesPerSample;
-            frmOffset += tileWidth * tileHeight * mBytesPerSample;
+            offset += width * height * mActiveRawRes.mBytesPerSample;
+            frmOffset += tileWidth * tileHeight * mActiveRawRes.mBytesPerSample;
         }
     }
 
@@ -276,10 +447,11 @@
             int flags = 0;
             long pts = mInputOffsetPts;
             if (mIsAudio) {
-                pts += mNumBytesSubmitted * 1000000L / ((long) mBytesPerSample * mChannels
-                        * mSampleRate);
+                pts += mNumBytesSubmitted * 1000000L / ((long) mActiveRawRes.mBytesPerSample
+                        * mActiveEncCfg.mChannelCount * mActiveEncCfg.mSampleRate);
                 size = Math.min(inputBuffer.capacity(), mInputData.length - mInputBufferReadOffset);
-                assertEquals(0, size % ((long) mBytesPerSample * mChannels));
+                assertEquals(0, size % ((long) mActiveRawRes.mBytesPerSample
+                        * mActiveEncCfg.mChannelCount));
                 inputBuffer.put(mInputData, mInputBufferReadOffset, size);
                 if (mSignalEOSWithLastFrame) {
                     if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
@@ -290,8 +462,9 @@
                 }
                 mInputBufferReadOffset += size;
             } else {
-                pts += mInputCount * 1000000L / mFrameRate;
-                size = mBytesPerSample * mWidth * mHeight * 3 / 2;
+                pts += mInputCount * 1000000L / mActiveEncCfg.mFrameRate;
+                size = mActiveRawRes.mBytesPerSample * mActiveEncCfg.mWidth * mActiveEncCfg.mHeight
+                        * 3 / 2;
                 int frmSize = mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
                         * mActiveRawRes.mHeight * 3 / 2;
                 if (mInputBufferReadOffset + frmSize > mInputData.length) {
@@ -331,19 +504,26 @@
             mSawOutputEOS = true;
         }
         if (info.size > 0) {
+            ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
             if (mSaveToMem) {
                 MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
                 copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
                         info.flags);
                 mInfoList.add(copy);
 
-                ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
                 mOutputBuff.saveToMemory(buf, info);
             }
             if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                 mOutputBuff.saveOutPTS(info.presentationTimeUs);
                 mOutputCount++;
             }
+            if (mMuxer != null) {
+                if (mTrackID == -1) {
+                    mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
+                    mMuxer.start();
+                }
+                mMuxer.writeSampleData(mTrackID, buf, info);
+            }
         }
         mCodec.releaseOutputBuffer(bufferIndex, false);
     }
@@ -351,10 +531,30 @@
     @Override
     protected void doWork(int frameLimit) throws IOException, InterruptedException {
         mLoopBackFrameLimit = frameLimit;
+        if (mMuxOutput) {
+            int muxerFormat = getMuxerFormatForMediaType(mMime);
+            mMuxedOutputFile = getTempFilePath((mActiveEncCfg.mInputBitDepth == 10) ? "10bit" : "");
+            mMuxer = new MediaMuxer(mMuxedOutputFile, muxerFormat);
+        }
         super.doWork(frameLimit);
     }
 
     @Override
+    public void waitForAllOutputs() throws InterruptedException {
+        super.waitForAllOutputs();
+        if (mMuxOutput) {
+            if (mTrackID != -1) {
+                mMuxer.stop();
+                mTrackID = -1;
+            }
+            if (mMuxer != null) {
+                mMuxer.release();
+                mMuxer = null;
+            }
+        }
+    }
+
+    @Override
     protected PersistableBundle validateMetrics(String codec, MediaFormat format) {
         PersistableBundle metrics = super.validateMetrics(codec, format);
         assertEquals("error! metrics#MetricsConstants.MIME_TYPE is not as expected \n" + mTestConfig
@@ -364,74 +564,39 @@
         return metrics;
     }
 
-    protected void setUpParams(int limit) {
-        int count = 0;
-        for (int bitrate : mBitrates) {
-            if (mIsAudio) {
-                for (int rate : mEncParamList1) {
-                    for (int channels : mEncParamList2) {
-                        MediaFormat format = new MediaFormat();
-                        format.setString(MediaFormat.KEY_MIME, mMime);
-                        if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
-                            format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, bitrate);
-                        } else {
-                            format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-                        }
-                        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
-                        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
-                        mFormats.add(format);
-                        count++;
-                        if (count >= limit) return;
-                    }
-                }
-            } else {
-                assertEquals("Wrong number of height, width parameters \n" + mTestConfig + mTestEnv,
-                        mEncParamList1.length, mEncParamList2.length);
-                for (int i = 0; i < mEncParamList1.length; i++) {
-                    MediaFormat format = new MediaFormat();
-                    format.setString(MediaFormat.KEY_MIME, mMime);
-                    format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-                    format.setInteger(MediaFormat.KEY_WIDTH, mEncParamList1[i]);
-                    format.setInteger(MediaFormat.KEY_HEIGHT, mEncParamList2[i]);
-                    format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
-                    format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
-                    format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
-                    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                            MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
-                    mFormats.add(format);
-                    count++;
-                    if (count >= limit) return;
-                }
-            }
-        }
-    }
-
-    public void encodeToMemory(String file, String encoder, int frameLimit, MediaFormat format,
-            boolean saveToMem) throws IOException, InterruptedException {
+    public void encodeToMemory(String encoder, EncoderConfigParams cfg, RawResource res,
+            int frameLimit, boolean saveToMem, boolean muxOutput)
+            throws IOException, InterruptedException {
         mSaveToMem = saveToMem;
+        mMuxOutput = muxOutput;
         mOutputBuff = new OutputManager();
         mInfoList.clear();
+        mActiveEncCfg = cfg;
+        mActiveRawRes = res;
         mCodec = MediaCodec.createByCodecName(encoder);
-        setUpSource(file);
-        configureCodec(format, false, true, true);
+        setUpSource(mActiveRawRes.mFileName);
+        configureCodec(mActiveEncCfg.getFormat(), false, true, true);
         mCodec.start();
         doWork(frameLimit);
         queueEOS();
         waitForAllOutputs();
         mCodec.stop();
         mCodec.release();
+        mActiveRawRes = null;
+        mActiveEncCfg = null;
         mSaveToMem = false;
+        mMuxOutput = false;
     }
 
     void validateTestState() {
         super.validateTestState();
-        if ((mIsAudio || (mIsVideo && mMaxBFrames == 0))
+        if ((mIsAudio || (mIsVideo && mActiveEncCfg.mMaxBFrames == 0))
                 && !mOutputBuff.isPtsStrictlyIncreasing(mPrevOutputPts)) {
             fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
                     + mOutputBuff.getErrMsg());
         }
         if (mIsVideo) {
-            if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mMaxBFrames != 0))) {
+            if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mActiveEncCfg.mMaxBFrames != 0))) {
                 fail("Input pts list and Output pts list are not identical \n" + mTestConfig
                         + mTestEnv + mOutputBuff.getErrMsg());
             }
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index e3acdea..08a958f 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -108,6 +108,7 @@
     //TODO(b/248315681) Remove codenameEquals() check once devices return correct version for U
     public static final boolean IS_AT_LEAST_U = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU)
             || ApiLevelUtil.codenameEquals("UpsideDownCake");
+    public static final boolean IS_BEFORE_U = !IS_AT_LEAST_U;
     public static final boolean FIRST_SDK_IS_AT_LEAST_T =
             ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU);
     public static final boolean VNDK_IS_AT_LEAST_T =
diff --git a/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java
deleted file mode 100644
index c629278..0000000
--- a/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.mediav2.common.cts;
-
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
-import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
-import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.graphics.ImageFormat;
-import android.media.AudioFormat;
-import android.media.Image;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.media.MediaMuxer;
-import android.os.PersistableBundle;
-import android.util.Log;
-
-import com.android.compatibility.common.util.Preconditions;
-
-import org.junit.After;
-import org.junit.Before;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Wrapper class for trying and testing encoder components.
- */
-public class EncoderTestBase extends CodecTestBase {
-    private static final String LOG_TAG = EncoderTestBase.class.getSimpleName();
-
-    protected final EncoderConfigParams[] mEncCfgParams;
-
-    protected EncoderConfigParams mActiveEncCfg;
-    protected RawResource mActiveRawRes;
-    protected boolean mIsLoopBack;
-    protected int mLoopBackFrameLimit;
-
-    protected byte[] mInputData;
-    protected int mInputBufferReadOffset;
-    protected int mNumBytesSubmitted;
-    protected long mInputOffsetPts;
-
-    protected ArrayList<MediaCodec.BufferInfo> mInfoList = new ArrayList<>();
-
-    protected boolean mMuxOutput;
-    protected String mMuxedOutputFile;
-    protected MediaMuxer mMuxer;
-    protected int mTrackID = -1;
-
-    public EncoderTestBase(String encoder, String mime, EncoderConfigParams[] encCfgParams,
-            String allTestParams) {
-        super(encoder, mime, allTestParams);
-        mEncCfgParams = encCfgParams;
-    }
-
-    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_MP4 = new ArrayList<>(
-            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
-                    MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
-                    MediaFormat.MIMETYPE_AUDIO_AAC));
-    static {
-        if (CodecTestBase.IS_AT_LEAST_U) {
-            MEDIATYPE_LIST_FOR_TYPE_MP4.add(MediaFormat.MIMETYPE_VIDEO_AV1);
-        }
-    }
-    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_WEBM =
-            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
-                    MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
-    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_3GP =
-            Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
-                    MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
-                    MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
-    private static final List<String> MEDIATYPE_LIST_FOR_TYPE_OGG =
-            Collections.singletonList(MediaFormat.MIMETYPE_AUDIO_OPUS);
-
-    public static final float ACCEPTABLE_WIRELESS_TX_QUALITY = 20.0f;  // psnr in dB
-    public static final float ACCEPTABLE_AV_SYNC_ERROR = 22.0f; // duration in ms
-
-    /**
-     * Selects encoder input color format in byte buffer mode. As of now ndk tests support only
-     * 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
-     * work in ndk due to lack of AMediaCodec_GetInputImage()
-     */
-    public static int findByteBufferColorFormat(String encoder, String mime) throws IOException {
-        MediaCodec codec = MediaCodec.createByCodecName(encoder);
-        MediaCodecInfo.CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime);
-        int colorFormat = -1;
-        for (int c : cap.colorFormats) {
-            if (c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
-                    || c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {
-                Log.v(LOG_TAG, "selecting color format: " + c);
-                colorFormat = c;
-                break;
-            }
-        }
-        codec.release();
-        return colorFormat;
-    }
-
-    public static void muxOutput(String filePath, int muxerFormat, MediaFormat format,
-            ByteBuffer buffer, ArrayList<MediaCodec.BufferInfo> infos) throws IOException {
-        MediaMuxer muxer = null;
-        try {
-            muxer = new MediaMuxer(filePath, muxerFormat);
-            int trackID = muxer.addTrack(format);
-            muxer.start();
-            for (MediaCodec.BufferInfo info : infos) {
-                muxer.writeSampleData(trackID, buffer, info);
-            }
-            muxer.stop();
-        } finally {
-            if (muxer != null) muxer.release();
-        }
-    }
-
-    public static boolean isMediaTypeContainerPairValid(String mime, int format) {
-        boolean result = false;
-        if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) {
-            result = MEDIATYPE_LIST_FOR_TYPE_MP4.contains(mime) || mime.startsWith("application/");
-        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
-            result = MEDIATYPE_LIST_FOR_TYPE_WEBM.contains(mime);
-        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
-            result = MEDIATYPE_LIST_FOR_TYPE_3GP.contains(mime);
-        } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
-            result = MEDIATYPE_LIST_FOR_TYPE_OGG.contains(mime);
-        }
-        return result;
-    }
-
-    public static int getMuxerFormatForMediaType(String mediaType) {
-        for (int muxFormat = MUXER_OUTPUT_FIRST; muxFormat <= MUXER_OUTPUT_LAST; muxFormat++) {
-            if (isMediaTypeContainerPairValid(mediaType, muxFormat)) {
-                return muxFormat;
-            }
-        }
-        fail("no configured muxer support for " + mediaType);
-        return MUXER_OUTPUT_LAST;
-    }
-
-    public static String getTempFilePath(String infix) throws IOException {
-        return File.createTempFile("tmp" + infix, ".bin").getAbsolutePath();
-    }
-
-    public static String bitRateModeToString(int mode) {
-        switch (mode) {
-            case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR:
-                return "cbr";
-            case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR:
-                return "vbr";
-            case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ:
-                return "cq";
-            case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD:
-                return "cbrwithfd";
-            default:
-                return "unknown";
-        }
-    }
-
-    public static String rangeToString(int range) {
-        switch (range) {
-            case UNSPECIFIED:
-                return "unspecified";
-            case MediaFormat.COLOR_RANGE_FULL:
-                return "full";
-            case MediaFormat.COLOR_RANGE_LIMITED:
-                return "limited";
-            default:
-                return "unknown";
-        }
-    }
-
-    public static String colorStandardToString(int standard) {
-        switch (standard) {
-            case UNSPECIFIED:
-                return "unspecified";
-            case MediaFormat.COLOR_STANDARD_BT709:
-                return "bt709";
-            case MediaFormat.COLOR_STANDARD_BT601_PAL:
-                return "bt601pal";
-            case MediaFormat.COLOR_STANDARD_BT601_NTSC:
-                return "bt601ntsc";
-            case MediaFormat.COLOR_STANDARD_BT2020:
-                return "bt2020";
-            default:
-                return "unknown";
-        }
-    }
-
-    public static String colorTransferToString(int transfer) {
-        switch (transfer) {
-            case UNSPECIFIED:
-                return "unspecified";
-            case MediaFormat.COLOR_TRANSFER_LINEAR:
-                return "linear";
-            case MediaFormat.COLOR_TRANSFER_SDR_VIDEO:
-                return "sdr";
-            case MediaFormat.COLOR_TRANSFER_HLG:
-                return "hlg";
-            case MediaFormat.COLOR_TRANSFER_ST2084:
-                return "st2084";
-            default:
-                return "unknown";
-        }
-    }
-
-    public static String colorFormatToString(int colorFormat, int bitDepth) {
-        switch (colorFormat) {
-            case COLOR_FormatYUV420Flexible:
-                return "yuv420flexible";
-            case COLOR_FormatYUVP010:
-                return "yuvp010";
-            case COLOR_FormatSurface:
-                if (bitDepth == 8) {
-                    return "surfacergb888";
-                } else if (bitDepth == 10) {
-                    return "surfaceabgr2101010";
-                } else {
-                    return "unknown";
-                }
-            default:
-                return "unknown";
-        }
-    }
-
-    public static String audioEncodingToString(int enc) {
-        switch (enc) {
-            case AudioFormat.ENCODING_INVALID:
-                return "invalid";
-            case AudioFormat.ENCODING_PCM_16BIT:
-                return "pcm16";
-            case AudioFormat.ENCODING_PCM_FLOAT:
-                return "pcmfloat";
-            default:
-                return "unknown";
-        }
-    }
-
-    @Before
-    public void setUpCodecEncoderTestBase() {
-        assertTrue("Testing a mime that is neither audio nor video is not supported \n"
-                + mTestConfig, mIsAudio || mIsVideo);
-    }
-
-    @After
-    public void tearDown() {
-        if (mMuxer != null) {
-            mMuxer.release();
-            mMuxer = null;
-        }
-    }
-
-    @Override
-    protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
-        super.resetContext(isAsync, signalEOSWithLastFrame);
-        mInputBufferReadOffset = 0;
-        mNumBytesSubmitted = 0;
-        mInputOffsetPts = 0;
-        mInfoList.clear();
-    }
-
-    protected void setUpSource(String inpPath) throws IOException {
-        Preconditions.assertTestFileExists(inpPath);
-        try (FileInputStream fInp = new FileInputStream(inpPath)) {
-            int size = (int) new File(inpPath).length();
-            mInputData = new byte[size];
-            fInp.read(mInputData, 0, size);
-        }
-    }
-
-    protected void fillImage(Image image) {
-        int format = image.getFormat();
-        assertTrue("unexpected image format \n" + mTestConfig + mTestEnv,
-                format == ImageFormat.YUV_420_888 || format == ImageFormat.YCBCR_P010);
-        int bytesPerSample = (ImageFormat.getBitsPerPixel(format) * 2) / (8 * 3);  // YUV420
-        assertEquals("Invalid bytes per sample \n" + mTestConfig + mTestEnv, bytesPerSample,
-                mActiveRawRes.mBytesPerSample);
-
-        int imageWidth = image.getWidth();
-        int imageHeight = image.getHeight();
-        Image.Plane[] planes = image.getPlanes();
-        int offset = mInputBufferReadOffset;
-        for (int i = 0; i < planes.length; ++i) {
-            ByteBuffer buf = planes[i].getBuffer();
-            int width = imageWidth;
-            int height = imageHeight;
-            int tileWidth = mActiveRawRes.mWidth;
-            int tileHeight = mActiveRawRes.mHeight;
-            int rowStride = planes[i].getRowStride();
-            int pixelStride = planes[i].getPixelStride();
-            if (i != 0) {
-                width = imageWidth / 2;
-                height = imageHeight / 2;
-                tileWidth = mActiveRawRes.mWidth / 2;
-                tileHeight = mActiveRawRes.mHeight / 2;
-            }
-            if (pixelStride == bytesPerSample) {
-                if (width == rowStride && width == tileWidth && height == tileHeight) {
-                    buf.put(mInputData, offset, width * height * bytesPerSample);
-                } else {
-                    for (int z = 0; z < height; z += tileHeight) {
-                        int rowsToCopy = Math.min(height - z, tileHeight);
-                        for (int y = 0; y < rowsToCopy; y++) {
-                            for (int x = 0; x < width; x += tileWidth) {
-                                int colsToCopy = Math.min(width - x, tileWidth);
-                                buf.position((z + y) * rowStride + x * bytesPerSample);
-                                buf.put(mInputData, offset + y * tileWidth * bytesPerSample,
-                                        colsToCopy * bytesPerSample);
-                            }
-                        }
-                    }
-                }
-            } else {
-                // do it pixel-by-pixel
-                for (int z = 0; z < height; z += tileHeight) {
-                    int rowsToCopy = Math.min(height - z, tileHeight);
-                    for (int y = 0; y < rowsToCopy; y++) {
-                        int lineOffset = (z + y) * rowStride;
-                        for (int x = 0; x < width; x += tileWidth) {
-                            int colsToCopy = Math.min(width - x, tileWidth);
-                            for (int w = 0; w < colsToCopy; w++) {
-                                for (int bytePos = 0; bytePos < bytesPerSample; bytePos++) {
-                                    buf.position(lineOffset + (x + w) * pixelStride + bytePos);
-                                    buf.put(mInputData[offset + y * tileWidth * bytesPerSample
-                                            + w * bytesPerSample + bytePos]);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            offset += tileWidth * tileHeight * bytesPerSample;
-        }
-    }
-
-    void fillByteBuffer(ByteBuffer inputBuffer) {
-        int offset = 0, frmOffset = mInputBufferReadOffset;
-        for (int plane = 0; plane < 3; plane++) {
-            int width = mActiveEncCfg.mWidth;
-            int height = mActiveEncCfg.mHeight;
-            int tileWidth = mActiveRawRes.mWidth;
-            int tileHeight = mActiveRawRes.mHeight;
-            if (plane != 0) {
-                width = mActiveEncCfg.mWidth / 2;
-                height = mActiveEncCfg.mHeight / 2;
-                tileWidth = mActiveRawRes.mWidth / 2;
-                tileHeight = mActiveRawRes.mHeight / 2;
-            }
-            for (int k = 0; k < height; k += tileHeight) {
-                int rowsToCopy = Math.min(height - k, tileHeight);
-                for (int j = 0; j < rowsToCopy; j++) {
-                    for (int i = 0; i < width; i += tileWidth) {
-                        int colsToCopy = Math.min(width - i, tileWidth);
-                        inputBuffer.position(
-                                offset + (k + j) * width * mActiveRawRes.mBytesPerSample
-                                        + i * mActiveRawRes.mBytesPerSample);
-                        inputBuffer.put(mInputData,
-                                frmOffset + j * tileWidth * mActiveRawRes.mBytesPerSample,
-                                colsToCopy * mActiveRawRes.mBytesPerSample);
-                    }
-                }
-            }
-            offset += width * height * mActiveRawRes.mBytesPerSample;
-            frmOffset += tileWidth * tileHeight * mActiveRawRes.mBytesPerSample;
-        }
-    }
-
-    protected void enqueueInput(int bufferIndex) {
-        if (mIsLoopBack && mInputBufferReadOffset >= mInputData.length) {
-            mInputBufferReadOffset = 0;
-        }
-        ByteBuffer inputBuffer = mCodec.getInputBuffer(bufferIndex);
-        if (mInputBufferReadOffset >= mInputData.length) {
-            enqueueEOS(bufferIndex);
-        } else {
-            int size;
-            int flags = 0;
-            long pts = mInputOffsetPts;
-            if (mIsAudio) {
-                pts += mNumBytesSubmitted * 1000000L / ((long) mActiveRawRes.mBytesPerSample
-                        * mActiveEncCfg.mChannelCount * mActiveEncCfg.mSampleRate);
-                size = Math.min(inputBuffer.capacity(), mInputData.length - mInputBufferReadOffset);
-                assertEquals(0, size % ((long) mActiveRawRes.mBytesPerSample
-                        * mActiveEncCfg.mChannelCount));
-                inputBuffer.put(mInputData, mInputBufferReadOffset, size);
-                if (mSignalEOSWithLastFrame) {
-                    if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
-                            (mInputBufferReadOffset + size >= mInputData.length)) {
-                        flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
-                        mSawInputEOS = true;
-                    }
-                }
-                mInputBufferReadOffset += size;
-            } else {
-                pts += mInputCount * 1000000L / mActiveEncCfg.mFrameRate;
-                size = mActiveRawRes.mBytesPerSample * mActiveEncCfg.mWidth * mActiveEncCfg.mHeight
-                        * 3 / 2;
-                int frmSize = mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
-                        * mActiveRawRes.mHeight * 3 / 2;
-                if (mInputBufferReadOffset + frmSize > mInputData.length) {
-                    fail("received partial frame to encode \n" + mTestConfig + mTestEnv);
-                } else {
-                    Image img = mCodec.getInputImage(bufferIndex);
-                    assertNotNull("getInputImage() expected to return non-null for video \n"
-                            + mTestConfig + mTestEnv, img);
-                    fillImage(img);
-                }
-                if (mSignalEOSWithLastFrame) {
-                    if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
-                            (mInputBufferReadOffset + frmSize >= mInputData.length)) {
-                        flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
-                        mSawInputEOS = true;
-                    }
-                }
-                mInputBufferReadOffset += frmSize;
-            }
-            mNumBytesSubmitted += size;
-            if (ENABLE_LOGS) {
-                Log.v(LOG_TAG, "input: id: " + bufferIndex + " size: " + size + " pts: " + pts
-                        + " flags: " + flags);
-            }
-            mCodec.queueInputBuffer(bufferIndex, 0, size, pts, flags);
-            mOutputBuff.saveInPTS(pts);
-            mInputCount++;
-        }
-    }
-
-    protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
-        if (ENABLE_LOGS) {
-            Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: "
-                    + info.size + " timestamp: " + info.presentationTimeUs);
-        }
-        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-            mSawOutputEOS = true;
-        }
-        if (info.size > 0) {
-            ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
-            if (mSaveToMem) {
-                MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
-                copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
-                        info.flags);
-                mInfoList.add(copy);
-
-                mOutputBuff.saveToMemory(buf, info);
-            }
-            if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
-                mOutputBuff.saveOutPTS(info.presentationTimeUs);
-                mOutputCount++;
-            }
-            if (mMuxer != null) {
-                if (mTrackID == -1) {
-                    mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
-                    mMuxer.start();
-                }
-                mMuxer.writeSampleData(mTrackID, buf, info);
-            }
-        }
-        mCodec.releaseOutputBuffer(bufferIndex, false);
-    }
-
-    @Override
-    protected void doWork(int frameLimit) throws IOException, InterruptedException {
-        mLoopBackFrameLimit = frameLimit;
-        if (mMuxOutput) {
-            int muxerFormat = getMuxerFormatForMediaType(mMime);
-            mMuxedOutputFile = getTempFilePath((mActiveEncCfg.mInputBitDepth == 10) ? "10bit" : "");
-            mMuxer = new MediaMuxer(mMuxedOutputFile, muxerFormat);
-        }
-        super.doWork(frameLimit);
-    }
-
-    @Override
-    public void waitForAllOutputs() throws InterruptedException {
-        super.waitForAllOutputs();
-        if (mMuxOutput) {
-            if (mTrackID != -1) {
-                mMuxer.stop();
-                mTrackID = -1;
-            }
-            if (mMuxer != null) {
-                mMuxer.release();
-                mMuxer = null;
-            }
-        }
-    }
-
-    @Override
-    protected PersistableBundle validateMetrics(String codec, MediaFormat format) {
-        PersistableBundle metrics = super.validateMetrics(codec, format);
-        assertEquals("error! metrics#MetricsConstants.MIME_TYPE is not as expected \n" + mTestConfig
-                + mTestEnv, metrics.getString(MediaCodec.MetricsConstants.MIME_TYPE), mMime);
-        assertEquals("error! metrics#MetricsConstants.ENCODER is not as expected \n" + mTestConfig
-                + mTestEnv, 1, metrics.getInt(MediaCodec.MetricsConstants.ENCODER));
-        return metrics;
-    }
-
-    public void encodeToMemory(String encoder, EncoderConfigParams cfg, RawResource res,
-            int frameLimit, boolean saveToMem, boolean muxOutput)
-            throws IOException, InterruptedException {
-        mSaveToMem = saveToMem;
-        mMuxOutput = muxOutput;
-        mOutputBuff = new OutputManager();
-        mInfoList.clear();
-        mActiveEncCfg = cfg;
-        mActiveRawRes = res;
-        mCodec = MediaCodec.createByCodecName(encoder);
-        setUpSource(mActiveRawRes.mFileName);
-        configureCodec(mActiveEncCfg.getFormat(), false, true, true);
-        mCodec.start();
-        doWork(frameLimit);
-        queueEOS();
-        waitForAllOutputs();
-        mCodec.stop();
-        mCodec.release();
-        mActiveRawRes = null;
-        mActiveEncCfg = null;
-        mSaveToMem = false;
-        mMuxOutput = false;
-    }
-
-    void validateTestState() {
-        super.validateTestState();
-        if ((mIsAudio || (mIsVideo && mActiveEncCfg.mMaxBFrames == 0))
-                && !mOutputBuff.isPtsStrictlyIncreasing(mPrevOutputPts)) {
-            fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
-                    + mOutputBuff.getErrMsg());
-        }
-        if (mIsVideo) {
-            if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mActiveEncCfg.mMaxBFrames != 0))) {
-                fail("Input pts list and Output pts list are not identical \n" + mTestConfig
-                        + mTestEnv + mOutputBuff.getErrMsg());
-            }
-        }
-    }
-}
diff --git a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
index f5d9186..14ef351 100644
--- a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
@@ -35,7 +35,7 @@
 /**
  * Wrapper class for testing HDR support in video encoder components
  */
-public class HDREncoderTestBase extends EncoderTestBase {
+public class HDREncoderTestBase extends CodecEncoderTestBase {
     private static final String LOG_TAG = HDREncoderTestBase.class.getSimpleName();
 
     private ByteBuffer mHdrStaticInfo;
diff --git a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
index 12b53d4..f4f1899 100644
--- a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
@@ -27,8 +27,8 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.mediav2.common.cts.CodecDecoderTestBase;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.OutputManager;
 
 import androidx.test.filters.LargeTest;
@@ -61,7 +61,7 @@
  * </ul>
  */
 @RunWith(Parameterized.class)
-public class AudioEncoderTest extends EncoderTestBase {
+public class AudioEncoderTest extends CodecEncoderTestBase {
     public AudioEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
             @SuppressWarnings("unused") String testLabel, String allTestParams) {
         super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index 22b762f..445642f 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -19,12 +19,13 @@
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.mediav2.common.cts.CodecEncoderTestBase.ACCEPTABLE_WIRELESS_TX_QUALITY;
+import static android.mediav2.common.cts.CodecEncoderTestBase.colorFormatToString;
+import static android.mediav2.common.cts.CodecEncoderTestBase.getMuxerFormatForMediaType;
+import static android.mediav2.common.cts.CodecEncoderTestBase.getTempFilePath;
 import static android.mediav2.common.cts.CodecTestBase.hasSupportForColorFormat;
 import static android.mediav2.common.cts.CodecTestBase.isHardwareAcceleratedCodec;
 import static android.mediav2.common.cts.CodecTestBase.isSoftwareCodec;
-import static android.mediav2.common.cts.EncoderTestBase.colorFormatToString;
-import static android.mediav2.common.cts.EncoderTestBase.getMuxerFormatForMediaType;
-import static android.mediav2.common.cts.EncoderTestBase.getTempFilePath;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -40,6 +41,7 @@
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 import android.mediav2.common.cts.CodecAsyncHandler;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.CodecTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
 import android.mediav2.common.cts.OutputManager;
@@ -686,8 +688,10 @@
     public void testSimpleEncodeFromSurface() throws IOException, InterruptedException {
         mDecoder = MediaCodec.createByCodecName(mDecoderName);
         String tmpPath = null;
-        boolean muxOutput = !mEncMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1)
-                || CodecTestBase.IS_AT_LEAST_U;
+        boolean muxOutput = true;
+        if (mEncMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
+            muxOutput = false;
+        }
         {
             mEncoder = MediaCodec.createByCodecName(mEncoderName);
             /* TODO(b/149027258) */
@@ -790,6 +794,11 @@
         }
         mDecoder.release();
         mExtractor.release();
+        // Skip stream validation as there is no reference for tone mapped input
+        if (muxOutput && !mTestToneMap) {
+            CodecEncoderTestBase.validateEncodedPSNR(mTestFileMediaType, mTestFile, mEncMediaType,
+                    tmpPath, false, false, ACCEPTABLE_WIRELESS_TX_QUALITY);
+        }
         if (muxOutput) new File(tmpPath).delete();
     }
 
@@ -803,7 +812,7 @@
     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void testSimpleEncodeFromSurfaceNative() throws IOException {
+    public void testSimpleEncodeFromSurfaceNative() throws IOException, InterruptedException {
         assumeFalse("tone mapping tests are skipped in native mode", mTestToneMap);
         String tmpPath = null;
         if (!mEncMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) || CodecTestBase.IS_AT_LEAST_U) {
@@ -816,6 +825,8 @@
                 EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
         assertTrue(mTestConfig.toString(), isPass);
         if (tmpPath != null) {
+            CodecEncoderTestBase.validateEncodedPSNR(mTestFileMediaType, mTestFile, mEncMediaType,
+                    tmpPath, false, false, ACCEPTABLE_WIRELESS_TX_QUALITY);
             new File(tmpPath).delete();
         }
     }
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index 843d305..cc86e76 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -23,8 +23,8 @@
 
 import android.media.MediaCodec;
 import android.media.MediaFormat;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.OutputManager;
 import android.os.Bundle;
 import android.util.Log;
@@ -71,7 +71,7 @@
  * The test runs mediacodec in synchronous and asynchronous mode.
  */
 @RunWith(Parameterized.class)
-public class CodecEncoderTest extends EncoderTestBase {
+public class CodecEncoderTest extends CodecEncoderTestBase {
     private static final String LOG_TAG = CodecEncoderTest.class.getSimpleName();
     private static final ArrayList<String> ABR_MEDIATYPE_LIST = new ArrayList<>();
 
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
index db0bf9e..df21ded 100644
--- a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -19,7 +19,7 @@
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
-import static android.mediav2.common.cts.EncoderTestBase.colorFormatToString;
+import static android.mediav2.common.cts.CodecEncoderTestBase.colorFormatToString;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
index a07dc4d..a2f4b76 100644
--- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
@@ -28,9 +28,9 @@
 import android.media.MediaCodecList;
 import android.media.MediaFormat;
 import android.mediav2.common.cts.CodecDecoderTestBase;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.CodecTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.OutputManager;
 import android.opengl.GLES20;
 import android.os.Build;
@@ -73,7 +73,7 @@
  * restricted to HLG/HDR profiles.
  */
 @RunWith(Parameterized.class)
-public class EncoderColorAspectsTest extends EncoderTestBase {
+public class EncoderColorAspectsTest extends CodecEncoderTestBase {
     private static final String LOG_TAG = EncoderColorAspectsTest.class.getSimpleName();
 
     private Surface mInpSurface;
@@ -285,11 +285,6 @@
     public void testColorAspects() throws IOException, InterruptedException {
         Assume.assumeTrue("Test introduced with Android 11", sIsAtLeastR);
 
-        if (mCodecName.equals("OMX.google.h264.encoder")) {  // TODO(b/189883530)
-            Log.d(LOG_TAG, "test skipped due to b/189883530");
-            return;
-        }
-
         mActiveEncCfg = mEncCfgParams[0];
         if (mActiveEncCfg.mInputBitDepth > 8) {
             // Check if encoder is capable of supporting HDR profiles.
diff --git a/tests/media/src/android/mediav2/cts/EncoderInput.java b/tests/media/src/android/mediav2/cts/EncoderInput.java
index 2b7daa8..7b879b8 100644
--- a/tests/media/src/android/mediav2/cts/EncoderInput.java
+++ b/tests/media/src/android/mediav2/cts/EncoderInput.java
@@ -85,18 +85,4 @@
         }
         return null;
     }
-
-    /**
-     * TODO (b/260533828) remove this once all encoders are update to use
-     * @deprecated This function is marked for future removal. Use
-     * {@link EncoderInput#getRawResource(EncoderConfigParams)} instead.
-     */
-    @Deprecated(forRemoval = true)
-    public static RawResource getRawResource(String mediaType, boolean isHighBitDepth) {
-        if (mediaType.startsWith("audio/")) {
-            return isHighBitDepth ? INPUT_AUDIO_FILE_HBD : INPUT_AUDIO_FILE;
-        } else {
-            return isHighBitDepth ? INPUT_VIDEO_FILE_HBD : INPUT_VIDEO_FILE;
-        }
-    }
 }
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index a5eb22c..c5c9a32 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -31,8 +31,8 @@
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.OutputManager;
 import android.util.Log;
 import android.util.Pair;
@@ -75,7 +75,7 @@
  * handle certain profile and level configurations. This is verified as well.
  */
 @RunWith(Parameterized.class)
-public class EncoderProfileLevelTest extends EncoderTestBase {
+public class EncoderProfileLevelTest extends CodecEncoderTestBase {
     private static final String LOG_TAG = EncoderProfileLevelTest.class.getSimpleName();
     private static final HashMap<String, Pair<int[], Integer>> PROFILE_LEVEL_CDD = new HashMap<>();
 
diff --git a/tests/media/src/android/mediav2/cts/MuxerTest.java b/tests/media/src/android/mediav2/cts/MuxerTest.java
index 938df1b..7804408 100644
--- a/tests/media/src/android/mediav2/cts/MuxerTest.java
+++ b/tests/media/src/android/mediav2/cts/MuxerTest.java
@@ -16,7 +16,7 @@
 
 package android.mediav2.cts;
 
-import static android.mediav2.common.cts.EncoderTestBase.isMediaTypeContainerPairValid;
+import static android.mediav2.common.cts.CodecEncoderTestBase.isMediaTypeContainerPairValid;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 8a94a85..82cfae0 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -24,8 +24,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediav2.common.cts.CodecEncoderTestBase;
+import android.mediav2.common.cts.CodecTestBase;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.RawResource;
 
 import androidx.test.filters.LargeTest;
@@ -55,7 +56,7 @@
  * </ul>
  */
 @RunWith(Parameterized.class)
-public class VideoEncoderTest extends EncoderTestBase {
+public class VideoEncoderTest extends CodecEncoderTestBase {
     public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
             @SuppressWarnings("unused") String testLabel, String allTestParams) {
         super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
@@ -170,10 +171,19 @@
         RawResource res = EncoderInput.getRawResource(mEncCfgParams[0]);
         assertNotNull("no raw resource found for testing config : " + mActiveEncCfg + mTestConfig
                 + mTestEnv, res);
-        encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, false);
+
+        boolean muxOutput = true;
+        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
+            muxOutput = false;
+        }
+        encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, muxOutput);
 
         // cleanup tmp files
-        if (mMuxOutput) {
+        if (muxOutput) {
+            // validate output
+            validateEncodedPSNR(res, mMime, mMuxedOutputFile, true, mIsLoopBack,
+                    ACCEPTABLE_WIRELESS_TX_QUALITY);
+
             File tmp = new File(mMuxedOutputFile);
             if (tmp.exists()) {
                 assertTrue("unable to delete tmp file" + mMuxedOutputFile, tmp.delete());
diff --git a/tests/tests/background/Android.bp b/tests/tests/background/Android.bp
index ad0efa0..03030212 100644
--- a/tests/tests/background/Android.bp
+++ b/tests/tests/background/Android.bp
@@ -25,7 +25,6 @@
         "mockito-target-minus-junit4",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
-        "ub-uiautomator",
     ],
     libs: ["android.test.runner"],
     srcs: ["src/**/*.java"],
diff --git a/tests/tests/contactsproviderwipe/Android.bp b/tests/tests/contactsproviderwipe/Android.bp
index 2a82727..62cf0c0 100644
--- a/tests/tests/contactsproviderwipe/Android.bp
+++ b/tests/tests/contactsproviderwipe/Android.bp
@@ -25,7 +25,6 @@
         "mockito-target-minus-junit4",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
-        "ub-uiautomator",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/tests/drm/TEST_MAPPING b/tests/tests/drm/TEST_MAPPING
index 437c95c..d2fb8f4 100644
--- a/tests/tests/drm/TEST_MAPPING
+++ b/tests/tests/drm/TEST_MAPPING
@@ -3,5 +3,16 @@
     {
       "name": "CtsDrmTestCases"
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "CtsDrmTestCases",
+      "options": [
+        {
+          // TODO(b/244594813)
+          "exclude-filter": "android.drm.cts.DRMTest#testForwardLockAccess"
+        }
+      ]
+    }
   ]
 }
diff --git a/tests/tests/hardware/Android.bp b/tests/tests/hardware/Android.bp
index ad603cc..9d337e4 100644
--- a/tests/tests/hardware/Android.bp
+++ b/tests/tests/hardware/Android.bp
@@ -65,7 +65,6 @@
         "cts-wm-util",
         "mockito-target-minus-junit4",
         "platform-test-annotations",
-        "ub-uiautomator",
         "ctshardware-aidl-java",
     ],
     jni_libs: [
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
index a834b0d..2e13f30 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
@@ -31,7 +31,6 @@
 import android.hardware.input.cts.InputAssistantActivity;
 import android.server.wm.WindowManagerStateHelper;
 import android.speech.RecognizerIntent;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,8 +49,6 @@
 public class UsbVoiceCommandTest extends InputHidTestCase {
     private static final String TAG = "UsbVoiceCommandTest";
 
-    private final UiDevice mUiDevice =
-            UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
     private final UiAutomation mUiAutomation =
             InstrumentationRegistry.getInstrumentation().getUiAutomation();
     private final PackageManager mPackageManager =
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
index b712fdf..30e8477 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
@@ -708,7 +708,7 @@
                     if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
                             decoderOutputFormat);
                 } else if (decoderStatus < 0) {
-                    fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+                    fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
                 } else {  // decoderStatus >= 0
                     if (!toSurface) {
                         ByteBuffer outputFrame = decoderOutputBuffers[decoderStatus];
@@ -863,7 +863,7 @@
                     if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
                             decoderOutputFormat);
                 } else if (decoderStatus < 0) {
-                    fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+                    fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
                 } else {  // decoderStatus >= 0
                     if (VERBOSE) Log.d(TAG, "surface decoder given buffer " + decoderStatus +
                             " (size=" + info.size + ")");
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
index 2baad3f..96f05c6 100755
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -359,7 +359,7 @@
                     if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
                             decoderOutputFormat);
                 } else if (decoderStatus < 0) {
-                    fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+                    fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
                 } else {  // decoderStatus >= 0
                     if (VERBOSE) Log.d(TAG, "surface decoder given buffer " + decoderStatus +
                             " (size=" + info.size + ")");
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
index 48eaa42..9750f30 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
@@ -507,7 +507,7 @@
                 if (VERBOSE) Log.v(TAG, "decoder output format changed: " + outFormat);
             } else if (res < 0) {
                 // Should be decoding error.
-                fail("unexpected result from deocder.dequeueOutputBuffer: " + res);
+                fail("unexpected result from decoder.dequeueOutputBuffer: " + res);
             } else {
                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                     sawOutputEOS = true;
diff --git a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index f879528..3c2ca72 100644
--- a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -20,6 +20,7 @@
 import android.media.MediaDrm.KeyStatus;
 import android.media.MediaDrm.MediaDrmStateException;
 import android.media.MediaDrmException;
+import android.media.MediaDrmThrowable;
 import android.media.MediaFormat;
 import android.media.NotProvisionedException;
 import android.media.ResourceBusyException;
@@ -51,6 +52,7 @@
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.junit.Assert;
 
 import java.nio.charset.Charset;
 import java.util.ArrayList;
@@ -968,6 +970,10 @@
             if (!Arrays.equals(deviceId, getByteArrayProperty(drm, DEVICEID_PROPERTY_KEY))) {
                 throw new Error("Failed to set byte array for key=" + DEVICEID_PROPERTY_KEY);
             }
+
+            for (String k: new String[] {"oemError", "errorContext"}) {
+                testIntegerProperties(drm, k);
+            }
         } finally {
             stopDrm(drm);
         }
@@ -1232,10 +1238,16 @@
 
         MediaDrm drm = null;
         boolean gotException = false;
+        final int OEM_ERROR = 123;
+        final int ERROR_CONTEXT = 456;
 
         try {
             drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
             drm.setPropertyString("drmErrorTest", "resourceContention");
+            if (getClearkeyVersionInt(drm) >= 14) {
+                drm.setPropertyString("oemError", Integer.toString(OEM_ERROR));
+                drm.setPropertyString("errorContext", Integer.toString(ERROR_CONTEXT));
+            }
             byte[] sessionId = drm.openSession();
 
             try {
@@ -1248,6 +1260,13 @@
                 if(sIsAtLeastS && !e.isTransient()) {
                         throw new Error("Expected transient ERROR_RESOURCE_CONTENTION");
                 }
+                if (getClearkeyVersionInt(drm) >= 14) {
+                    final MediaDrmThrowable mdt = e;
+                    final int RESOURCE_CONTENTION_AIDL = 16;
+                    assertEquals("Vendor Error mismatch", mdt.getVendorError(), RESOURCE_CONTENTION_AIDL);
+                    assertEquals("OEM Error mismatch", mdt.getOemError(), OEM_ERROR);
+                    assertEquals("Error context mismatch", mdt.getErrorContext(), ERROR_CONTEXT);
+                }
                 gotException = true;
             }
         } catch(Exception e) {
@@ -1643,8 +1662,6 @@
             assertTrue("Expected ERROR_SESSION_NOT_OPENED value in info",
                     e.getDiagnosticInfo().contains(
                             String.valueOf(MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED)));
-            assertEquals("No vendor error expected from Clearkey", 0, e.getVendorError());
-            assertEquals("No OEM error expected from Clearkey", 0, e.getOemError());
         }  finally {
             if (drm != null) {
                 drm.close();
@@ -1652,6 +1669,25 @@
         }
     }
 
+    private void testIntegerProperties(MediaDrm drm, String testKey)
+            throws ResourceBusyException, UnsupportedSchemeException, NotProvisionedException {
+        if (getClearkeyVersionInt(drm) < 14) {
+            return;
+        }
+        String testValue = "123456";
+        assertEquals("Default value not 0", drm.getPropertyString(testKey), "0");
+        Assert.assertThrows("Non-numeric must throw", Exception.class, () -> {
+            drm.setPropertyString(testKey, "xyz"); });
+        Assert.assertThrows("Non-integral must throw", Exception.class, () -> {
+            drm.setPropertyString(testKey, "3.141"); });
+        Assert.assertThrows("Out-of-range (MAX) must throw", Exception.class, () -> {
+            drm.setPropertyString(testKey, Long.toString(Long.MAX_VALUE)); });
+        Assert.assertThrows("Out-of-range (MIN) must throw", Exception.class, () -> {
+            drm.setPropertyString(testKey, Long.toString(Long.MIN_VALUE)); });
+        drm.setPropertyString(testKey, testValue);
+        assertEquals("Property didn't match", drm.getPropertyString(testKey), testValue);
+    }
+
     private String getClearkeyVersion(MediaDrm drm) {
         try {
             return drm.getPropertyString("version");
@@ -1660,6 +1696,14 @@
         }
     }
 
+    private int getClearkeyVersionInt(MediaDrm drm) {
+        try {
+            return Integer.parseInt(drm.getPropertyString("version"));
+        } catch (Exception e) {
+            return Integer.MIN_VALUE;
+        }
+    }
+
     private boolean cannotHandleGetPropertyByteArray(MediaDrm drm) {
         boolean apiNotSupported = false;
         byte[] bytes = new byte[0];
diff --git a/tests/tests/media/projection/OWNERS b/tests/tests/media/projection/OWNERS
new file mode 100644
index 0000000..d963c71
--- /dev/null
+++ b/tests/tests/media/projection/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 970984
+include platform/frameworks/base:/media/java/android/media/projection/OWNERS
+nmusgrave@google.com
diff --git a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
index 3e121ec..6a1077c 100644
--- a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
+++ b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
@@ -23,7 +23,6 @@
 import android.widget.ImageView
 import android.widget.TextView
 import com.google.common.truth.Truth.assertThat
-import org.junit.Assume
 
 class NotificationTemplateApi30Test : NotificationTemplateTestBase() {
 
@@ -58,7 +57,9 @@
     }
 
     fun testWideIcon_inBigPicture_isSquareForLegacyApps() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val icon = createBitmap(200, 100)
@@ -89,7 +90,9 @@
     }
 
     fun testPromoteBigPicture_withoutLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+                if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -114,7 +117,9 @@
     }
 
     fun testPromoteBigPicture_withLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val icon = createBitmap(80, 65)
@@ -143,7 +148,9 @@
     }
 
     fun testPromoteBigPicture_withBigLargeIcon() {
-        skipIfPlatformDoesNotSupportNotificationStyles()
+        if (skipIfPlatformDoesNotSupportNotificationStyles()) {
+            return
+        }
 
         val picture = createBitmap(40, 30)
         val inputWidth = 400
@@ -292,10 +299,9 @@
      *
      * If the current platform does not support notification styles, skip this test without failure.
      */
-    private fun skipIfPlatformDoesNotSupportNotificationStyles() {
-        Assume.assumeFalse("Current platform does not support notification styles.",
-                mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
-                        mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+    private fun skipIfPlatformDoesNotSupportNotificationStyles(): Boolean {
+        return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
+                        mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
     }
 
     companion object {
diff --git a/tests/tests/print/printTestUtilLib/Android.bp b/tests/tests/print/printTestUtilLib/Android.bp
index 9abb4ee..da85b79 100644
--- a/tests/tests/print/printTestUtilLib/Android.bp
+++ b/tests/tests/print/printTestUtilLib/Android.bp
@@ -24,7 +24,6 @@
     static_libs: [
         "mockito-target-minus-junit4",
         "ctstestrunner-axt",
-        "ub-uiautomator",
         "compatibility-device-util-axt",
         "androidx.test.rules",
         "platformprotosnano",
diff --git a/tests/tests/resolverservice/OWNERS b/tests/tests/resolverservice/OWNERS
index 978b1b4..87f734b 100644
--- a/tests/tests/resolverservice/OWNERS
+++ b/tests/tests/resolverservice/OWNERS
@@ -1,4 +1,2 @@
-# Bug component: 24950
-kanlig@google.com
-patb@google.com
-chiuwinson@google.com
\ No newline at end of file
+# Bug component: 36137
+include platform/frameworks/base:/PACKAGE_MANAGER_OWNERS
\ No newline at end of file
diff --git a/tests/tests/slice/Android.bp b/tests/tests/slice/Android.bp
index 891a682..d3d75f8 100644
--- a/tests/tests/slice/Android.bp
+++ b/tests/tests/slice/Android.bp
@@ -34,7 +34,6 @@
         "metrics-helper-lib",
         "mockito-target-inline-minus-junit4",
         "platform-test-annotations",
-        "ub-uiautomator",
     ],
     compile_multilib: "both",
     jni_libs: [
diff --git a/tests/tests/syncmanager/Android.bp b/tests/tests/syncmanager/Android.bp
index 2042319..b3d9216 100644
--- a/tests/tests/syncmanager/Android.bp
+++ b/tests/tests/syncmanager/Android.bp
@@ -26,7 +26,6 @@
         "mockito-target-minus-junit4",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
-        "ub-uiautomator",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/tests/syncmanager/apps/Android.bp b/tests/tests/syncmanager/apps/Android.bp
index cbcfe29..0cb4cb8 100644
--- a/tests/tests/syncmanager/apps/Android.bp
+++ b/tests/tests/syncmanager/apps/Android.bp
@@ -26,7 +26,6 @@
         "androidx.legacy_legacy-support-v4",
         "mockito-target-minus-junit4",
         "compatibility-device-util-axt",
-        "ub-uiautomator",
     ],
     sdk_version: "test_current",
     // tag this module as a cts test artifact
@@ -48,7 +47,6 @@
         "androidx.legacy_legacy-support-v4",
         "mockito-target-minus-junit4",
         "compatibility-device-util-axt",
-        "ub-uiautomator",
     ],
     sdk_version: "test_current",
     // tag this module as a cts test artifact
diff --git a/tests/tests/uiautomation/Android.bp b/tests/tests/uiautomation/Android.bp
index b4d80a8..b41d2fb 100644
--- a/tests/tests/uiautomation/Android.bp
+++ b/tests/tests/uiautomation/Android.bp
@@ -27,7 +27,6 @@
     static_libs: [
         "CtsAccessibilityCommon",
         "ctstestrunner-axt",
-        "ub-uiautomator",
     ],
     libs: ["android.test.base"],
     srcs: ["src/**/*.java"],
diff --git a/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java b/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
index 68c4a77..20f7283 100644
--- a/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
@@ -246,7 +246,7 @@
         }
 
         mReceivedEvents.add(new ReceivedEvent(event.getEventTime(), event.getAction(),
-                (int) event.getX(), (int) event.getY(), event.getSource()));
+                Math.round(event.getX()), Math.round(event.getY()), event.getSource()));
 
         // Always return true to make sure the event has been handled.
         return true;
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
index 044a311..676127c 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
@@ -27,9 +27,9 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.mediav2.common.cts.BitStreamUtils;
+import android.mediav2.common.cts.CodecEncoderTestBase;
 import android.mediav2.common.cts.DecodeStreamToYuv;
 import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
 import android.mediav2.common.cts.RawResource;
 import android.util.Log;
 
@@ -47,7 +47,7 @@
 /**
  * Wrapper class for handling and testing video encoder components.
  */
-public class VideoEncoderValidationTestBase extends EncoderTestBase {
+public class VideoEncoderValidationTestBase extends CodecEncoderTestBase {
     private static final String LOG_TAG = VideoEncoderValidationTestBase.class.getSimpleName();
     private static final String MEDIA_DIR = WorkDir.getMediaDirString();
 
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index a9c024f..1ccf352 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -103,6 +103,7 @@
         BINARY_EXCEPTIONS.add("sepolicy-analyze");
         BINARY_EXCEPTIONS.add("avbtool");
         BINARY_EXCEPTIONS.add("img2simg");
+        BINARY_EXCEPTIONS.add("initrd_bootconfig");
         BINARY_EXCEPTIONS.add("lpmake");
         BINARY_EXCEPTIONS.add("lpunpack");
         BINARY_EXCEPTIONS.add("mk_payload");