Merge "Merge "Merge "DO NOT MERGE: This test case tries to decode a corrupt image file using BitmapFactory.decodeStream which causes Process crash on an unpatched device, thus failing the test." into lollipop-cts-dev am: b0d4b6797d  -s ours" into lollipop-mr1-cts-dev am: 04ec7def27  -s ours" into marshmallow-cts-dev am: ea883af7fe  -s ours am: 69b840344d am: f758bed62a am: 136d9d0c0e am: 2655db6a27  -s ours am: d449ee6262 am: 580a6886af
am: 0a5589fd07  -s ours

* commit '0a5589fd072164947f57b1641105d937a943753f':

Change-Id: I8461b0f97cad94784a130fd53068955b4d0221fe
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index e79659b..1b63e53 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -152,7 +152,7 @@
         helpBuilder.append("  help: show this message.\n");
         helpBuilder.append("  help all: show the complete tradefed help.\n");
         helpBuilder.append("  version: show the version.\n");
-        helpBuilder.append("  exit: gracefully exit the compatibiltiy console, waiting until all ");
+        helpBuilder.append("  exit: gracefully exit the compatibility console, waiting until all ");
         helpBuilder.append("invocations have completed.\n");
         helpBuilder.append("Run:\n");
         final String runPrompt = "  run <plan> ";
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index eb4a091..19fd3bd 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner android-support-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index 85c74f9..7003012 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -27,7 +27,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
 LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner compatibility-device-util \
-	ub-uiautomator
+	ub-uiautomator android-support-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/numberblocking/app/Android.mk b/hostsidetests/numberblocking/app/Android.mk
index 492a2ec..5755f84 100644
--- a/hostsidetests/numberblocking/app/Android.mk
+++ b/hostsidetests/numberblocking/app/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index 775e679..6ce0148 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 10a6792..a467088 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -196,6 +196,8 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.app.stubs.FragmentResultActivity" android:label="FragmentResultActivity" />
+
         <activity android:name="android.app.stubs.ChildTabActivity" android:label="ChildTabActivity" />
 
         <activity android:name="android.app.stubs.LauncherActivityStub"
diff --git a/tests/app/app/src/android/app/stubs/FragmentResultActivity.java b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
new file mode 100644
index 0000000..364d093
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * A simple Activity used to return a result.
+ */
+public class FragmentResultActivity extends Activity {
+    public static final String EXTRA_RESULT_CODE = "result";
+    public static final String EXTRA_RESULT_CONTENT = "result_content";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        int resultCode = getIntent().getIntExtra(EXTRA_RESULT_CODE, Activity.RESULT_OK);
+        String result = getIntent().getStringExtra(EXTRA_RESULT_CONTENT);
+        Intent intent = new Intent();
+        intent.putExtra(EXTRA_RESULT_CONTENT, result);
+        setResult(resultCode, intent);
+        finish();
+    }
+}
diff --git a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
index 65ba911..9ca08b9 100644
--- a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Bundle;
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
diff --git a/tests/app/src/android/app/cts/FragmentReceiveResultTest.java b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
new file mode 100644
index 0000000..7535cc6
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 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.app.cts;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.stubs.FragmentResultActivity;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.R;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests Fragment's startActivityForResult and startIntentSenderForResult.
+ */
+public class FragmentReceiveResultTest extends
+        ActivityInstrumentationTestCase2<FragmentTestActivity> {
+
+    private FragmentTestActivity mActivity;
+    private TestFragment mFragment;
+
+    public FragmentReceiveResultTest() {
+        super(FragmentTestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mFragment = attachTestFragment();
+    }
+
+    @SmallTest
+    public void testStartActivityForResultOk() {
+        startActivityForResult(10, Activity.RESULT_OK, "content 10");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(10, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+        assertEquals("content 10", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartActivityForResultCanceled() {
+        startActivityForResult(20, Activity.RESULT_CANCELED, "content 20");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(20, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+        assertEquals("content 20", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartIntentSenderForResultOk() {
+        startIntentSenderForResult(30, Activity.RESULT_OK, "content 30");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(30, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+        assertEquals("content 30", mFragment.mResultContent);
+    }
+
+    @SmallTest
+    public void testStartIntentSenderForResultCanceled() {
+        startIntentSenderForResult(40, Activity.RESULT_CANCELED, "content 40");
+
+        assertTrue("Fragment should receive result", mFragment.mHasResult);
+        assertEquals(40, mFragment.mRequestCode);
+        assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+        assertEquals("content 40", mFragment.mResultContent);
+    }
+
+    private TestFragment attachTestFragment() {
+        final TestFragment fragment = new TestFragment();
+        getInstrumentation().waitForIdleSync();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.getFragmentManager().beginTransaction()
+                        .add(R.id.content, fragment)
+                        .addToBackStack(null)
+                        .commitAllowingStateLoss();
+                mActivity.getFragmentManager().executePendingTransactions();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        return fragment;
+    }
+
+    private void startActivityForResult(final int requestCode, final int resultCode,
+            final String content) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+                mFragment.startActivityForResult(intent, requestCode);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void startIntentSenderForResult(final int requestCode, final int resultCode,
+            final String content) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+                intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+                PendingIntent pendingIntent = PendingIntent.getActivity(mActivity,
+                        requestCode, intent, 0);
+
+                try {
+                    mFragment.startIntentSenderForResult(pendingIntent.getIntentSender(),
+                            requestCode, null, 0, 0, 0, null);
+                } catch (IntentSender.SendIntentException e) {
+                    fail("IntentSender failed");
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private final class TestFragment extends Fragment {
+        boolean mHasResult = false;
+        int mRequestCode = -1;
+        int mResultCode = 100;
+        String mResultContent;
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            mHasResult = true;
+            mRequestCode = requestCode;
+            mResultCode = resultCode;
+            mResultContent = data.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
+        }
+    }
+
+}
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index db687bf..4a3620e 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -345,7 +345,7 @@
 
 class StaticInfo {
   public:
-    StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
+    explicit StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
 
     bool isColorOutputSupported() {
         return isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index 4cc3606..0303dbd 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index 08201a6..cf76aa0b 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index be6a759..e192a0c 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -107,4 +107,27 @@
         }
     }
 
+    public void testGetIccAuthentication() {
+        // EAP-SIM rand is 16 bytes.
+        String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+        String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
+        if (!hasCellular) return;
+        try {
+            assertNull("getIccAuthentication should return null for empty data.",
+                    mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_AKA, ""));
+            String response = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge);
+            assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
+            // response is base64 encoded. After decoding, the value should be:
+            // 1 length byte + SRES(4 bytes) + 1 length byte + Kc(8 bytes)
+            byte[] result = android.util.Base64.decode(response, android.util.Base64.DEFAULT);
+            assertTrue("Result length must be 14 bytes.", 14 == result.length);
+            String response2 = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge2);
+            assertTrue("Two responses must be different.", !response.equals(response2));
+        } catch (SecurityException e) {
+            failMessage();
+        }
+    }
 }
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index 8b99003..d0aedec 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -25,6 +25,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.microedition.khronos.egl.EGL10;
@@ -61,20 +62,16 @@
         int detectedMajorVersion = getDetectedMajorVersion();
         int reportedVersion = getVersionFromActivityManager(mActivity);
 
-        assertEquals("Detected OpenGL ES major version " + detectedMajorVersion
-                + " but Activity Manager is reporting " +  getMajorVersion(reportedVersion)
-                + " (Check ro.opengles.version)",
-                detectedMajorVersion, getMajorVersion(reportedVersion));
         assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
                 reportedVersion, getVersionFromPackageManager(mActivity));
 
-        assertGlVersionString(1);
+        assertGlVersionString(1, 1);
         if (detectedMajorVersion == 2) {
             restartActivityWithClientVersion(2);
-            assertGlVersionString(2);
+            assertGlVersionString(2, getMinorVersion(reportedVersion));
         } else if (detectedMajorVersion == 3) {
             restartActivityWithClientVersion(3);
-            assertGlVersionString(3);
+            assertGlVersionString(3, getMinorVersion(reportedVersion));
         }
     }
 
@@ -123,14 +120,11 @@
         restartActivityWithClientVersion(3);
 
         String extensions = mActivity.getExtensionsString();
-        if (!hasExtension(extensions, "ANDROID_extension_pack_es31a")) {
-            assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available but ANDROID_extension_pack_es31a isn't in the extension list",
-                    hasAepFeature);
-            return;
-        }
-
-        assertTrue("ANDROID_extension_pack_es31a is present, but support is incomplete",
-                mActivity.getAepEs31Support());
+        boolean hasAepExtension = hasExtension(extensions, "GL_ANDROID_extension_pack_es31a");
+        assertEquals("System feature FEATURE_OPENGLES_EXTENSION_PACK is "
+            + (hasAepFeature ? "" : "not ") + "available, but extension GL_ANDROID_extension_pack_es31a is "
+            + (hasAepExtension ? "" : "not ") + "in the OpenGL ES extension list.",
+            hasAepFeature, hasAepExtension);
     }
 
     public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
@@ -289,15 +283,21 @@
     }
 
     /**
-     * Check that the version string has some form of "Open GL ES X.Y" in it where X is the major
-     * version and Y must be some digit.
+     * Check that the version string has the form "OpenGL ES(-CM)? (\d+)\.(\d+)", where the two
+     * numbers match the major and minor parameters.
      */
-    private void assertGlVersionString(int majorVersion) throws InterruptedException {
-        String versionString = "" + majorVersion;
-        String message = "OpenGL version string '" + mActivity.getVersionString()
-                + "' is not " + majorVersion + ".0+.";
-        assertTrue(message, Pattern.matches(".*OpenGL.*ES.*" + versionString + "\\.\\d.*",
-                mActivity.getVersionString()));
+    private void assertGlVersionString(int major, int minor) throws InterruptedException {
+        Matcher matcher = Pattern.compile("OpenGL ES(?:-CM)? (\\d+)\\.(\\d+).*")
+                                 .matcher(mActivity.getVersionString());
+        assertTrue("OpenGL ES version string is not of the required form "
+            + "'OpenGL ES(-CM)? (\\d+)\\.(\\d+).*'",
+            matcher.matches());
+        int stringMajor = Integer.parseInt(matcher.group(1));
+        int stringMinor = Integer.parseInt(matcher.group(2));
+        assertEquals("GL_VERSION string doesn't match ActivityManager major version (check ro.opengles.version property)",
+            major, stringMajor);
+        assertEquals("GL_VERSION string doesn't match ActivityManager minor version (check ro.opengles.version property)",
+            minor, stringMinor);
     }
 
     /** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
diff --git a/tests/tests/icu/Android.mk b/tests/tests/icu/Android.mk
index 6f183d5..39d1285 100644
--- a/tests/tests/icu/Android.mk
+++ b/tests/tests/icu/Android.mk
@@ -30,9 +30,12 @@
 
 # The aim of this package is to run tests against the implementation in use by
 # the current android system.
+LOCAL_JAVA_LIBRARIES := cts-core-test-runner
+
 LOCAL_STATIC_JAVA_LIBRARIES := \
-	cts-core-test-runner \
-	android-icu4j-tests
+	android-icu4j-tests \
+	ctstestrunner \
+	android-support-test
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 7a9504d..4a81a85 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -30,7 +30,7 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libjnitest libnativehelper_compat_libc++
 
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index fe98bc3..cde0817 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_JAVA_LIBRARIES := bouncycastle
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
+        android-support-test \
         core-tests-support \
         ctsdeviceutil \
         ctstestrunner \
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 879c72b..d61556d 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,10 +44,13 @@
 # include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
 
+# do not compress VP9 video files
+LOCAL_AAPT_FLAGS := -0 .vp9
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsMediaTestCases
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_00.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_00.vp9
new file mode 100644
index 0000000..1d65e32
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_00.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_00_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_00_vp9_md5
new file mode 100644
index 0000000..aa90d5a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_00_vp9_md5
@@ -0,0 +1,2 @@
+c3fbb7abbdb5bd4ed4a7e34768c17df1  vp90-2-00-quantizer-00-352x288-0001.i420
+08203c2595bdb2d58ead6f921345d699  vp90-2-00-quantizer-00-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_01.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_01.vp9
new file mode 100644
index 0000000..c2aebcf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_01.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_01_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_01_vp9_md5
new file mode 100644
index 0000000..85e12ba
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_01_vp9_md5
@@ -0,0 +1,2 @@
+f041b870cf9236d5f22e2b08a77d5958  vp90-2-00-quantizer-01-352x288-0001.i420
+cbdb7526986ae15592891488c9afc84c  vp90-2-00-quantizer-01-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_02.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_02.vp9
new file mode 100644
index 0000000..6baa992
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_02.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_02_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_02_vp9_md5
new file mode 100644
index 0000000..e1bbcaa
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_02_vp9_md5
@@ -0,0 +1,2 @@
+98048cfdb4af5059f4085c5acc94ef8f  vp90-2-00-quantizer-02-352x288-0001.i420
+8160183e1eed1d0af4427be216b8b9f7  vp90-2-00-quantizer-02-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_03.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_03.vp9
new file mode 100644
index 0000000..7b7ead0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_03.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_03_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_03_vp9_md5
new file mode 100644
index 0000000..fb6f597
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_03_vp9_md5
@@ -0,0 +1,2 @@
+15c548208f5eda243a151a42f4d64855  vp90-2-00-quantizer-03-352x288-0001.i420
+e96d463dc8e9b27b1c2ec40f77eee6ef  vp90-2-00-quantizer-03-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_04.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_04.vp9
new file mode 100644
index 0000000..4eb17d0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_04.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_04_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_04_vp9_md5
new file mode 100644
index 0000000..fbe7558
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_04_vp9_md5
@@ -0,0 +1,2 @@
+928c64a0747ac57ab50c1520d694fea7  vp90-2-00-quantizer-04-352x288-0001.i420
+a6f6daa293231e95ef30ed168f582c84  vp90-2-00-quantizer-04-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_05.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_05.vp9
new file mode 100644
index 0000000..b11f071
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_05.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_05_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_05_vp9_md5
new file mode 100644
index 0000000..4977060
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_05_vp9_md5
@@ -0,0 +1,2 @@
+082460718b7d7046c8fb23184b7f71ca  vp90-2-00-quantizer-05-352x288-0001.i420
+4a41aad51c40a92df72333e13f47d3fe  vp90-2-00-quantizer-05-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_06.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_06.vp9
new file mode 100644
index 0000000..11e2814
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_06.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_06_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_06_vp9_md5
new file mode 100644
index 0000000..2a90a40
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_06_vp9_md5
@@ -0,0 +1,2 @@
+cfca1bed96ff62a69b2d841fda01c6b9  vp90-2-00-quantizer-06-352x288-0001.i420
+9b4d61f1b998745c108f8eb67925e03d  vp90-2-00-quantizer-06-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_07.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_07.vp9
new file mode 100644
index 0000000..38f752c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_07.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_07_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_07_vp9_md5
new file mode 100644
index 0000000..6b77e7f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_07_vp9_md5
@@ -0,0 +1,2 @@
+6f5122064bead9d9882bec2698a6ed9c  vp90-2-00-quantizer-07-352x288-0001.i420
+50dae67d2f57a76eece210dee8b6df9e  vp90-2-00-quantizer-07-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_08.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_08.vp9
new file mode 100644
index 0000000..a666e85
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_08_vp9_md5
new file mode 100644
index 0000000..d0dba67
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_08_vp9_md5
@@ -0,0 +1,2 @@
+eb3d6985fcda5d93dd62d53354e8a093  vp90-2-00-quantizer-08-352x288-0001.i420
+5b1f5b7780b4cafe1f75e56a0b526643  vp90-2-00-quantizer-08-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_09.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_09.vp9
new file mode 100644
index 0000000..d5e9268
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_09.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_09_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_09_vp9_md5
new file mode 100644
index 0000000..a1d78c2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_09_vp9_md5
@@ -0,0 +1,2 @@
+d7ccaf28c59875fe91983def5490d2b1  vp90-2-00-quantizer-09-352x288-0001.i420
+bd98fe9492054826748de840b4495309  vp90-2-00-quantizer-09-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_10.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_10.vp9
new file mode 100644
index 0000000..ad74ec5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_10_vp9_md5
new file mode 100644
index 0000000..cc8a716
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_10_vp9_md5
@@ -0,0 +1,2 @@
+20dda6231f9801c9c237c6d09d9939b6  vp90-2-00-quantizer-10-352x288-0001.i420
+23c91e93807fb9a4ed5bd5bdd449d99f  vp90-2-00-quantizer-10-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_11.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_11.vp9
new file mode 100644
index 0000000..144a555
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_11.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_11_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_11_vp9_md5
new file mode 100644
index 0000000..39464f2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_11_vp9_md5
@@ -0,0 +1,2 @@
+960833315ebcdee97f46c4d98d0f3fef  vp90-2-00-quantizer-11-352x288-0001.i420
+eec40507d17b64b7895a61cb87b2096a  vp90-2-00-quantizer-11-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_12.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_12.vp9
new file mode 100644
index 0000000..c831b57
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_12.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_12_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_12_vp9_md5
new file mode 100644
index 0000000..57e7dbe
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_12_vp9_md5
@@ -0,0 +1,2 @@
+6533224d3b6ba1ec0dd973bbe56c6349  vp90-2-00-quantizer-12-352x288-0001.i420
+12ceadc6d28327a24a75f8c40b6084d1  vp90-2-00-quantizer-12-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_13.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_13.vp9
new file mode 100644
index 0000000..168bca9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_13.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_13_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_13_vp9_md5
new file mode 100644
index 0000000..03acb52
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_13_vp9_md5
@@ -0,0 +1,2 @@
+7268de6756014f79a56dcf010c52a97f  vp90-2-00-quantizer-13-352x288-0001.i420
+9e39e9b0e2295b8460dfa05f44762771  vp90-2-00-quantizer-13-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_14.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_14.vp9
new file mode 100644
index 0000000..0113e12
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_14.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_14_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_14_vp9_md5
new file mode 100644
index 0000000..2525db5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_14_vp9_md5
@@ -0,0 +1,2 @@
+57e9e333c641fa952f7485b788df225a  vp90-2-00-quantizer-14-352x288-0001.i420
+551f0cea83dcdf4540c3983736757874  vp90-2-00-quantizer-14-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_15.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_15.vp9
new file mode 100644
index 0000000..fe7add2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_15.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_15_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_15_vp9_md5
new file mode 100644
index 0000000..c6e5377
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_15_vp9_md5
@@ -0,0 +1,2 @@
+17a0a2842856b9e89aede237648d5dda  vp90-2-00-quantizer-15-352x288-0001.i420
+c9fcade888a38621bebe3d4b41664245  vp90-2-00-quantizer-15-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_16.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_16.vp9
new file mode 100644
index 0000000..c9c35b4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_16_vp9_md5
new file mode 100644
index 0000000..c1abf24
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_16_vp9_md5
@@ -0,0 +1,2 @@
+6cc2089e9a3d352fe10b59ccd935c677  vp90-2-00-quantizer-16-352x288-0001.i420
+d165bf7b9cb901e121a65038758d8613  vp90-2-00-quantizer-16-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_17.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_17.vp9
new file mode 100644
index 0000000..cd8dd67
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_17.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_17_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_17_vp9_md5
new file mode 100644
index 0000000..40d8f03
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_17_vp9_md5
@@ -0,0 +1,2 @@
+bc80511c83162c09661f155cd29f6dd8  vp90-2-00-quantizer-17-352x288-0001.i420
+a62f1cbdb3f86d2fb4c880cfd917def5  vp90-2-00-quantizer-17-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_18.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_18.vp9
new file mode 100644
index 0000000..4b0fe9f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_18_vp9_md5
new file mode 100644
index 0000000..3cb5fbe
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_18_vp9_md5
@@ -0,0 +1,2 @@
+b2d350f6faa41cb50c2e8a9907d0f4a5  vp90-2-00-quantizer-18-352x288-0001.i420
+39b4380d16bc8e093dd4dba475175fb3  vp90-2-00-quantizer-18-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_19.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_19.vp9
new file mode 100644
index 0000000..f14d8d6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_19.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_19_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_19_vp9_md5
new file mode 100644
index 0000000..36dbdac
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_19_vp9_md5
@@ -0,0 +1,2 @@
+441e09be3c15fcb240afd74bb7a10a72  vp90-2-00-quantizer-19-352x288-0001.i420
+32ae5dac876ca5d5ae6ab7c74f4dc25d  vp90-2-00-quantizer-19-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_20.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_20.vp9
new file mode 100644
index 0000000..062fd61
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_20.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_20_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_20_vp9_md5
new file mode 100644
index 0000000..ca80f66
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_20_vp9_md5
@@ -0,0 +1,2 @@
+7786eb9944dba0553e129133523a98c1  vp90-2-00-quantizer-20-352x288-0001.i420
+206d888f8453427f10a40aa8bf5f6df0  vp90-2-00-quantizer-20-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_21.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_21.vp9
new file mode 100644
index 0000000..500950c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_21.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_21_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_21_vp9_md5
new file mode 100644
index 0000000..b31ac9e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_21_vp9_md5
@@ -0,0 +1,2 @@
+aab95e195be71feca050a839d7b3154d  vp90-2-00-quantizer-21-352x288-0001.i420
+02a05d699bbbdc477e34bb0dad9f0391  vp90-2-00-quantizer-21-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_22.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_22.vp9
new file mode 100644
index 0000000..88dad68
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_22.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_22_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_22_vp9_md5
new file mode 100644
index 0000000..8f50f51
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_22_vp9_md5
@@ -0,0 +1,2 @@
+41f853c3ee2d4611b645cc643d82e287  vp90-2-00-quantizer-22-352x288-0001.i420
+1c240c653110ff8609ca0f0287a6496d  vp90-2-00-quantizer-22-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_23.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_23.vp9
new file mode 100644
index 0000000..1834017
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_23.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_23_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_23_vp9_md5
new file mode 100644
index 0000000..ea0aaaa
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_23_vp9_md5
@@ -0,0 +1,2 @@
+bc5b07369df50c8f97ce1a377fe513cf  vp90-2-00-quantizer-23-352x288-0001.i420
+ce62ddb4f3e305d0f8587ae8bb44cc79  vp90-2-00-quantizer-23-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_24.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_24.vp9
new file mode 100644
index 0000000..d9dac53
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_24.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_24_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_24_vp9_md5
new file mode 100644
index 0000000..49f378f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_24_vp9_md5
@@ -0,0 +1,2 @@
+982d54041221c977b6f0e37a9236cc76  vp90-2-00-quantizer-24-352x288-0001.i420
+57631e7f13f645c834e2944ebfd6d40e  vp90-2-00-quantizer-24-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_25.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_25.vp9
new file mode 100644
index 0000000..e04f1b6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_25.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_25_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_25_vp9_md5
new file mode 100644
index 0000000..90ed556
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_25_vp9_md5
@@ -0,0 +1,2 @@
+b0fb55f3f2f56b3d27038e83c10123ce  vp90-2-00-quantizer-25-352x288-0001.i420
+9fcac3becdcc2d30d778a55eca4c2018  vp90-2-00-quantizer-25-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_26.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_26.vp9
new file mode 100644
index 0000000..3b5abd3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_26.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_26_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_26_vp9_md5
new file mode 100644
index 0000000..dbec99c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_26_vp9_md5
@@ -0,0 +1,2 @@
+4f645e0f354da77b9e2f2a6753c361da  vp90-2-00-quantizer-26-352x288-0001.i420
+b7542998ec298273ca662bc9b658d10e  vp90-2-00-quantizer-26-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_27.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_27.vp9
new file mode 100644
index 0000000..6dbea83
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_27.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_27_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_27_vp9_md5
new file mode 100644
index 0000000..14ec691
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_27_vp9_md5
@@ -0,0 +1,2 @@
+6edc96a3747cad43828397045764206e  vp90-2-00-quantizer-27-352x288-0001.i420
+5fbc65d20fdca1abd69079851ce676d3  vp90-2-00-quantizer-27-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_28.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_28.vp9
new file mode 100644
index 0000000..8f928cc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_28.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_28_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_28_vp9_md5
new file mode 100644
index 0000000..0e2d177
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_28_vp9_md5
@@ -0,0 +1,2 @@
+5db3e910e70da38bb91d01d73acc33dd  vp90-2-00-quantizer-28-352x288-0001.i420
+b920ee7f7e61b7fdf9f44b1f738d0292  vp90-2-00-quantizer-28-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_29.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_29.vp9
new file mode 100644
index 0000000..f343340
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_29.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_29_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_29_vp9_md5
new file mode 100644
index 0000000..1187388
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_29_vp9_md5
@@ -0,0 +1,2 @@
+3cb3e310be5305077efa6216f6f10654  vp90-2-00-quantizer-29-352x288-0001.i420
+692d3e098af5978fe1a898ebc1a66a7a  vp90-2-00-quantizer-29-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_30.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_30.vp9
new file mode 100644
index 0000000..f6ce3c8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_30.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_30_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_30_vp9_md5
new file mode 100644
index 0000000..39a6f82
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_30_vp9_md5
@@ -0,0 +1,2 @@
+e3b3cea66ea38c5dfba1aa73bb4c611d  vp90-2-00-quantizer-30-352x288-0001.i420
+42bb3e54b19c3f4c4f7ee3a6ba012e19  vp90-2-00-quantizer-30-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_31.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_31.vp9
new file mode 100644
index 0000000..e83141f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_31.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_31_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_31_vp9_md5
new file mode 100644
index 0000000..9d84937
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_31_vp9_md5
@@ -0,0 +1,2 @@
+2523e9ecfd3781eafcd7da192dc105e9  vp90-2-00-quantizer-31-352x288-0001.i420
+6d5feea012b9a1f51fc643633e728764  vp90-2-00-quantizer-31-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_32.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_32.vp9
new file mode 100644
index 0000000..5987ec8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_32_vp9_md5
new file mode 100644
index 0000000..5e6cdde
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_32_vp9_md5
@@ -0,0 +1,2 @@
+0a0305eba36500ebf6cc6cc0f01f5a3b  vp90-2-00-quantizer-32-352x288-0001.i420
+2c76bcd6763467f9057a726fbcf50ab1  vp90-2-00-quantizer-32-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_33.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_33.vp9
new file mode 100644
index 0000000..c053597
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_33.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_33_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_33_vp9_md5
new file mode 100644
index 0000000..4604865
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_33_vp9_md5
@@ -0,0 +1,2 @@
+c68433e0e94047c220be9b629334f744  vp90-2-00-quantizer-33-352x288-0001.i420
+fcfa4dff7a39bc9c5e315849ecbb46ea  vp90-2-00-quantizer-33-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_34.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_34.vp9
new file mode 100644
index 0000000..3b13d0c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_34_vp9_md5
new file mode 100644
index 0000000..42ec3bd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_34_vp9_md5
@@ -0,0 +1,2 @@
+ad9dc2f912c137b014a33e2792c88a25  vp90-2-00-quantizer-34-352x288-0001.i420
+11221ee4ea5c776f43af68756682cd5a  vp90-2-00-quantizer-34-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_35.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_35.vp9
new file mode 100644
index 0000000..9e88eaf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_35.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_35_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_35_vp9_md5
new file mode 100644
index 0000000..7467703
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_35_vp9_md5
@@ -0,0 +1,2 @@
+75031f898cccf303a64ab46b1f815389  vp90-2-00-quantizer-35-352x288-0001.i420
+a4fc864e7fbc470dfcab6207e0eea152  vp90-2-00-quantizer-35-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_36.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_36.vp9
new file mode 100644
index 0000000..89095d8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_36.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_36_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_36_vp9_md5
new file mode 100644
index 0000000..f83c5fd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_36_vp9_md5
@@ -0,0 +1,2 @@
+c7824af009fde6cafdd8d39fae6bb6cf  vp90-2-00-quantizer-36-352x288-0001.i420
+516a82d5fc4dfa3daf713ed2ec36041b  vp90-2-00-quantizer-36-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_37.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_37.vp9
new file mode 100644
index 0000000..51ea020
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_37.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_37_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_37_vp9_md5
new file mode 100644
index 0000000..56ae9cf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_37_vp9_md5
@@ -0,0 +1,2 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-00-quantizer-37-352x288-0001.i420
+fb23e0bc64728a492a33d985032f21b8  vp90-2-00-quantizer-37-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_38.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_38.vp9
new file mode 100644
index 0000000..b502d01
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_38.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_38_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_38_vp9_md5
new file mode 100644
index 0000000..5c70650
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_38_vp9_md5
@@ -0,0 +1,2 @@
+8347bfb891317e89ef66781d6c28e24f  vp90-2-00-quantizer-38-352x288-0001.i420
+a5722f824d32deac042513a1a7dcdcd0  vp90-2-00-quantizer-38-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_39.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_39.vp9
new file mode 100644
index 0000000..559a435
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_39.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_39_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_39_vp9_md5
new file mode 100644
index 0000000..7c9fece
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_39_vp9_md5
@@ -0,0 +1,2 @@
+018968f97fac3bdff146cf22c1da5ef0  vp90-2-00-quantizer-39-352x288-0001.i420
+ca8b09b01e5132183395e238f1c7901e  vp90-2-00-quantizer-39-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_40.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_40.vp9
new file mode 100644
index 0000000..2cbb549
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_40.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_40_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_40_vp9_md5
new file mode 100644
index 0000000..6b3c92a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_40_vp9_md5
@@ -0,0 +1,2 @@
+792660f6589ad5340be4bd0554435866  vp90-2-00-quantizer-40-352x288-0001.i420
+68c84c8a15d679e0a73678b93215c62c  vp90-2-00-quantizer-40-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_41.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_41.vp9
new file mode 100644
index 0000000..910d486
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_41.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_41_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_41_vp9_md5
new file mode 100644
index 0000000..7df4a7f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_41_vp9_md5
@@ -0,0 +1,2 @@
+a456bdfc6c1c07b4cb3a3848843743b9  vp90-2-00-quantizer-41-352x288-0001.i420
+fe41a12b8cb6bc5667ba2179e076f3b0  vp90-2-00-quantizer-41-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_42.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_42.vp9
new file mode 100644
index 0000000..53c6b55
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_42.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_42_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_42_vp9_md5
new file mode 100644
index 0000000..4abe677
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_42_vp9_md5
@@ -0,0 +1,2 @@
+f016dd8431694d989700fb1ba71a5b2d  vp90-2-00-quantizer-42-352x288-0001.i420
+e89c3c5b935157b40f2fb0ab92415828  vp90-2-00-quantizer-42-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_43.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_43.vp9
new file mode 100644
index 0000000..0d3e706
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_43.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_43_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_43_vp9_md5
new file mode 100644
index 0000000..2db4096
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_43_vp9_md5
@@ -0,0 +1,2 @@
+7b8ab82625f3006bac89d4fb5197e71c  vp90-2-00-quantizer-43-352x288-0001.i420
+18bd3716045563dfba2c72b640b3274b  vp90-2-00-quantizer-43-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_44.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_44.vp9
new file mode 100644
index 0000000..4b1c580
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_44.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_44_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_44_vp9_md5
new file mode 100644
index 0000000..aa705be
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_44_vp9_md5
@@ -0,0 +1,2 @@
+66fde04d8320c750e56406feefd29979  vp90-2-00-quantizer-44-352x288-0001.i420
+f9d01d8fc1722ec345e624e14b404215  vp90-2-00-quantizer-44-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_45.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_45.vp9
new file mode 100644
index 0000000..12779d6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_45.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_45_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_45_vp9_md5
new file mode 100644
index 0000000..4472c2f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_45_vp9_md5
@@ -0,0 +1,2 @@
+cc97597b015896d73f3e60e7ae44c4da  vp90-2-00-quantizer-45-352x288-0001.i420
+fea98bc508f92135641ab99762444b14  vp90-2-00-quantizer-45-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_46.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_46.vp9
new file mode 100644
index 0000000..8f1aff1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_46.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_46_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_46_vp9_md5
new file mode 100644
index 0000000..bb306b1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_46_vp9_md5
@@ -0,0 +1,2 @@
+79ed95c741178bb3c0954f1f6f8e21a3  vp90-2-00-quantizer-46-352x288-0001.i420
+f02a06a5e2b5b7619c9a52c5bea0564d  vp90-2-00-quantizer-46-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_47.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_47.vp9
new file mode 100644
index 0000000..e8d81b4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_47.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_47_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_47_vp9_md5
new file mode 100644
index 0000000..5734952
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_47_vp9_md5
@@ -0,0 +1,2 @@
+9b98e948b8c2a822f21bd8419e6f4410  vp90-2-00-quantizer-47-352x288-0001.i420
+491382d68c16c2a3c6f1746598bc4a97  vp90-2-00-quantizer-47-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_48.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_48.vp9
new file mode 100644
index 0000000..9644566
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_48.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_48_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_48_vp9_md5
new file mode 100644
index 0000000..0b79523
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_48_vp9_md5
@@ -0,0 +1,2 @@
+f0f095b0edae7262f44d7ed7ef84ded4  vp90-2-00-quantizer-48-352x288-0001.i420
+0e833889ccac81d60251007d1baf6500  vp90-2-00-quantizer-48-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_49.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_49.vp9
new file mode 100644
index 0000000..c0efd85
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_49.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_49_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_49_vp9_md5
new file mode 100644
index 0000000..72f8300
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_49_vp9_md5
@@ -0,0 +1,2 @@
+6c1b7b7827617fb9b8417aca2cfdbcaa  vp90-2-00-quantizer-49-352x288-0001.i420
+4c1fc8a89297fdcf79f0faabd42b8684  vp90-2-00-quantizer-49-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_50.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_50.vp9
new file mode 100644
index 0000000..3797305
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_50.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_50_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_50_vp9_md5
new file mode 100644
index 0000000..f104046
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_50_vp9_md5
@@ -0,0 +1,2 @@
+ca6142db68463487bc28c888ab38476c  vp90-2-00-quantizer-50-352x288-0001.i420
+02a71153ec70f569524c3d814cb62f86  vp90-2-00-quantizer-50-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_51.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_51.vp9
new file mode 100644
index 0000000..ad66216
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_51.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_51_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_51_vp9_md5
new file mode 100644
index 0000000..7874a6f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_51_vp9_md5
@@ -0,0 +1,2 @@
+eece2627df1ddf0872256eb92352e179  vp90-2-00-quantizer-51-352x288-0001.i420
+0ee9f221246ad747250e4b5e8ba586e2  vp90-2-00-quantizer-51-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_52.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_52.vp9
new file mode 100644
index 0000000..b729121
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_52.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_52_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_52_vp9_md5
new file mode 100644
index 0000000..d5092d6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_52_vp9_md5
@@ -0,0 +1,2 @@
+7290039d974c4e50db9d69f9864bcdbe  vp90-2-00-quantizer-52-352x288-0001.i420
+264765de9d02503038a4da54133b9f85  vp90-2-00-quantizer-52-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_53.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_53.vp9
new file mode 100644
index 0000000..eace52e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_53.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_53_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_53_vp9_md5
new file mode 100644
index 0000000..3566f61
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_53_vp9_md5
@@ -0,0 +1,2 @@
+917af24da66f143a56a01eb2c2254285  vp90-2-00-quantizer-53-352x288-0001.i420
+45a05d3bc644420519619e4115662a70  vp90-2-00-quantizer-53-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_54.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_54.vp9
new file mode 100644
index 0000000..0100c2b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_54.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_54_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_54_vp9_md5
new file mode 100644
index 0000000..96fdd4b6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_54_vp9_md5
@@ -0,0 +1,2 @@
+6fea2820bb10a9dec9add4d2452b01f5  vp90-2-00-quantizer-54-352x288-0001.i420
+74675169a4bfc2ff5463c4db5d85a79f  vp90-2-00-quantizer-54-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_55.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_55.vp9
new file mode 100644
index 0000000..d84bbb2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_55.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_55_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_55_vp9_md5
new file mode 100644
index 0000000..ec38867
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_55_vp9_md5
@@ -0,0 +1,2 @@
+11e5d196f6537fb7d85988d90195e556  vp90-2-00-quantizer-55-352x288-0001.i420
+8536106795f7c93c5a43a11493527469  vp90-2-00-quantizer-55-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_56.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_56.vp9
new file mode 100644
index 0000000..befee07
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_56.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_56_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_56_vp9_md5
new file mode 100644
index 0000000..a93ced9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_56_vp9_md5
@@ -0,0 +1,2 @@
+40839b7a3a40ec10f96b8a75224f646d  vp90-2-00-quantizer-56-352x288-0001.i420
+11408dd73e8c45ddaab99f5c9650102b  vp90-2-00-quantizer-56-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_57.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_57.vp9
new file mode 100644
index 0000000..7df44d5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_57.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_57_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_57_vp9_md5
new file mode 100644
index 0000000..1979cd8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_57_vp9_md5
@@ -0,0 +1,2 @@
+d0e9fa03dd48da4592ebaadb4e3794e0  vp90-2-00-quantizer-57-352x288-0001.i420
+5172e29b1e04cd543833d6a68aab297c  vp90-2-00-quantizer-57-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_58.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_58.vp9
new file mode 100644
index 0000000..49a5fa9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_58.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_58_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_58_vp9_md5
new file mode 100644
index 0000000..cb06866
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_58_vp9_md5
@@ -0,0 +1,2 @@
+bef4a27d460e7697e038fe6f1c8bd597  vp90-2-00-quantizer-58-352x288-0001.i420
+124674686cafc5f2ff5bc7ea412b8f3b  vp90-2-00-quantizer-58-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_59.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_59.vp9
new file mode 100644
index 0000000..fd50ac3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_59.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_59_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_59_vp9_md5
new file mode 100644
index 0000000..240ea59
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_59_vp9_md5
@@ -0,0 +1,2 @@
+ae9d99e9d16ef20073300559566844ae  vp90-2-00-quantizer-59-352x288-0001.i420
+da9405e5a6bfe4ed18d927ba2004008e  vp90-2-00-quantizer-59-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_60.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_60.vp9
new file mode 100644
index 0000000..d2caca9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_60.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_60_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_60_vp9_md5
new file mode 100644
index 0000000..550fee9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_60_vp9_md5
@@ -0,0 +1,2 @@
+9e66bb8e1b5e206ea4afe4bf2d335ac5  vp90-2-00-quantizer-60-352x288-0001.i420
+092b74c905c12c1e87e90f5a79857736  vp90-2-00-quantizer-60-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_61.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_61.vp9
new file mode 100644
index 0000000..f20df40
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_61.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_61_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_61_vp9_md5
new file mode 100644
index 0000000..2e3edd3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_61_vp9_md5
@@ -0,0 +1,2 @@
+d062dc6be246c8042744018765ef50a8  vp90-2-00-quantizer-61-352x288-0001.i420
+45fd9cbacb6a91060a7e49a58a85869d  vp90-2-00-quantizer-61-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_62.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_62.vp9
new file mode 100644
index 0000000..2b8fd32
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_62.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_62_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_62_vp9_md5
new file mode 100644
index 0000000..1d266b3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_62_vp9_md5
@@ -0,0 +1,2 @@
+62f7e42fe653e81c5a65a25389e045b5  vp90-2-00-quantizer-62-352x288-0001.i420
+cb0cdd0b25689e0a43328550011d960d  vp90-2-00-quantizer-62-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_63.vp9 b/tests/tests/media/res/raw/vp90_2_00_quantizer_63.vp9
new file mode 100644
index 0000000..28c2564
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_63.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_00_quantizer_63_vp9_md5 b/tests/tests/media/res/raw/vp90_2_00_quantizer_63_vp9_md5
new file mode 100644
index 0000000..b5d122f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_00_quantizer_63_vp9_md5
@@ -0,0 +1,2 @@
+8467643dceff827e04acd82eeff1d1b0  vp90-2-00-quantizer-63-352x288-0001.i420
+c786f49d66f4dfd685dea9605821a19f  vp90-2-00-quantizer-63-352x288-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_1.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_1.vp9
new file mode 100644
index 0000000..dd0f0ee
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_1.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_1_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_1_vp9_md5
new file mode 100644
index 0000000..1db2ed2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_1_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-1-352x288-0001.i420
+aa20a75be3a316193496706c9f760d08  vp90-2-01-sharpness-1-352x288-0002.i420
+95567be97a64d3c9efe45f2524116a2e  vp90-2-01-sharpness-1-352x288-0003.i420
+219e86cd6b3cca312856eead21776b1c  vp90-2-01-sharpness-1-352x288-0004.i420
+4a67fd359ca362398e97c15eb018a2bb  vp90-2-01-sharpness-1-352x288-0005.i420
+9916d4e359274d690827f0eb22547423  vp90-2-01-sharpness-1-352x288-0006.i420
+a07785b52561150c48f1a8eff89d5d75  vp90-2-01-sharpness-1-352x288-0007.i420
+a3382a92982953dfa20018e5ac975b51  vp90-2-01-sharpness-1-352x288-0008.i420
+911836989ca7b148438aa3ec7fc7e303  vp90-2-01-sharpness-1-352x288-0009.i420
+5627b981e3fc9e4401d35d3a5ab25917  vp90-2-01-sharpness-1-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_2.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_2.vp9
new file mode 100644
index 0000000..d1d1a06
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_2.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_2_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_2_vp9_md5
new file mode 100644
index 0000000..cb4d78e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_2_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-2-352x288-0001.i420
+cd94572239817ae7c9b07de739c3272b  vp90-2-01-sharpness-2-352x288-0002.i420
+383cf752d457e122b5ff49d08960208e  vp90-2-01-sharpness-2-352x288-0003.i420
+1c0a6ec9cd3ce29b8b004e7526f1b07e  vp90-2-01-sharpness-2-352x288-0004.i420
+91c42a8a108d67947cabfc2a5a80df66  vp90-2-01-sharpness-2-352x288-0005.i420
+08c57fc1f3fec0305883315a66c714d1  vp90-2-01-sharpness-2-352x288-0006.i420
+70cb8d8dc83eac82f2d3c4b0376bb1aa  vp90-2-01-sharpness-2-352x288-0007.i420
+ffd62a9ef829ec81f0f74f740488a41f  vp90-2-01-sharpness-2-352x288-0008.i420
+bab0aa23b5854e2a70926046e4618710  vp90-2-01-sharpness-2-352x288-0009.i420
+fec456f38f2a43661e786a8d5f67ed15  vp90-2-01-sharpness-2-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_3.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_3.vp9
new file mode 100644
index 0000000..ac4d3c7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_3.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_3_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_3_vp9_md5
new file mode 100644
index 0000000..5f66ebd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_3_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-3-352x288-0001.i420
+0d487a146393a0b8b84b4be1b371b507  vp90-2-01-sharpness-3-352x288-0002.i420
+68372e191eba620a431cfff226026ac3  vp90-2-01-sharpness-3-352x288-0003.i420
+de7fd274460e36b983fe93acc208d72f  vp90-2-01-sharpness-3-352x288-0004.i420
+afbd36c61bab65b98ff9acf08e215721  vp90-2-01-sharpness-3-352x288-0005.i420
+e1e9fc2ab4e7a187a8d8d84aae48d6b9  vp90-2-01-sharpness-3-352x288-0006.i420
+11d95de6a9cc5e00511e99534779faac  vp90-2-01-sharpness-3-352x288-0007.i420
+cd2f5539fdfc2d8eefe6b6da28c13398  vp90-2-01-sharpness-3-352x288-0008.i420
+a8b3aeed41da7aeb8d5b962ee4a4af93  vp90-2-01-sharpness-3-352x288-0009.i420
+4283670bd1c1c506ef18d3dafca22035  vp90-2-01-sharpness-3-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_4.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_4.vp9
new file mode 100644
index 0000000..4f9ac94
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_4.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_4_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_4_vp9_md5
new file mode 100644
index 0000000..dc3f2c1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_4_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-4-352x288-0001.i420
+8bad76c55b5149169d64ce6512521de6  vp90-2-01-sharpness-4-352x288-0002.i420
+c1d986e1f9bf46382e598ba289b9bd7c  vp90-2-01-sharpness-4-352x288-0003.i420
+86c097ac6069c786023d3561dae68bac  vp90-2-01-sharpness-4-352x288-0004.i420
+8c238a2831b8c7c49736b6de6ff76ed8  vp90-2-01-sharpness-4-352x288-0005.i420
+cb5a038ed0a74a317ee72dae93a7ee3e  vp90-2-01-sharpness-4-352x288-0006.i420
+f8fe330a257e3e4e4c39c1c12820a654  vp90-2-01-sharpness-4-352x288-0007.i420
+a73e2fcdcbb9334c0c123f8276a2c881  vp90-2-01-sharpness-4-352x288-0008.i420
+24fccece8ee639e4d0e00e4060e1db0c  vp90-2-01-sharpness-4-352x288-0009.i420
+46d6e9aad69a39c718c5fd1e41e86e6e  vp90-2-01-sharpness-4-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_5.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_5.vp9
new file mode 100644
index 0000000..7f5e528
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_5.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_5_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_5_vp9_md5
new file mode 100644
index 0000000..a545e7c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_5_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-5-352x288-0001.i420
+f1ce0a5d57a46c9ff1331804b7b03fdb  vp90-2-01-sharpness-5-352x288-0002.i420
+0364a085b06bee6b980189cf5378eda9  vp90-2-01-sharpness-5-352x288-0003.i420
+4b5358698d734b0ae210909a913d4c1e  vp90-2-01-sharpness-5-352x288-0004.i420
+dc22565aaceee77b15fd8ab3c84bd5e0  vp90-2-01-sharpness-5-352x288-0005.i420
+5f6340b656536292b46ba9a647aeb6e4  vp90-2-01-sharpness-5-352x288-0006.i420
+b7d4bce9a04b2a6caa45801be15e331e  vp90-2-01-sharpness-5-352x288-0007.i420
+534c851cfe59ffc047815ece98d8cede  vp90-2-01-sharpness-5-352x288-0008.i420
+786b0e1564d5c71aabfc2dd528cff4e7  vp90-2-01-sharpness-5-352x288-0009.i420
+cac0366209cf471bb7cc3e64966cbbd4  vp90-2-01-sharpness-5-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_6.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_6.vp9
new file mode 100644
index 0000000..5f8d031
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_6.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_6_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_6_vp9_md5
new file mode 100644
index 0000000..0c36072
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_6_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-6-352x288-0001.i420
+45d9ca07ed04210b1ebc743169bc8ec4  vp90-2-01-sharpness-6-352x288-0002.i420
+5b646cc309a711f1d8814f925002d8c4  vp90-2-01-sharpness-6-352x288-0003.i420
+34db8db727fa1ded0a55cc7cf85be249  vp90-2-01-sharpness-6-352x288-0004.i420
+54173d08afe6369b16a9c0c9cc6ce04d  vp90-2-01-sharpness-6-352x288-0005.i420
+76275b0a478cdb3c1fb527ebbce023c3  vp90-2-01-sharpness-6-352x288-0006.i420
+e7643cdf0c42f2af700d8730bfc1a453  vp90-2-01-sharpness-6-352x288-0007.i420
+6e53097e56f680cb658d63100e7736f7  vp90-2-01-sharpness-6-352x288-0008.i420
+1a407c3c8ea1d5245ae68c5ce7de70e1  vp90-2-01-sharpness-6-352x288-0009.i420
+6cbca24912cadf09b20be74f14e359c9  vp90-2-01-sharpness-6-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_7.vp9 b/tests/tests/media/res/raw/vp90_2_01_sharpness_7.vp9
new file mode 100644
index 0000000..325523f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_7.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_01_sharpness_7_vp9_md5 b/tests/tests/media/res/raw/vp90_2_01_sharpness_7_vp9_md5
new file mode 100644
index 0000000..6c94a52
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_01_sharpness_7_vp9_md5
@@ -0,0 +1,10 @@
+a2e5c820fd9733e18f9349fb658ca281  vp90-2-01-sharpness-7-352x288-0001.i420
+f719d0be18d16a448b4e7da3e2d9bf28  vp90-2-01-sharpness-7-352x288-0002.i420
+83ee8ebc0ca796782a2376a76f2ffc26  vp90-2-01-sharpness-7-352x288-0003.i420
+7cf5afdbc229e1af50a5377cfc23d831  vp90-2-01-sharpness-7-352x288-0004.i420
+44244e896e0362f6376ba5afa563ba8b  vp90-2-01-sharpness-7-352x288-0005.i420
+df5f518d44eb6cb91b2df5a30d27ef82  vp90-2-01-sharpness-7-352x288-0006.i420
+43cc3f151b8337aca7ee659c8abeb783  vp90-2-01-sharpness-7-352x288-0007.i420
+4e89573470d9b97464e10806fc81aa8b  vp90-2-01-sharpness-7-352x288-0008.i420
+62e0ba70f07ece8d85372f0a42e83a9a  vp90-2-01-sharpness-7-352x288-0009.i420
+45ac2928acb11326f6c4a21401f3609c  vp90-2-01-sharpness-7-352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x08.vp9
new file mode 100644
index 0000000..269acbb
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x08_vp9_md5
new file mode 100644
index 0000000..c74db82
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x08_vp9_md5
@@ -0,0 +1,10 @@
+52def242c36123e5a8f5f53d6a971399  vp90-2-02-size-08x08-8x8-0001.i420
+79c93360fbd47179400414bbfee0901c  vp90-2-02-size-08x08-8x8-0002.i420
+c3b1947c79537baa7838905276276a91  vp90-2-02-size-08x08-8x8-0003.i420
+20f35e501bdee0bc63e87b9240265c25  vp90-2-02-size-08x08-8x8-0004.i420
+5e8f1c464bafd54833c51860906b5368  vp90-2-02-size-08x08-8x8-0005.i420
+f57b592600dfc99e634a083278af769a  vp90-2-02-size-08x08-8x8-0006.i420
+7b02191f85590cbad3f148c7b92d6436  vp90-2-02-size-08x08-8x8-0007.i420
+b0a1c9870447a1744f64cd4087ef55ee  vp90-2-02-size-08x08-8x8-0008.i420
+c82712b1ba7a95efb67cbdde0ad708b6  vp90-2-02-size-08x08-8x8-0009.i420
+89f4539f8d7a7b45a91fd2f46335988e  vp90-2-02-size-08x08-8x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x10.vp9
new file mode 100644
index 0000000..714467a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x10_vp9_md5
new file mode 100644
index 0000000..c051eb9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x10_vp9_md5
@@ -0,0 +1,10 @@
+ea3e0f807304b0eb2d3e329b0124f75c  vp90-2-02-size-08x10-8x10-0001.i420
+8d13cf682d63e7eb13094f55d67fc458  vp90-2-02-size-08x10-8x10-0002.i420
+e729cc6c3684c94a8f6118c618efc3ea  vp90-2-02-size-08x10-8x10-0003.i420
+ac43a0ace8e4112e877c2491ecc14fb5  vp90-2-02-size-08x10-8x10-0004.i420
+53695f90b88d8e8cb838f0faec3238d3  vp90-2-02-size-08x10-8x10-0005.i420
+40afd1c4dfd4a2e3b31631c46d252bcc  vp90-2-02-size-08x10-8x10-0006.i420
+2b656f76f2e84d2f82d9bda2b5be94d3  vp90-2-02-size-08x10-8x10-0007.i420
+b22f004d678d047bc401be5e040cf883  vp90-2-02-size-08x10-8x10-0008.i420
+57c840319abfb9c31013fbde54de3fb0  vp90-2-02-size-08x10-8x10-0009.i420
+0f3dfc156216d7cfb6fd1d8c77dadab9  vp90-2-02-size-08x10-8x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x16.vp9
new file mode 100644
index 0000000..815483f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x16_vp9_md5
new file mode 100644
index 0000000..d95f639
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x16_vp9_md5
@@ -0,0 +1,10 @@
+0553e56a9d89aea496421885aab491f5  vp90-2-02-size-08x16-8x16-0001.i420
+b2a14cf676f7ebf3c50450050f76ad16  vp90-2-02-size-08x16-8x16-0002.i420
+a308d981e09b50571fb0c8ebdcefe505  vp90-2-02-size-08x16-8x16-0003.i420
+d592ec625a0ac0373e82610c3eed9864  vp90-2-02-size-08x16-8x16-0004.i420
+acd19642455e643023b4fb882c3891ba  vp90-2-02-size-08x16-8x16-0005.i420
+5af5390fd8c29b795e0ddf83f3f34284  vp90-2-02-size-08x16-8x16-0006.i420
+473505aa2a76231725cf2107d6c9dbef  vp90-2-02-size-08x16-8x16-0007.i420
+84860db6887e320f2d64f80cf0032e57  vp90-2-02-size-08x16-8x16-0008.i420
+408e9cf60e99ae99d204ff08f3196d1a  vp90-2-02-size-08x16-8x16-0009.i420
+d8af96b79258f9382e911ed38340bdf5  vp90-2-02-size-08x16-8x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x18.vp9
new file mode 100644
index 0000000..542ae03
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x18_vp9_md5
new file mode 100644
index 0000000..d22d06a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x18_vp9_md5
@@ -0,0 +1,10 @@
+4c41f93b1b280b37bc77d7047435eaa4  vp90-2-02-size-08x18-8x18-0001.i420
+c9c80fdba2ebc2b8c3490ae35e34f84f  vp90-2-02-size-08x18-8x18-0002.i420
+089d86acb3263fa5ef4f591a7f44556d  vp90-2-02-size-08x18-8x18-0003.i420
+938fca6d93b83484144f5054e4838a41  vp90-2-02-size-08x18-8x18-0004.i420
+e0592e2ac9f5e09525ce0d3904cadf47  vp90-2-02-size-08x18-8x18-0005.i420
+ea43ff5d1330986e60c08567262ea764  vp90-2-02-size-08x18-8x18-0006.i420
+08b40fe109ee90188f1cba9bbb1b376e  vp90-2-02-size-08x18-8x18-0007.i420
+b067068a2a7e36d5c5b5b405a1e73a18  vp90-2-02-size-08x18-8x18-0008.i420
+9cf2d350296288803434b7451bd2be85  vp90-2-02-size-08x18-8x18-0009.i420
+3c785e21dc228d6396738fbfcb470289  vp90-2-02-size-08x18-8x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x32.vp9
new file mode 100644
index 0000000..57dafca
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x32_vp9_md5
new file mode 100644
index 0000000..32a5a7b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x32_vp9_md5
@@ -0,0 +1,10 @@
+f92a7777fd69aa2f2914d9a41c4828ba  vp90-2-02-size-08x32-8x32-0001.i420
+62e1cc73487d2249a88a60e35a22d9c7  vp90-2-02-size-08x32-8x32-0002.i420
+aa2619b605cb65eda15fdd99d5775550  vp90-2-02-size-08x32-8x32-0003.i420
+e6f0a491c543b835d0cefe5ca62c3dbe  vp90-2-02-size-08x32-8x32-0004.i420
+361be1a06913c398f09494ca1b2d288f  vp90-2-02-size-08x32-8x32-0005.i420
+0497bf849a973357c0ccb8d43f5bd8b4  vp90-2-02-size-08x32-8x32-0006.i420
+5ac6ac523147c409dd00820622161dd7  vp90-2-02-size-08x32-8x32-0007.i420
+7d07245574a46c524360f09be29a5f19  vp90-2-02-size-08x32-8x32-0008.i420
+fcfa7fbcaf42f81e4e34a4ee5a029ca1  vp90-2-02-size-08x32-8x32-0009.i420
+336e3fe4f15d3d6c82d82b1855dcfeb4  vp90-2-02-size-08x32-8x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x34.vp9
new file mode 100644
index 0000000..68ff21f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x34_vp9_md5
new file mode 100644
index 0000000..626dce9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x34_vp9_md5
@@ -0,0 +1,10 @@
+f3f2cd8f157466ff23dace85d77367ce  vp90-2-02-size-08x34-8x34-0001.i420
+639d9b70a14062e95559c12d2b597f91  vp90-2-02-size-08x34-8x34-0002.i420
+b2ee07a6656af583f19593229fa11848  vp90-2-02-size-08x34-8x34-0003.i420
+74e3b5ab4c798a0afe745694e871bbd5  vp90-2-02-size-08x34-8x34-0004.i420
+35f1c30d0f8678f319a392a6c53b5989  vp90-2-02-size-08x34-8x34-0005.i420
+07e2b4c0b92a394bfb11124fe80476f0  vp90-2-02-size-08x34-8x34-0006.i420
+7864bd20dfc5280e5f027d67ea22bf30  vp90-2-02-size-08x34-8x34-0007.i420
+10a2925a7b91dfa9b82de76069388fd4  vp90-2-02-size-08x34-8x34-0008.i420
+79cc7f7a149e8d6e04e065f75e63733c  vp90-2-02-size-08x34-8x34-0009.i420
+6453d10d97532d9bb03f7c06cba9fca0  vp90-2-02-size-08x34-8x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x64.vp9
new file mode 100644
index 0000000..337dfb9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x64_vp9_md5
new file mode 100644
index 0000000..f66d0c7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x64_vp9_md5
@@ -0,0 +1,10 @@
+764bd02b781a38c621a109c12f3d9393  vp90-2-02-size-08x64-8x64-0001.i420
+79496bd2b9212026af816b3b7a0587d5  vp90-2-02-size-08x64-8x64-0002.i420
+2a3afd47ba3d075033fd94d5c3746c45  vp90-2-02-size-08x64-8x64-0003.i420
+fca00cad8d37a6646337baebadd0ca31  vp90-2-02-size-08x64-8x64-0004.i420
+aca376fb3f8a5ef670ecc2430037262a  vp90-2-02-size-08x64-8x64-0005.i420
+7e6c8d96d1e24855c3e380f1bf2ce02c  vp90-2-02-size-08x64-8x64-0006.i420
+09e051241972969d439f27f324d78490  vp90-2-02-size-08x64-8x64-0007.i420
+2566b2a425caaba41305bf04ff10ea01  vp90-2-02-size-08x64-8x64-0008.i420
+db3995bedee42ada1b4ee63c339daf1b  vp90-2-02-size-08x64-8x64-0009.i420
+b00b8f1bf4fd907f0487738f5b5442c6  vp90-2-02-size-08x64-8x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_08x66.vp9
new file mode 100644
index 0000000..46febdd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_08x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_08x66_vp9_md5
new file mode 100644
index 0000000..0c4649c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_08x66_vp9_md5
@@ -0,0 +1,10 @@
+df20e8df89449fe50bb610e95a449a95  vp90-2-02-size-08x66-8x66-0001.i420
+18f1a66d463274d1b0489f3a50e86857  vp90-2-02-size-08x66-8x66-0002.i420
+b0cc102875a94c9a92e53826617adbe9  vp90-2-02-size-08x66-8x66-0003.i420
+dfece7c17b4b149283ef51bdc1bd440e  vp90-2-02-size-08x66-8x66-0004.i420
+6e346884f67be259fcabe493109cb63c  vp90-2-02-size-08x66-8x66-0005.i420
+6d282127311eb2d958377490d7cb77f0  vp90-2-02-size-08x66-8x66-0006.i420
+637ac8b14ca5ddbaf7b8910406c3cd08  vp90-2-02-size-08x66-8x66-0007.i420
+e7980f3fcb36969da0d218c4389fa9e8  vp90-2-02-size-08x66-8x66-0008.i420
+730a1c95b9fb165f6e1a2f33a0d25de0  vp90-2-02-size-08x66-8x66-0009.i420
+7bd8424d0783b1c8ad617e17408371bb  vp90-2-02-size-08x66-8x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x08.vp9
new file mode 100644
index 0000000..a27acd8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x08_vp9_md5
new file mode 100644
index 0000000..2f8e4be
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x08_vp9_md5
@@ -0,0 +1,10 @@
+e1e66a88615da98523ef887f1463fc42  vp90-2-02-size-10x08-10x8-0001.i420
+549842fa98c8faf572882d38b0aae390  vp90-2-02-size-10x08-10x8-0002.i420
+17ee85785517705fdc78c6122a4b2548  vp90-2-02-size-10x08-10x8-0003.i420
+1143391d419dac30a6c11f366157c974  vp90-2-02-size-10x08-10x8-0004.i420
+b62d2a962c4c36809ef75a610106715c  vp90-2-02-size-10x08-10x8-0005.i420
+e6f143ca33fbc0e776bb149950cdedff  vp90-2-02-size-10x08-10x8-0006.i420
+01716a1077ec66df00474fd4510d2789  vp90-2-02-size-10x08-10x8-0007.i420
+8cb5b6a865fa2cbb15f0d7736fda88a6  vp90-2-02-size-10x08-10x8-0008.i420
+0fb9fd883e895a540fe1704dddbbab04  vp90-2-02-size-10x08-10x8-0009.i420
+150a3b99aa24ef102c92f87c8adb4386  vp90-2-02-size-10x08-10x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x10.vp9
new file mode 100644
index 0000000..de3d37c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x10_vp9_md5
new file mode 100644
index 0000000..13ae622
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x10_vp9_md5
@@ -0,0 +1,10 @@
+083d638f2e147295d817bb14fff5e4f4  vp90-2-02-size-10x10-10x10-0001.i420
+6dbdc445b6fd6bb99f2025cc2a40977e  vp90-2-02-size-10x10-10x10-0002.i420
+41714089383b181d64fbfa7de5904608  vp90-2-02-size-10x10-10x10-0003.i420
+11fdb8465e1599f7a9227706646d2cba  vp90-2-02-size-10x10-10x10-0004.i420
+907876b3342a10040db0851a936af4e3  vp90-2-02-size-10x10-10x10-0005.i420
+e7b18d47d06b25de205d873d3d941640  vp90-2-02-size-10x10-10x10-0006.i420
+523ce7413c8da7f6a657a9b661f36c44  vp90-2-02-size-10x10-10x10-0007.i420
+23caff863af875c66c903662a3e1e6a1  vp90-2-02-size-10x10-10x10-0008.i420
+ed4cc5557203e5b7a119112ee9ceb00b  vp90-2-02-size-10x10-10x10-0009.i420
+4bb78a996be3188888d1c60e11a08e1b  vp90-2-02-size-10x10-10x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x16.vp9
new file mode 100644
index 0000000..843a547
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x16_vp9_md5
new file mode 100644
index 0000000..b614000
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x16_vp9_md5
@@ -0,0 +1,10 @@
+fab07d6209d2413e0a434e1aaaa12154  vp90-2-02-size-10x16-10x16-0001.i420
+f9ffffdb96f98527ba2e553d1265edbb  vp90-2-02-size-10x16-10x16-0002.i420
+56a992264cf7da2b23dd97435e9d0365  vp90-2-02-size-10x16-10x16-0003.i420
+b1db980423d8004bd45a789b02b92a65  vp90-2-02-size-10x16-10x16-0004.i420
+b29496aedc7026566367b634f55ebb28  vp90-2-02-size-10x16-10x16-0005.i420
+2bc9def672da4a2fc17cbd669e2b8081  vp90-2-02-size-10x16-10x16-0006.i420
+8c54721514cdf577a52a8668b9135f13  vp90-2-02-size-10x16-10x16-0007.i420
+2efab81d5e039d82b3bc7b0303b022c4  vp90-2-02-size-10x16-10x16-0008.i420
+bd0f42b91b5d126fd0baec765b1096ad  vp90-2-02-size-10x16-10x16-0009.i420
+c6bfea2735a629167bc6a7a7c76eb7f3  vp90-2-02-size-10x16-10x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x18.vp9
new file mode 100644
index 0000000..bd9c902
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x18_vp9_md5
new file mode 100644
index 0000000..0639abf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x18_vp9_md5
@@ -0,0 +1,10 @@
+0e9182e214aae732d94d007e5fe44888  vp90-2-02-size-10x18-10x18-0001.i420
+2630e2674b5611d68218fddac08815e2  vp90-2-02-size-10x18-10x18-0002.i420
+d5cdd7d6a3de17939f60bb60ef6877da  vp90-2-02-size-10x18-10x18-0003.i420
+29d1961096061029e78963fa82581eca  vp90-2-02-size-10x18-10x18-0004.i420
+5c2629f8aa59757f6b4aafa9f6cbcba1  vp90-2-02-size-10x18-10x18-0005.i420
+1f1a8b61e4fbd6222ddf42e9d0a07032  vp90-2-02-size-10x18-10x18-0006.i420
+cfb9771190ac2d0129907102d6abb63f  vp90-2-02-size-10x18-10x18-0007.i420
+cd98dd856ba573a26a943cbe53221f26  vp90-2-02-size-10x18-10x18-0008.i420
+ca13c161f067c4a4ce22bd58a2aca55b  vp90-2-02-size-10x18-10x18-0009.i420
+de4bd1a474a76a35b796a5fc45b4f893  vp90-2-02-size-10x18-10x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x32.vp9
new file mode 100644
index 0000000..4fa4f8b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x32_vp9_md5
new file mode 100644
index 0000000..aca6be0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x32_vp9_md5
@@ -0,0 +1,10 @@
+622e6407a051ea08706394d03330ffbf  vp90-2-02-size-10x32-10x32-0001.i420
+1841a0daf7c3ef7be94e01fdb1d3968a  vp90-2-02-size-10x32-10x32-0002.i420
+37790e6cb2415f7add0ac5d3ab354755  vp90-2-02-size-10x32-10x32-0003.i420
+91485880e17c292096a7335566d3648f  vp90-2-02-size-10x32-10x32-0004.i420
+eb6f74983d5fd13d6bd90afbce8836e1  vp90-2-02-size-10x32-10x32-0005.i420
+0069ab5ff7f0d4d601f7d0f9b7a08338  vp90-2-02-size-10x32-10x32-0006.i420
+dbf04254765f7497070387e8c34895c6  vp90-2-02-size-10x32-10x32-0007.i420
+410a9b2d9855b2c29618070994adae96  vp90-2-02-size-10x32-10x32-0008.i420
+7e7f34effd90209f29f1b9ae01488b3b  vp90-2-02-size-10x32-10x32-0009.i420
+471530f74082c01c9b0f1fcf3d240d77  vp90-2-02-size-10x32-10x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x34.vp9
new file mode 100644
index 0000000..e039c58
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x34_vp9_md5
new file mode 100644
index 0000000..1bd82bf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x34_vp9_md5
@@ -0,0 +1,10 @@
+bfeeaf51f972fd0dfe9ee757083cbb54  vp90-2-02-size-10x34-10x34-0001.i420
+10cd4ed6d762004846412d9cd0caa407  vp90-2-02-size-10x34-10x34-0002.i420
+04cca4008d656ed180de88dd2ddb4f21  vp90-2-02-size-10x34-10x34-0003.i420
+ec777e377836895748c06849fa35ed2d  vp90-2-02-size-10x34-10x34-0004.i420
+b55633d0f9239dff3e45a4abce4a35a7  vp90-2-02-size-10x34-10x34-0005.i420
+063c3ab4b4c599942c3a8a5b7bfe5029  vp90-2-02-size-10x34-10x34-0006.i420
+07b920169d32b5fc51d5b9ae16fef5bf  vp90-2-02-size-10x34-10x34-0007.i420
+8d49e727db9d3072b5ab7bab2133d9be  vp90-2-02-size-10x34-10x34-0008.i420
+17441437203447e946a57d2f96966332  vp90-2-02-size-10x34-10x34-0009.i420
+5d3f14af0e5cd81d0c7d2059f13efa5a  vp90-2-02-size-10x34-10x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x64.vp9
new file mode 100644
index 0000000..33817f0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x64_vp9_md5
new file mode 100644
index 0000000..26da4b6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x64_vp9_md5
@@ -0,0 +1,10 @@
+835254d0eecb17bed1f2b0f3a1638165  vp90-2-02-size-10x64-10x64-0001.i420
+c0c95ce9890eab339a0e0f8b26cb095c  vp90-2-02-size-10x64-10x64-0002.i420
+f0337d645ade07cb716952b0d19352e8  vp90-2-02-size-10x64-10x64-0003.i420
+7e3deb21cb3f0ead90c8af94464cde14  vp90-2-02-size-10x64-10x64-0004.i420
+c6b1ca6cfce358c411c0637c581157c8  vp90-2-02-size-10x64-10x64-0005.i420
+10fce3f11f1ce90286ff4d74fe44fcfd  vp90-2-02-size-10x64-10x64-0006.i420
+ee0565a1f121bc905a35550619127a50  vp90-2-02-size-10x64-10x64-0007.i420
+0624b601d379616eb792c94be60b6c91  vp90-2-02-size-10x64-10x64-0008.i420
+a1bb79cdf347548f1103f580f2b6930f  vp90-2-02-size-10x64-10x64-0009.i420
+40e96e16c7e065aa7932e5aa57f32398  vp90-2-02-size-10x64-10x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_10x66.vp9
new file mode 100644
index 0000000..c0ffdc8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_10x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_10x66_vp9_md5
new file mode 100644
index 0000000..40a8a9a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_10x66_vp9_md5
@@ -0,0 +1,10 @@
+1bd8b2d3bf679c4b925780bf82e12fae  vp90-2-02-size-10x66-10x66-0001.i420
+a0254b4cd4928fe1080cd6f8828288a9  vp90-2-02-size-10x66-10x66-0002.i420
+e416e99644cca481dc2806708d716ecb  vp90-2-02-size-10x66-10x66-0003.i420
+b1ed3203ffc77ed814f1cda7bfe721d2  vp90-2-02-size-10x66-10x66-0004.i420
+0ff7b9d84765f7b0b0650775ba72b334  vp90-2-02-size-10x66-10x66-0005.i420
+8b6cd91e035bad19b46b132bd411231d  vp90-2-02-size-10x66-10x66-0006.i420
+c714759a9a64402043ad00e5677c954c  vp90-2-02-size-10x66-10x66-0007.i420
+8e4738010b724ce66bcd0a5d5afcfbc1  vp90-2-02-size-10x66-10x66-0008.i420
+998a7aab8ed94f4b69bed39fb487f8d5  vp90-2-02-size-10x66-10x66-0009.i420
+9964683a15a65c032631a4f608e6009b  vp90-2-02-size-10x66-10x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_130x132.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_130x132.vp9
new file mode 100644
index 0000000..e14d5cc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_130x132.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_130x132_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_130x132_vp9_md5
new file mode 100644
index 0000000..451d950
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_130x132_vp9_md5
@@ -0,0 +1,10 @@
+8faddcc51f9bff5759dc15c7e6f5ce3f  vp90_2_02_size_130x132.webm-130x132-0001.i420
+74fe93bd53a03c466da40d67431b6d41  vp90_2_02_size_130x132.webm-130x132-0002.i420
+3a40cd8fdab88af3d15b5d4af7d62245  vp90_2_02_size_130x132.webm-130x132-0003.i420
+5c232e8e11f4254f9bf437dcf91418b9  vp90_2_02_size_130x132.webm-130x132-0004.i420
+eb7f2d1700705697d05e322abe12d732  vp90_2_02_size_130x132.webm-130x132-0005.i420
+f3accfe25de02102fd996622f9b43499  vp90_2_02_size_130x132.webm-130x132-0006.i420
+270a3780fc7b84afbe8a340bc2e61871  vp90_2_02_size_130x132.webm-130x132-0007.i420
+c169f3a5d566a1a4afde6c309f1e4644  vp90_2_02_size_130x132.webm-130x132-0008.i420
+48b6fefacb63f286096fb0b65f8bc7c4  vp90_2_02_size_130x132.webm-130x132-0009.i420
+fcc24b1b542545bab9e45b9d79f6b41f  vp90_2_02_size_130x132.webm-130x132-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_132x130.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_132x130.vp9
new file mode 100644
index 0000000..5282d3d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_132x130.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_132x130_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_132x130_vp9_md5
new file mode 100644
index 0000000..415deb4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_132x130_vp9_md5
@@ -0,0 +1,10 @@
+d75a9541df281c3fb1cd24f8be0788b3  vp90_2_02_size_132x130.webm-132x130-0001.i420
+a060549076fbf8856925c7f4a0e007b3  vp90_2_02_size_132x130.webm-132x130-0002.i420
+73ecf525a1a395deed6a7256e2c501d0  vp90_2_02_size_132x130.webm-132x130-0003.i420
+ec636e97f829b3457b7adda98c1c3580  vp90_2_02_size_132x130.webm-132x130-0004.i420
+f56f3f415b6b5d12fb5824aa82365cb3  vp90_2_02_size_132x130.webm-132x130-0005.i420
+376735c39fea4c2f48b8d2d260f9b73e  vp90_2_02_size_132x130.webm-132x130-0006.i420
+c616f543aaa73342b561f08ec24d9792  vp90_2_02_size_132x130.webm-132x130-0007.i420
+b86a6ecf6e5df70b9505861bcc8ac95e  vp90_2_02_size_132x130.webm-132x130-0008.i420
+1d9bc98446d2068fe37abc60abce0d28  vp90_2_02_size_132x130.webm-132x130-0009.i420
+febd071a35d2407e29f72c46f14f4667  vp90_2_02_size_132x130.webm-132x130-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_132x132.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_132x132.vp9
new file mode 100644
index 0000000..7c36464
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_132x132.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_132x132_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_132x132_vp9_md5
new file mode 100644
index 0000000..cb04a76
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_132x132_vp9_md5
@@ -0,0 +1,10 @@
+5dc0ef6d1452bf220dfe752b9c0a6081  vp90_2_02_size_132x132.webm-132x132-0001.i420
+cdec24d8945577908cd05a3254edc1ea  vp90_2_02_size_132x132.webm-132x132-0002.i420
+ce4978e6ab380156c33943b225145af2  vp90_2_02_size_132x132.webm-132x132-0003.i420
+516c9256ab785f04f41fa7b44ac89e6d  vp90_2_02_size_132x132.webm-132x132-0004.i420
+16071c396c07639360260d6544bbc198  vp90_2_02_size_132x132.webm-132x132-0005.i420
+8876317adaf2ee98682b0dbfa50b9cbc  vp90_2_02_size_132x132.webm-132x132-0006.i420
+a30299b275dfd0a08191f6a9f6633138  vp90_2_02_size_132x132.webm-132x132-0007.i420
+49b3e47e41d00cc283d3906bde82abc7  vp90_2_02_size_132x132.webm-132x132-0008.i420
+a922b8d8d9883b5fd05358724a1a84c2  vp90_2_02_size_132x132.webm-132x132-0009.i420
+1bc5c3b99f979087cd6065a9894b0d6d  vp90_2_02_size_132x132.webm-132x132-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x08.vp9
new file mode 100644
index 0000000..4de0d73
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x08_vp9_md5
new file mode 100644
index 0000000..3e3e92a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x08_vp9_md5
@@ -0,0 +1,10 @@
+68dccd167f9aa18df0840ebb8715eb68  vp90-2-02-size-16x08-16x8-0001.i420
+65c90bb99fdbee7abf21031d34cb18dc  vp90-2-02-size-16x08-16x8-0002.i420
+9ef1feb2dcbd4d73f3ee84e9e1cd2668  vp90-2-02-size-16x08-16x8-0003.i420
+b6281f7c88e9aa132d3902046f8cde5a  vp90-2-02-size-16x08-16x8-0004.i420
+4b439b716a294bddf9f56a229705907b  vp90-2-02-size-16x08-16x8-0005.i420
+d42c0a6f0d24522c90bc2233bc1df2c7  vp90-2-02-size-16x08-16x8-0006.i420
+74b763a5a12c4c4a581efb1818a92970  vp90-2-02-size-16x08-16x8-0007.i420
+0c3a0916ddfda5abdd3ac382f036e71f  vp90-2-02-size-16x08-16x8-0008.i420
+26ff590e8ae726f70e8b36f5eaee7a19  vp90-2-02-size-16x08-16x8-0009.i420
+30fa5810995d7132387ea585c4a1cc3a  vp90-2-02-size-16x08-16x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x10.vp9
new file mode 100644
index 0000000..541937a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x10_vp9_md5
new file mode 100644
index 0000000..9e00483
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x10_vp9_md5
@@ -0,0 +1,10 @@
+fb3cad61d7d9eb511758dbf87dd8abe1  vp90-2-02-size-16x10-16x10-0001.i420
+4fbc1aa5559c8db2930803893bd6ba75  vp90-2-02-size-16x10-16x10-0002.i420
+2d8e2ee04dcc6097ca9e3f27070cdcc8  vp90-2-02-size-16x10-16x10-0003.i420
+05d419f1322855ba3620665b68ce9910  vp90-2-02-size-16x10-16x10-0004.i420
+b004f8d88cb2c94f4e9a13cfa5bd480a  vp90-2-02-size-16x10-16x10-0005.i420
+9d9dec90e2213c0411939131aa9adf7f  vp90-2-02-size-16x10-16x10-0006.i420
+a00874356ff1b1e9da1a400424661f8d  vp90-2-02-size-16x10-16x10-0007.i420
+fda587eb6323cd98c773f05905ac1794  vp90-2-02-size-16x10-16x10-0008.i420
+781c63d221a04d8130806c799d16753a  vp90-2-02-size-16x10-16x10-0009.i420
+f346e311829f3789dc5a94da48ada5f4  vp90-2-02-size-16x10-16x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x16.vp9
new file mode 100644
index 0000000..4b7f230
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x16_vp9_md5
new file mode 100644
index 0000000..11de2b8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x16_vp9_md5
@@ -0,0 +1,10 @@
+b5c9daafa548e54a8e33e9881fda33f4  vp90-2-02-size-16x16-16x16-0001.i420
+1193acd7ea4b7aac968e35ef83c64378  vp90-2-02-size-16x16-16x16-0002.i420
+cd0e42c0b5a8b3be6f0e1d224062bf99  vp90-2-02-size-16x16-16x16-0003.i420
+ed79c71d17f68f86cbfa75ea2bfe97f3  vp90-2-02-size-16x16-16x16-0004.i420
+1502a859c7e07b31faad5b80e3e27cf7  vp90-2-02-size-16x16-16x16-0005.i420
+df3f093da914ea947db93c3baa188ecb  vp90-2-02-size-16x16-16x16-0006.i420
+480f86eb183b99277c1b38fdaafe2970  vp90-2-02-size-16x16-16x16-0007.i420
+023e0114282e04963f0f52e00e65ac61  vp90-2-02-size-16x16-16x16-0008.i420
+e67f29cf0acc7f9b553458e1e5c59ebf  vp90-2-02-size-16x16-16x16-0009.i420
+a779a14ba718f0c1df8a7edc9467d12e  vp90-2-02-size-16x16-16x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x18.vp9
new file mode 100644
index 0000000..de0bddc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x18_vp9_md5
new file mode 100644
index 0000000..7dcc81a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x18_vp9_md5
@@ -0,0 +1,10 @@
+5156b11cd9995d0c1638c9b0d2b0786c  vp90-2-02-size-16x18-16x18-0001.i420
+ef78557f93fb3ea770c7d49ab60edf21  vp90-2-02-size-16x18-16x18-0002.i420
+f31fb9bb14566e4538a45ac7bf398b2a  vp90-2-02-size-16x18-16x18-0003.i420
+97633875537f76ade183e975fa91b0fb  vp90-2-02-size-16x18-16x18-0004.i420
+602cf54f9af852175173c21abd63796f  vp90-2-02-size-16x18-16x18-0005.i420
+0b3741a6842cb65d6d21eda891882033  vp90-2-02-size-16x18-16x18-0006.i420
+44240a27a6b6d36c9661d499fb965f87  vp90-2-02-size-16x18-16x18-0007.i420
+9050f263f9a4767f9323ec8aa42cf7e6  vp90-2-02-size-16x18-16x18-0008.i420
+57fa3a8494375f588a95376bc0c3cb28  vp90-2-02-size-16x18-16x18-0009.i420
+084595f2a65aa10e7d3845044a0e7213  vp90-2-02-size-16x18-16x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x32.vp9
new file mode 100644
index 0000000..35371d5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x32_vp9_md5
new file mode 100644
index 0000000..f7b1555
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x32_vp9_md5
@@ -0,0 +1,10 @@
+c73d611490a5ddec6c690589deaf5e86  vp90-2-02-size-16x32-16x32-0001.i420
+5d8eaeb222aa64abda59ce7b09b2f6d9  vp90-2-02-size-16x32-16x32-0002.i420
+34321856b8dd5bbb9b63db04d3532289  vp90-2-02-size-16x32-16x32-0003.i420
+947337d2fec8a09242f60e31e99f4065  vp90-2-02-size-16x32-16x32-0004.i420
+bb7d92f6fc055f0cf0e97bd2be56cc9e  vp90-2-02-size-16x32-16x32-0005.i420
+5d343c82bcdd0e9d08581043cddfd0ca  vp90-2-02-size-16x32-16x32-0006.i420
+612ded93207712e4916d584cc4a7b87c  vp90-2-02-size-16x32-16x32-0007.i420
+6ba5e0d19893e1b96f5ca86e0bfd7e18  vp90-2-02-size-16x32-16x32-0008.i420
+336572e1dcb110b1eb87bea81e0752f4  vp90-2-02-size-16x32-16x32-0009.i420
+705f73d0a39afce59ea571e68bfe25df  vp90-2-02-size-16x32-16x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x34.vp9
new file mode 100644
index 0000000..a9c1024
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x34_vp9_md5
new file mode 100644
index 0000000..169e06c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x34_vp9_md5
@@ -0,0 +1,10 @@
+b8bf711d9a1ce49180ed56407c8a4b0a  vp90-2-02-size-16x34-16x34-0001.i420
+0457929b06ce46aec63d66bd38586e3f  vp90-2-02-size-16x34-16x34-0002.i420
+3b5f417ee5a936797a6f0d138b8ed73b  vp90-2-02-size-16x34-16x34-0003.i420
+5d1a42aeecfd5c8513cb2df94c206c8b  vp90-2-02-size-16x34-16x34-0004.i420
+a0ab2dddbc810a1667d779f6ed69d010  vp90-2-02-size-16x34-16x34-0005.i420
+b150cd7c4ec83e6f9d948e99d7465350  vp90-2-02-size-16x34-16x34-0006.i420
+ea39622ad21312bd8bcecdaf09aa18fb  vp90-2-02-size-16x34-16x34-0007.i420
+467a42e1226a01c8ba244f312f588bab  vp90-2-02-size-16x34-16x34-0008.i420
+f2311e15228ffc7fd377b89c203d0fbf  vp90-2-02-size-16x34-16x34-0009.i420
+5df58b3ac0a7856796a46f27be7dcf4c  vp90-2-02-size-16x34-16x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x64.vp9
new file mode 100644
index 0000000..4f9d19c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x64_vp9_md5
new file mode 100644
index 0000000..5b98188
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x64_vp9_md5
@@ -0,0 +1,10 @@
+925fdc485f3baa1ed145ae391519d7fd  vp90-2-02-size-16x64-16x64-0001.i420
+d37af656da2d7a727c8451773495d5ed  vp90-2-02-size-16x64-16x64-0002.i420
+8a0f207a99e46f3d3b2aaa3f1b061981  vp90-2-02-size-16x64-16x64-0003.i420
+a3914c7b739d3af2641fd6aae35428ef  vp90-2-02-size-16x64-16x64-0004.i420
+0ba3b49970d7b029f2dfa991fdfc6e61  vp90-2-02-size-16x64-16x64-0005.i420
+55838d1d787dc5a4fa4da2994f04587f  vp90-2-02-size-16x64-16x64-0006.i420
+c089f7ba2b2983df2a4dc2e07798af31  vp90-2-02-size-16x64-16x64-0007.i420
+c23dcb3b109543a61ccfa404a726caae  vp90-2-02-size-16x64-16x64-0008.i420
+01aaf09960f5ca599ca32768f017d0c9  vp90-2-02-size-16x64-16x64-0009.i420
+79fe955692ecba8bbb00b20a42ca8104  vp90-2-02-size-16x64-16x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_16x66.vp9
new file mode 100644
index 0000000..4499869
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_16x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_16x66_vp9_md5
new file mode 100644
index 0000000..34f48af
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_16x66_vp9_md5
@@ -0,0 +1,10 @@
+c7b0d91f362dff0a581434af6e902d43  vp90-2-02-size-16x66-16x66-0001.i420
+d8b016ef59c6bc193b29d1c714f342c1  vp90-2-02-size-16x66-16x66-0002.i420
+c520bd8d4b81aafc7687befff66c7396  vp90-2-02-size-16x66-16x66-0003.i420
+92e81bbd3af675c9cdb1cb00d03dabe1  vp90-2-02-size-16x66-16x66-0004.i420
+a271db3defe5daa6d9e0a73a580f4f88  vp90-2-02-size-16x66-16x66-0005.i420
+4077e857321e241bb98dfd89c0aca46f  vp90-2-02-size-16x66-16x66-0006.i420
+0466e1453a94baf876e9f64b60235300  vp90-2-02-size-16x66-16x66-0007.i420
+9d2cb9c7b180d44841e0e4d8a595d912  vp90-2-02-size-16x66-16x66-0008.i420
+500f443eeb0ecef47c34d1e91f0df6ce  vp90-2-02-size-16x66-16x66-0009.i420
+83354487982915c33b1c6243d80adaeb  vp90-2-02-size-16x66-16x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_178x180.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_178x180.vp9
new file mode 100644
index 0000000..c7f72dc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_178x180.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_178x180_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_178x180_vp9_md5
new file mode 100644
index 0000000..8af554c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_178x180_vp9_md5
@@ -0,0 +1,10 @@
+ca7515c880d0a8230432e77abf3e3d33  vp90_2_02_size_178x180.webm-178x180-0001.i420
+7612d57deeb9d947529f73dd1b64a08d  vp90_2_02_size_178x180.webm-178x180-0002.i420
+a230690af19b975ffaca630e84e648fe  vp90_2_02_size_178x180.webm-178x180-0003.i420
+c6f829cb3462fcc0f7259819797c3283  vp90_2_02_size_178x180.webm-178x180-0004.i420
+3d13df53df5abb8d7602ffb0a3c89bb6  vp90_2_02_size_178x180.webm-178x180-0005.i420
+08ed7474c5630c1d7de6e32906f8b62f  vp90_2_02_size_178x180.webm-178x180-0006.i420
+d09e4324a86be4e4141fcd72b855744b  vp90_2_02_size_178x180.webm-178x180-0007.i420
+2934746d377ee23fd3eaeea27d049210  vp90_2_02_size_178x180.webm-178x180-0008.i420
+9cbad3dfc8a5665f57f483fede1ac91c  vp90_2_02_size_178x180.webm-178x180-0009.i420
+9c2dc6879c5778f293db30eac2fe7103  vp90_2_02_size_178x180.webm-178x180-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_180x178.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_180x178.vp9
new file mode 100644
index 0000000..340be2b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_180x178.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_180x178_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_180x178_vp9_md5
new file mode 100644
index 0000000..dd72479
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_180x178_vp9_md5
@@ -0,0 +1,10 @@
+461aa52a5658cbb30320be36bf42867d  vp90_2_02_size_180x178.webm-180x178-0001.i420
+a6c5fb033c04b5bdbe47a07a2ea8a001  vp90_2_02_size_180x178.webm-180x178-0002.i420
+de1d2789826b143aaae0b7c337332a69  vp90_2_02_size_180x178.webm-180x178-0003.i420
+aaf60e6369a72ea8fe47b3767b6b4aef  vp90_2_02_size_180x178.webm-180x178-0004.i420
+40c6bfaf1f4bcd39d6c6cf588ea445cb  vp90_2_02_size_180x178.webm-180x178-0005.i420
+3bfe6508595fb0c000c196cb6387531b  vp90_2_02_size_180x178.webm-180x178-0006.i420
+b70dcaad6d9dd7fe378b323460c3a243  vp90_2_02_size_180x178.webm-180x178-0007.i420
+201fce98c70f2623196a44e40a4850ac  vp90_2_02_size_180x178.webm-180x178-0008.i420
+aba16ce70b06355a025d003d6974790b  vp90_2_02_size_180x178.webm-180x178-0009.i420
+39220f4dd594972d258788528d19460c  vp90_2_02_size_180x178.webm-180x178-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_180x180.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_180x180.vp9
new file mode 100644
index 0000000..c01cc6f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_180x180.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_180x180_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_180x180_vp9_md5
new file mode 100644
index 0000000..f257f21
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_180x180_vp9_md5
@@ -0,0 +1,10 @@
+325a336bcaf9987ab1ad3f6a7328d2be  vp90_2_02_size_180x180.webm-180x180-0001.i420
+e7d73157a4861d98318240b60d157f55  vp90_2_02_size_180x180.webm-180x180-0002.i420
+1db60eb53a9756c751325942a021b36e  vp90_2_02_size_180x180.webm-180x180-0003.i420
+c0adb82dc19f4cabcebd18f0d7712ee5  vp90_2_02_size_180x180.webm-180x180-0004.i420
+35b768881097c1e6b99814e4fbf905d1  vp90_2_02_size_180x180.webm-180x180-0005.i420
+c3af16f1334c6baa0a51086f57c7cfd5  vp90_2_02_size_180x180.webm-180x180-0006.i420
+d30718f4a93162e7752e5177096718ee  vp90_2_02_size_180x180.webm-180x180-0007.i420
+b73f17d3affa5a9f69273579c09f4566  vp90_2_02_size_180x180.webm-180x180-0008.i420
+f596f4234d2486985a2d94ce73bd72ad  vp90_2_02_size_180x180.webm-180x180-0009.i420
+aab77693ee7b744c81a0b913f5318ac2  vp90_2_02_size_180x180.webm-180x180-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x08.vp9
new file mode 100644
index 0000000..c1b063e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x08_vp9_md5
new file mode 100644
index 0000000..19f6cbe
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x08_vp9_md5
@@ -0,0 +1,10 @@
+3219af4ef540636b0f67a989e9966059  vp90-2-02-size-18x08-18x8-0001.i420
+1a3655c2cfd2ee332bc89da5b3faf778  vp90-2-02-size-18x08-18x8-0002.i420
+d638d5b361a6d81440e26993ed86c97d  vp90-2-02-size-18x08-18x8-0003.i420
+d9bc2e7cffd66db4ba9dcbce99448d4d  vp90-2-02-size-18x08-18x8-0004.i420
+399f962e0a0573915bc4da4a9f1effcf  vp90-2-02-size-18x08-18x8-0005.i420
+69d917e19b903e4f07f848e9e557bbe7  vp90-2-02-size-18x08-18x8-0006.i420
+d6311488a58acf6eb0cc45bc4fe3c2da  vp90-2-02-size-18x08-18x8-0007.i420
+0ce360a84d5755307f98d65c83f190e1  vp90-2-02-size-18x08-18x8-0008.i420
+2554828e6dbf94424ccac30fb153872e  vp90-2-02-size-18x08-18x8-0009.i420
+598a55f9735e85b8d45105dd6be7f97b  vp90-2-02-size-18x08-18x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x10.vp9
new file mode 100644
index 0000000..5b1d1f4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x10_vp9_md5
new file mode 100644
index 0000000..f79825a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x10_vp9_md5
@@ -0,0 +1,10 @@
+bf574489e9360b6475aa012c747e7924  vp90-2-02-size-18x10-18x10-0001.i420
+851100301c2937312a6fd32f5aab5a09  vp90-2-02-size-18x10-18x10-0002.i420
+0f7c1209e44ea7cd4df12d82f9224684  vp90-2-02-size-18x10-18x10-0003.i420
+28d121f9c40de5280435bfdeaec0c072  vp90-2-02-size-18x10-18x10-0004.i420
+bb00898d03ce4dff5f7bee719dd3f5b5  vp90-2-02-size-18x10-18x10-0005.i420
+a098cc66bc25b81f84b0e930b0915cdb  vp90-2-02-size-18x10-18x10-0006.i420
+81e25f19bfcbfce17bd7138eedae04ee  vp90-2-02-size-18x10-18x10-0007.i420
+69c36c5ce555a461f16a1733450f7258  vp90-2-02-size-18x10-18x10-0008.i420
+c95236d9e7c624bb664310bd9ef47fb4  vp90-2-02-size-18x10-18x10-0009.i420
+7ab0942e686939951037314e9402d2c1  vp90-2-02-size-18x10-18x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x16.vp9
new file mode 100644
index 0000000..f27acd1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x16_vp9_md5
new file mode 100644
index 0000000..aeafea2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x16_vp9_md5
@@ -0,0 +1,10 @@
+9535aaa2ea26fbdc16e7fe9cba3fc9b4  vp90-2-02-size-18x16-18x16-0001.i420
+7f6e7ca33c0b27ff052dc2ab6721e37d  vp90-2-02-size-18x16-18x16-0002.i420
+d37e3f169457a9c7f2a197353e39d3d6  vp90-2-02-size-18x16-18x16-0003.i420
+f26d7d81dd81d051680ea2485e812705  vp90-2-02-size-18x16-18x16-0004.i420
+704b01955ced6d101b9e9315d3327f28  vp90-2-02-size-18x16-18x16-0005.i420
+30d46d6a0f6be383dede451cacf465f4  vp90-2-02-size-18x16-18x16-0006.i420
+83c7ed04f0af61ec665041967cbce05d  vp90-2-02-size-18x16-18x16-0007.i420
+152daf37dd37607886c50dd4c7796357  vp90-2-02-size-18x16-18x16-0008.i420
+609d807351ba74b1c432e3d0516add91  vp90-2-02-size-18x16-18x16-0009.i420
+67953f0c735984232cb6782217cdcdf6  vp90-2-02-size-18x16-18x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x18.vp9
new file mode 100644
index 0000000..35ec6a7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x18_vp9_md5
new file mode 100644
index 0000000..9600c40e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x18_vp9_md5
@@ -0,0 +1,10 @@
+83790b0e7004d8d89b7134ee1a88d885  vp90-2-02-size-18x18-18x18-0001.i420
+0baf0bf556ae56d2f4b04567e6ac7ed9  vp90-2-02-size-18x18-18x18-0002.i420
+c648854a4d49f7e407a2450cf4ba292a  vp90-2-02-size-18x18-18x18-0003.i420
+510c3aca23339841ffc72ed5c75d184e  vp90-2-02-size-18x18-18x18-0004.i420
+1c1f3116ec4d4ee1ad790652e49233ad  vp90-2-02-size-18x18-18x18-0005.i420
+f94891f4e16fd32d638a2c696f5922e6  vp90-2-02-size-18x18-18x18-0006.i420
+e164814c22e38cbe45312dfd48d987fc  vp90-2-02-size-18x18-18x18-0007.i420
+f582515fcc6c4308ad931d2f6cf371a0  vp90-2-02-size-18x18-18x18-0008.i420
+0a446974bd227ee34a1621a2b7852abb  vp90-2-02-size-18x18-18x18-0009.i420
+beca28bdae8d1fe20036b3646f3109cd  vp90-2-02-size-18x18-18x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x32.vp9
new file mode 100644
index 0000000..f288c06
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x32_vp9_md5
new file mode 100644
index 0000000..697fa7d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x32_vp9_md5
@@ -0,0 +1,10 @@
+62eabc8819ded6ddba2c3a5029497cf0  vp90-2-02-size-18x32-18x32-0001.i420
+b760182fddf8bc05f149e80bbcb2c281  vp90-2-02-size-18x32-18x32-0002.i420
+0c44be0472ebd2653ce9fb174c6180ab  vp90-2-02-size-18x32-18x32-0003.i420
+bbb033c3bfeeb6f59cb43013597b9d92  vp90-2-02-size-18x32-18x32-0004.i420
+a769975cdbc6529525f7cac8a0d9299a  vp90-2-02-size-18x32-18x32-0005.i420
+15b02059bbced62f19c0626efea1ecb9  vp90-2-02-size-18x32-18x32-0006.i420
+47f4b50322ed31649bdcfffb05c70fa2  vp90-2-02-size-18x32-18x32-0007.i420
+8649cdd0a958047839f5b6e7bbf6f288  vp90-2-02-size-18x32-18x32-0008.i420
+2c766e3fd3882a9a5aff52ffe9d1d341  vp90-2-02-size-18x32-18x32-0009.i420
+184a62b7332a1c24acbf03f670fb7ac1  vp90-2-02-size-18x32-18x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x34.vp9
new file mode 100644
index 0000000..6b8c072
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x34_vp9_md5
new file mode 100644
index 0000000..2b9926c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x34_vp9_md5
@@ -0,0 +1,10 @@
+612cc424eaae924cb25c7732c422f752  vp90-2-02-size-18x34-18x34-0001.i420
+010e8c2a814862529fcf8d7771ba2d7f  vp90-2-02-size-18x34-18x34-0002.i420
+7d791b7a5916738998f77586339d5840  vp90-2-02-size-18x34-18x34-0003.i420
+aeada5f59f3dda9ab3e898f305428cb2  vp90-2-02-size-18x34-18x34-0004.i420
+06af894d38a1f0d3665c0081f5397ddf  vp90-2-02-size-18x34-18x34-0005.i420
+24bf31323c568e652550e9d35de9c96c  vp90-2-02-size-18x34-18x34-0006.i420
+a9681ec47d3e6a19321b9ea47221dc3f  vp90-2-02-size-18x34-18x34-0007.i420
+73ae7268df79c4012952bd3e8011e894  vp90-2-02-size-18x34-18x34-0008.i420
+67aa4145398ca17036959251cb4ce17b  vp90-2-02-size-18x34-18x34-0009.i420
+de247b80114c722da849f5aa23adbb38  vp90-2-02-size-18x34-18x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x64.vp9
new file mode 100644
index 0000000..da13d78
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x64_vp9_md5
new file mode 100644
index 0000000..0fbd0c0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x64_vp9_md5
@@ -0,0 +1,10 @@
+72c74de547d9ed1b17bc962dbd5e0bb1  vp90-2-02-size-18x64-18x64-0001.i420
+462849f9e2204738e9f08b40e682a6ae  vp90-2-02-size-18x64-18x64-0002.i420
+f0ee17692fd816747b11d5737b511cda  vp90-2-02-size-18x64-18x64-0003.i420
+0234d23406660ede76dd22b35a708390  vp90-2-02-size-18x64-18x64-0004.i420
+6544fdb9dc225d155820d3c7dfc909eb  vp90-2-02-size-18x64-18x64-0005.i420
+1c073544794389596177512fb4dcffce  vp90-2-02-size-18x64-18x64-0006.i420
+864709daac7b091d33afa2210c145084  vp90-2-02-size-18x64-18x64-0007.i420
+b049c4ac941743613ede9a41b16acde5  vp90-2-02-size-18x64-18x64-0008.i420
+ad0c4adb0efec03729a79f42eec66267  vp90-2-02-size-18x64-18x64-0009.i420
+146057d941f5a47eb8b2c9eefeaf3100  vp90-2-02-size-18x64-18x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_18x66.vp9
new file mode 100644
index 0000000..b1ffba7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_18x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_18x66_vp9_md5
new file mode 100644
index 0000000..46a7a3d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_18x66_vp9_md5
@@ -0,0 +1,10 @@
+c3fc4a1593b9cc2f3752106af8539386  vp90-2-02-size-18x66-18x66-0001.i420
+7f2ffe6bc1750f6749bb5ad12cbaf34b  vp90-2-02-size-18x66-18x66-0002.i420
+2539b10a981d59ef54efd77cd7276aaa  vp90-2-02-size-18x66-18x66-0003.i420
+0bff22b4dfb7485fbedd6ff5b99673d1  vp90-2-02-size-18x66-18x66-0004.i420
+6a2b38f4abee785260a61bc60f16e7fa  vp90-2-02-size-18x66-18x66-0005.i420
+2fbb69b5519b51548bf1ee425ff79c55  vp90-2-02-size-18x66-18x66-0006.i420
+dbd267028be2256111b2411b91fcc117  vp90-2-02-size-18x66-18x66-0007.i420
+12b2f1003633c9e19cae3d0fda06102d  vp90-2-02-size-18x66-18x66-0008.i420
+d419a756c492867523af5185fd57d989  vp90-2-02-size-18x66-18x66-0009.i420
+8a7d36760bf5db32baef349b97316b47  vp90-2-02-size-18x66-18x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x08.vp9
new file mode 100644
index 0000000..97e741c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x08_vp9_md5
new file mode 100644
index 0000000..b744f57
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x08_vp9_md5
@@ -0,0 +1,10 @@
+c7b30cde5664387b0f7a80d9b01e4fe2  vp90-2-02-size-32x08-32x8-0001.i420
+2228a2a4e54ab5145525e5803c314dcd  vp90-2-02-size-32x08-32x8-0002.i420
+8c048469eba24f3163c36b7461b3b42a  vp90-2-02-size-32x08-32x8-0003.i420
+f6b8e8e701dea09dcf1158e9a52921c6  vp90-2-02-size-32x08-32x8-0004.i420
+b3a5fde0daf2eef8fc08521f88f79692  vp90-2-02-size-32x08-32x8-0005.i420
+653ae11cc1380ae7f39b2e007f896d81  vp90-2-02-size-32x08-32x8-0006.i420
+6e66fe002a7dff95e13cc9d3d13d9686  vp90-2-02-size-32x08-32x8-0007.i420
+13308c917a1e22c2f702afc32b8a23c2  vp90-2-02-size-32x08-32x8-0008.i420
+4fee1e63f9452dc3f81c1d634bd7f41d  vp90-2-02-size-32x08-32x8-0009.i420
+666b43ead5c7c99ae5b7637da5aa4d62  vp90-2-02-size-32x08-32x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x10.vp9
new file mode 100644
index 0000000..acfa19b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x10_vp9_md5
new file mode 100644
index 0000000..cb40846
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x10_vp9_md5
@@ -0,0 +1,10 @@
+7c5b5df373ebfd31d210ff910e02213b  vp90-2-02-size-32x10-32x10-0001.i420
+c5b0a5e3eceb792b15818324a43aa2a8  vp90-2-02-size-32x10-32x10-0002.i420
+1d9c0eafd4638dfe4fe308174fde2faf  vp90-2-02-size-32x10-32x10-0003.i420
+47301d12055944b35008028761cf5e7b  vp90-2-02-size-32x10-32x10-0004.i420
+9586ac1087423dcd3b0ff96d43ae475e  vp90-2-02-size-32x10-32x10-0005.i420
+26bfe1afea96c7ef2084fffd1fa99a33  vp90-2-02-size-32x10-32x10-0006.i420
+0995c8a1935266159a7ef3f95d7f4697  vp90-2-02-size-32x10-32x10-0007.i420
+8cfcc0ea67507ab7f3551d8ac50f93a5  vp90-2-02-size-32x10-32x10-0008.i420
+658cf3cb887b055d9de7d50db4eb78a9  vp90-2-02-size-32x10-32x10-0009.i420
+856bd5189688f7ccfe9995752bc0f1f6  vp90-2-02-size-32x10-32x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x16.vp9
new file mode 100644
index 0000000..dec3c01
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x16_vp9_md5
new file mode 100644
index 0000000..7609114
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x16_vp9_md5
@@ -0,0 +1,10 @@
+7c2818db2632e5c5beee17e7105d9209  vp90-2-02-size-32x16-32x16-0001.i420
+cead72bd22995e98b54a91c7b4a20975  vp90-2-02-size-32x16-32x16-0002.i420
+eb6baee5d65d778052c88ba5db2f9174  vp90-2-02-size-32x16-32x16-0003.i420
+1f5f38e89e985e9e4172446de05e91fd  vp90-2-02-size-32x16-32x16-0004.i420
+57b57ffcb03627942fc5868324a10feb  vp90-2-02-size-32x16-32x16-0005.i420
+4b4066a452d8e9cd687cd611f5d9cb88  vp90-2-02-size-32x16-32x16-0006.i420
+113e5069b2a4d2c2e802b72649eb435d  vp90-2-02-size-32x16-32x16-0007.i420
+e176bb233f76f9fd4c55d62d53487b60  vp90-2-02-size-32x16-32x16-0008.i420
+f2ff3def712a846ea7b678bd9078e32b  vp90-2-02-size-32x16-32x16-0009.i420
+21007ed1c727c5ccc5955188a2cec276  vp90-2-02-size-32x16-32x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x18.vp9
new file mode 100644
index 0000000..2062e61
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x18_vp9_md5
new file mode 100644
index 0000000..4bd047f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x18_vp9_md5
@@ -0,0 +1,10 @@
+9da5409d344e7b8380688569e54803a5  vp90-2-02-size-32x18-32x18-0001.i420
+9b51e14e2e624ee2b430e9eaf1a48798  vp90-2-02-size-32x18-32x18-0002.i420
+b8811779f363b9a595e3a92737771ea9  vp90-2-02-size-32x18-32x18-0003.i420
+e5a0c335e5e713a3e77fff0b65127fb9  vp90-2-02-size-32x18-32x18-0004.i420
+1bffa3283b463a356794c8f7a73f8c54  vp90-2-02-size-32x18-32x18-0005.i420
+97c13270621a583eb9e13c05f9d792f0  vp90-2-02-size-32x18-32x18-0006.i420
+a6f81a4dde1ffc352ebe9d8ab8782f35  vp90-2-02-size-32x18-32x18-0007.i420
+91a955a86ce9378ff3442794ce0934c6  vp90-2-02-size-32x18-32x18-0008.i420
+2e4f8938e9c88b328a258a0b99366ea6  vp90-2-02-size-32x18-32x18-0009.i420
+adbbbc192cf36e1fc7c308824765d482  vp90-2-02-size-32x18-32x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x32.vp9
new file mode 100644
index 0000000..fbfa4ab
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x32_vp9_md5
new file mode 100644
index 0000000..4e5b3c4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x32_vp9_md5
@@ -0,0 +1,10 @@
+117915db1856cee26f05a609c8c8de2e  vp90-2-02-size-32x32-32x32-0001.i420
+943771a98b26b174e88ed1f4e872e504  vp90-2-02-size-32x32-32x32-0002.i420
+3e0d2585e1f1cb540998d107aca5c395  vp90-2-02-size-32x32-32x32-0003.i420
+e64a9e1e0232983a69ab48453025b23d  vp90-2-02-size-32x32-32x32-0004.i420
+2c6ef6637fb7b9425f7d7ea28cd84087  vp90-2-02-size-32x32-32x32-0005.i420
+419a5a31a43955d408c13ee8a5ddce9c  vp90-2-02-size-32x32-32x32-0006.i420
+2ab13e1c236553d42d59498ca350b190  vp90-2-02-size-32x32-32x32-0007.i420
+b8068beb037f3232d4da38fe33a8a885  vp90-2-02-size-32x32-32x32-0008.i420
+160df68b9e3f75e9b1f8ed7cce327bc2  vp90-2-02-size-32x32-32x32-0009.i420
+1ccafa8c7babdce0983aeb20d298b0ee  vp90-2-02-size-32x32-32x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x34.vp9
new file mode 100644
index 0000000..7ea9965
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x34_vp9_md5
new file mode 100644
index 0000000..28b1e11
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x34_vp9_md5
@@ -0,0 +1,10 @@
+770582911fd0095ebbeae384e87665ac  vp90-2-02-size-32x34-32x34-0001.i420
+f99d7e3131f04413cba2f9de6818976d  vp90-2-02-size-32x34-32x34-0002.i420
+3bfbb8c9c48f24cd596973a6deb33a3f  vp90-2-02-size-32x34-32x34-0003.i420
+0b8166afdd357f20c76f77d228bb7171  vp90-2-02-size-32x34-32x34-0004.i420
+3a3d7f2a03e19a82250d6ca0238f9791  vp90-2-02-size-32x34-32x34-0005.i420
+9b558f9b8744b016059f69f3fca90d2c  vp90-2-02-size-32x34-32x34-0006.i420
+c857736342f1145d919cb77732120006  vp90-2-02-size-32x34-32x34-0007.i420
+11dc5dda4c883a3146db060dd50343d0  vp90-2-02-size-32x34-32x34-0008.i420
+7526a62ae87de174be86eac7bb36c7f3  vp90-2-02-size-32x34-32x34-0009.i420
+9ef38f47cfc461710ff0dd75690473c0  vp90-2-02-size-32x34-32x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x64.vp9
new file mode 100644
index 0000000..0bc9223
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x64_vp9_md5
new file mode 100644
index 0000000..d00ccc6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x64_vp9_md5
@@ -0,0 +1,10 @@
+caa8471a8b381d53c3e8fc627946a871  vp90-2-02-size-32x64-32x64-0001.i420
+2cba86ea14c0f28e242625b08f5e9b88  vp90-2-02-size-32x64-32x64-0002.i420
+cea0440ff6569fc82c3030e0340fb649  vp90-2-02-size-32x64-32x64-0003.i420
+c18ef37f1356ade96a2f40af954b31c8  vp90-2-02-size-32x64-32x64-0004.i420
+21e6e549378bcff47913ef292e74dc37  vp90-2-02-size-32x64-32x64-0005.i420
+a9d3d483f74a5afe5d80725ce696fd20  vp90-2-02-size-32x64-32x64-0006.i420
+a436e2586b0963747deaf5e450e2b230  vp90-2-02-size-32x64-32x64-0007.i420
+9daaadf265df56974cb0950843d9fd8c  vp90-2-02-size-32x64-32x64-0008.i420
+e0b84714bad2519e62b7d16705fb09d5  vp90-2-02-size-32x64-32x64-0009.i420
+8cdfce574edbe548da7f6cd9a7076b9e  vp90-2-02-size-32x64-32x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_32x66.vp9
new file mode 100644
index 0000000..9d96d3d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_32x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_32x66_vp9_md5
new file mode 100644
index 0000000..4a00973
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_32x66_vp9_md5
@@ -0,0 +1,10 @@
+920ea4b8a00d41489d122d641d6e4fe5  vp90-2-02-size-32x66-32x66-0001.i420
+8bfc8d452a79f2978b8e973b77cbf8a8  vp90-2-02-size-32x66-32x66-0002.i420
+09f3f0d31d3377a844fa5385d9b36b9f  vp90-2-02-size-32x66-32x66-0003.i420
+df43fae763da9360c8062bb92ee091a8  vp90-2-02-size-32x66-32x66-0004.i420
+445d8c675bb865d1814fcfa6b8a9afd3  vp90-2-02-size-32x66-32x66-0005.i420
+dc7d43db86aac6636724de8790eda555  vp90-2-02-size-32x66-32x66-0006.i420
+d3a9fc272424449ffc5b7e69f8f9948b  vp90-2-02-size-32x66-32x66-0007.i420
+11ef33b9bccca54b3703bf24ab55e2d6  vp90-2-02-size-32x66-32x66-0008.i420
+ce31b8bf9b00b427ca956abb800d8034  vp90-2-02-size-32x66-32x66-0009.i420
+e707f824d6e95d482bf3a0b4d52ea069  vp90-2-02-size-32x66-32x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x08.vp9
new file mode 100644
index 0000000..3a1d276
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x08_vp9_md5
new file mode 100644
index 0000000..2940416
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x08_vp9_md5
@@ -0,0 +1,10 @@
+c14f2ba5b4582c9d3a488976814691b3  vp90-2-02-size-34x08-34x8-0001.i420
+4387a4dce19007b7efb810b5a4069749  vp90-2-02-size-34x08-34x8-0002.i420
+ecfe868d28f4861a5612edfd57447a02  vp90-2-02-size-34x08-34x8-0003.i420
+5cba54f568534d29169ac31c8fa505e0  vp90-2-02-size-34x08-34x8-0004.i420
+fe9aab7b3378b9fc3e373ee626b887db  vp90-2-02-size-34x08-34x8-0005.i420
+fce72dfc7f9c0cb50ff73761b4d82c1f  vp90-2-02-size-34x08-34x8-0006.i420
+d4d98f42b1377e0f0ffaa66aa81d40c3  vp90-2-02-size-34x08-34x8-0007.i420
+65c027646dc95a749ce2d7ad0a6beccc  vp90-2-02-size-34x08-34x8-0008.i420
+317b283a0d907270f671272771022e69  vp90-2-02-size-34x08-34x8-0009.i420
+d3e2c008584608502f3e24c5c5f64028  vp90-2-02-size-34x08-34x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x10.vp9
new file mode 100644
index 0000000..336a18a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x10_vp9_md5
new file mode 100644
index 0000000..9e19ab4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x10_vp9_md5
@@ -0,0 +1,10 @@
+fd7212b519783cf4831ce4bff91f2312  vp90-2-02-size-34x10-34x10-0001.i420
+9768722ee939d80a6716865fdebca33d  vp90-2-02-size-34x10-34x10-0002.i420
+328ee0f774eeafde00dcc4b9a8f4e9af  vp90-2-02-size-34x10-34x10-0003.i420
+f882fa6015fcb042094eadab5fa952cf  vp90-2-02-size-34x10-34x10-0004.i420
+4331a3dabeae27d2bf3590eb96ce914a  vp90-2-02-size-34x10-34x10-0005.i420
+0e15106bd8e90377f6ed8b464d17159c  vp90-2-02-size-34x10-34x10-0006.i420
+8f062653ac2b83f7e541393e838d0e0f  vp90-2-02-size-34x10-34x10-0007.i420
+eeb98c1728c1a74510f8bfaf10fc0002  vp90-2-02-size-34x10-34x10-0008.i420
+30bb058a67d6a5ee3693b21cbca5349a  vp90-2-02-size-34x10-34x10-0009.i420
+7ce4b79983b3abc37b141a3bea56e0b7  vp90-2-02-size-34x10-34x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x16.vp9
new file mode 100644
index 0000000..41d41f3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x16_vp9_md5
new file mode 100644
index 0000000..1c01cd4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x16_vp9_md5
@@ -0,0 +1,10 @@
+e443c43101be00470c6a61c1a2995b5a  vp90-2-02-size-34x16-34x16-0001.i420
+1e79b1b46ec704d360b5fb725913b0f1  vp90-2-02-size-34x16-34x16-0002.i420
+6d5e77cafab6bc43498980c515d299d3  vp90-2-02-size-34x16-34x16-0003.i420
+91c3bba5fd2aa29ee54c8f3783cfe5a2  vp90-2-02-size-34x16-34x16-0004.i420
+9548d07c2a6204694d34e973e8339077  vp90-2-02-size-34x16-34x16-0005.i420
+6819a34c7e3c13bee3ea2b18e12e92fd  vp90-2-02-size-34x16-34x16-0006.i420
+f75920457f01f65bf30ba1ec41076d4e  vp90-2-02-size-34x16-34x16-0007.i420
+3a04f6cc0c348c21464b173ac6005043  vp90-2-02-size-34x16-34x16-0008.i420
+93a3336374e8cc4dfb2c0b4716ab60ec  vp90-2-02-size-34x16-34x16-0009.i420
+148af188b8a2ee93de406a01c2af180d  vp90-2-02-size-34x16-34x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x18.vp9
new file mode 100644
index 0000000..9c2f4ea
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x18_vp9_md5
new file mode 100644
index 0000000..74ee172
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x18_vp9_md5
@@ -0,0 +1,10 @@
+ab7eabb355e5163e7451945018fadebd  vp90-2-02-size-34x18-34x18-0001.i420
+b9a77cc0c769535808996a6de7b374ff  vp90-2-02-size-34x18-34x18-0002.i420
+bd773f11d89091b3c9ebc22d8291dd49  vp90-2-02-size-34x18-34x18-0003.i420
+278c215d6c188752818f07f4d317c0e0  vp90-2-02-size-34x18-34x18-0004.i420
+b59856932c675c1ba587644c23cdb002  vp90-2-02-size-34x18-34x18-0005.i420
+2bcaef04f89326a56025269a68742043  vp90-2-02-size-34x18-34x18-0006.i420
+5abb4a1b96b4bc003cd19a146347c54e  vp90-2-02-size-34x18-34x18-0007.i420
+26e36058f451ff80d498ac1c0343489f  vp90-2-02-size-34x18-34x18-0008.i420
+57ac43fcc6f1a2c863188aca68d52524  vp90-2-02-size-34x18-34x18-0009.i420
+282467118b5b7a986ccd28d16dab3ea7  vp90-2-02-size-34x18-34x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x32.vp9
new file mode 100644
index 0000000..2c020b4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x32_vp9_md5
new file mode 100644
index 0000000..fb6d77d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x32_vp9_md5
@@ -0,0 +1,10 @@
+7e334867e27046fabf0f39365311c38c  vp90-2-02-size-34x32-34x32-0001.i420
+d2a49216ecedea62f546e54c1552f163  vp90-2-02-size-34x32-34x32-0002.i420
+f66e10d1779533e5b6e2b98369134833  vp90-2-02-size-34x32-34x32-0003.i420
+0054b8d4393df58eee87784862a29901  vp90-2-02-size-34x32-34x32-0004.i420
+b9cdf3ebea0d1e3f1e0c42db2e11a3c2  vp90-2-02-size-34x32-34x32-0005.i420
+c08a728d955a559457c82e44c3296148  vp90-2-02-size-34x32-34x32-0006.i420
+d05f4c4a8b0e606525c3d388d26a9351  vp90-2-02-size-34x32-34x32-0007.i420
+78fc2544da88a1a21d6626b0f7bbcf8c  vp90-2-02-size-34x32-34x32-0008.i420
+90832c4fed05390377551359bb9a91f7  vp90-2-02-size-34x32-34x32-0009.i420
+5290a0e77081863398f36c7ae192710b  vp90-2-02-size-34x32-34x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x34.vp9
new file mode 100644
index 0000000..bcc9c17
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x34_vp9_md5
new file mode 100644
index 0000000..36d92f5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x34_vp9_md5
@@ -0,0 +1,10 @@
+1bb98ba89abf6b86f47a851f8126e1ff  vp90-2-02-size-34x34-34x34-0001.i420
+b960cc795c179afe7eec360c57fddd7f  vp90-2-02-size-34x34-34x34-0002.i420
+a93cd094a80c542ecb7b6ac7720c5eff  vp90-2-02-size-34x34-34x34-0003.i420
+f1cd34e4f0bf9b1238769f028708b742  vp90-2-02-size-34x34-34x34-0004.i420
+f01437ad14450d2136a8fc971f180eb7  vp90-2-02-size-34x34-34x34-0005.i420
+8778230f1182c2227bf1e253bd85df4c  vp90-2-02-size-34x34-34x34-0006.i420
+1d1d5cf6c5cc9e73a1fa5b882e441d74  vp90-2-02-size-34x34-34x34-0007.i420
+2f7a1867487c56c252e35225f71adb55  vp90-2-02-size-34x34-34x34-0008.i420
+1d1aea21f70ceed596f22ec32d8712ee  vp90-2-02-size-34x34-34x34-0009.i420
+260e66df92f32bc853f4cd4ede692ea4  vp90-2-02-size-34x34-34x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x64.vp9
new file mode 100644
index 0000000..daa63a3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x64_vp9_md5
new file mode 100644
index 0000000..6a6795e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x64_vp9_md5
@@ -0,0 +1,10 @@
+3856635223f578e1e7f7e7250a53cb8d  vp90-2-02-size-34x64-34x64-0001.i420
+ee8d7c3a0ea165420d7e733b9e59219a  vp90-2-02-size-34x64-34x64-0002.i420
+3d33f06bac22131f04e3411fc216dc02  vp90-2-02-size-34x64-34x64-0003.i420
+7aea667775077de32250dac25fd24bb3  vp90-2-02-size-34x64-34x64-0004.i420
+43fb534551f153c5e9e60240df0bf3b4  vp90-2-02-size-34x64-34x64-0005.i420
+d42b721aa2242d4258d97f840fdcc901  vp90-2-02-size-34x64-34x64-0006.i420
+e876200d720cbe6e36e0ffb775c5ad6c  vp90-2-02-size-34x64-34x64-0007.i420
+453078449d8701270564086e58a1d69e  vp90-2-02-size-34x64-34x64-0008.i420
+22cb799a817d45a7591489e6faa31cb9  vp90-2-02-size-34x64-34x64-0009.i420
+628dc3f03bf5dd5cae135ad1e4b9ebf7  vp90-2-02-size-34x64-34x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_34x66.vp9
new file mode 100644
index 0000000..ca90995
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_34x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_34x66_vp9_md5
new file mode 100644
index 0000000..af3cde6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_34x66_vp9_md5
@@ -0,0 +1,10 @@
+bf4e568217906ee4b58dc4707bee8ef6  vp90-2-02-size-34x66-34x66-0001.i420
+f823f8c7b6e47ba43215f3becd35208e  vp90-2-02-size-34x66-34x66-0002.i420
+1d986d65b502e77764428e21e77503a6  vp90-2-02-size-34x66-34x66-0003.i420
+73520382bc54d6aee165402518dd7b5d  vp90-2-02-size-34x66-34x66-0004.i420
+c84e943758f2d7e37126172728838640  vp90-2-02-size-34x66-34x66-0005.i420
+1d4b298da98e4b66b31ad6874f726aa6  vp90-2-02-size-34x66-34x66-0006.i420
+e67748eeb3c818deb8b51d321cd16a9c  vp90-2-02-size-34x66-34x66-0007.i420
+4d1514c63e669261beef9e35b04c241e  vp90-2-02-size-34x66-34x66-0008.i420
+57705e2131e2129efbc68b74a1e0459c  vp90-2-02-size-34x66-34x66-0009.i420
+681acf1b384856d6e544d8e7a79fc628  vp90-2-02-size-34x66-34x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x08.vp9
new file mode 100644
index 0000000..cfb8189
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x08_vp9_md5
new file mode 100644
index 0000000..0b40ce8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x08_vp9_md5
@@ -0,0 +1,10 @@
+d801797c94039b0a166d46e151ec912c  vp90-2-02-size-64x08-64x8-0001.i420
+161ec22caa3689b214d9ab993424584b  vp90-2-02-size-64x08-64x8-0002.i420
+499b589ecf1873e388c256ce948eabb9  vp90-2-02-size-64x08-64x8-0003.i420
+22bc77650e3df70e3e36f2a1b8d8aa71  vp90-2-02-size-64x08-64x8-0004.i420
+750e40530257a68211596a60de18bffa  vp90-2-02-size-64x08-64x8-0005.i420
+4f812a92157e7186642656b59bc28a3d  vp90-2-02-size-64x08-64x8-0006.i420
+a3f141cec127a2c2e16740b8dd4ce56a  vp90-2-02-size-64x08-64x8-0007.i420
+a5ba9959bf65ab6e254e5b359a3d59b5  vp90-2-02-size-64x08-64x8-0008.i420
+baa72b8a57277d9e9ad4b92aab04f5d1  vp90-2-02-size-64x08-64x8-0009.i420
+4cb9aebb6c9d5bd164461726de201549  vp90-2-02-size-64x08-64x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x10.vp9
new file mode 100644
index 0000000..243962a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x10_vp9_md5
new file mode 100644
index 0000000..acd1ed1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x10_vp9_md5
@@ -0,0 +1,10 @@
+97eb5fd0599d482662eb0a1def5c5ef2  vp90-2-02-size-64x10-64x10-0001.i420
+dfdc1b61b478dcca8d411021486aa2ec  vp90-2-02-size-64x10-64x10-0002.i420
+2cf560f068bdcb9e345951739091808e  vp90-2-02-size-64x10-64x10-0003.i420
+33cacb04c0797fc7bd774251e04b7fb9  vp90-2-02-size-64x10-64x10-0004.i420
+7fca126c0542c0dcdcf769b156bd85f5  vp90-2-02-size-64x10-64x10-0005.i420
+8a46c5a48cb5bd34be8e647c127f8d61  vp90-2-02-size-64x10-64x10-0006.i420
+1ddf07562c0b7dc68ed61b8e1a09fcf0  vp90-2-02-size-64x10-64x10-0007.i420
+d75911d5eb7fc75ffc3ee40344fc7ed2  vp90-2-02-size-64x10-64x10-0008.i420
+498329c8a01d950286af11e1fcf3ac07  vp90-2-02-size-64x10-64x10-0009.i420
+7a6ec019df5f3e419d389699094f87c3  vp90-2-02-size-64x10-64x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x16.vp9
new file mode 100644
index 0000000..28663da
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x16_vp9_md5
new file mode 100644
index 0000000..dd67756
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x16_vp9_md5
@@ -0,0 +1,10 @@
+a43068a364cc42619e62406dcf17ddfc  vp90-2-02-size-64x16-64x16-0001.i420
+94691f93299bbf5b6ba3022b02b3e069  vp90-2-02-size-64x16-64x16-0002.i420
+3c8fc275490b4daf63ef6d8f9b7f81f6  vp90-2-02-size-64x16-64x16-0003.i420
+96c06031f0fcad49dfed256c5c737d07  vp90-2-02-size-64x16-64x16-0004.i420
+f722d3a51790b55d070d57d3b9a53d0d  vp90-2-02-size-64x16-64x16-0005.i420
+a753b3dfe13f5778f9f054e73e512ef1  vp90-2-02-size-64x16-64x16-0006.i420
+fa12cbe6cbc38fa8a38ecbcf1af8833c  vp90-2-02-size-64x16-64x16-0007.i420
+cb42303391ef6f76f77d14d2600cce12  vp90-2-02-size-64x16-64x16-0008.i420
+e0c18bb1d4dcc8168b5fdd7c7963987e  vp90-2-02-size-64x16-64x16-0009.i420
+581b5291cb60e50326c0dfa6a2d09d8a  vp90-2-02-size-64x16-64x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x18.vp9
new file mode 100644
index 0000000..9fb5e37
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x18_vp9_md5
new file mode 100644
index 0000000..4a01c17
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x18_vp9_md5
@@ -0,0 +1,10 @@
+adf7e84a351847683f6a8dd177019e29  vp90-2-02-size-64x18-64x18-0001.i420
+8227cf283a27277fbab3d7826e340337  vp90-2-02-size-64x18-64x18-0002.i420
+a5551b16db948e395537310d12128e76  vp90-2-02-size-64x18-64x18-0003.i420
+4b57ed07dbc15de9ab6143656b2a7e8e  vp90-2-02-size-64x18-64x18-0004.i420
+a15489495f0acc41f446e9689e4142d6  vp90-2-02-size-64x18-64x18-0005.i420
+b0a0d5d3ff756e8ae19797455432755c  vp90-2-02-size-64x18-64x18-0006.i420
+094a440243d36edcdd3e9d0d070de011  vp90-2-02-size-64x18-64x18-0007.i420
+a780bd61e1abbfbb28581784531608bd  vp90-2-02-size-64x18-64x18-0008.i420
+55886a8c7aad65683aa9366a38382512  vp90-2-02-size-64x18-64x18-0009.i420
+5ae5b24383f66720a62ed1001664051f  vp90-2-02-size-64x18-64x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x32.vp9
new file mode 100644
index 0000000..c80dcf2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x32_vp9_md5
new file mode 100644
index 0000000..15e0b11
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x32_vp9_md5
@@ -0,0 +1,10 @@
+931ab6a2482c3e84bc7ef8dfbc251307  vp90-2-02-size-64x32-64x32-0001.i420
+3552a9d8470a64ed627a6dbb799b7811  vp90-2-02-size-64x32-64x32-0002.i420
+cae1863fc606a0e3df3e708b7eefdf99  vp90-2-02-size-64x32-64x32-0003.i420
+4b825a07e235c4708b12a726da8e4cdf  vp90-2-02-size-64x32-64x32-0004.i420
+0dac578ef616a13be2b9db3c0d775524  vp90-2-02-size-64x32-64x32-0005.i420
+bfd47cbab8285f301777351c8bc5553c  vp90-2-02-size-64x32-64x32-0006.i420
+f29f9a0cfeaaae3bdeb26933bc7c17dc  vp90-2-02-size-64x32-64x32-0007.i420
+c7f3a4d24dcf72ef195a402eff77d8f6  vp90-2-02-size-64x32-64x32-0008.i420
+88ede6207441a7953cf893032c353663  vp90-2-02-size-64x32-64x32-0009.i420
+258f4e86541813e3edb1fe5332ff4ab1  vp90-2-02-size-64x32-64x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x34.vp9
new file mode 100644
index 0000000..ddd6d64
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x34_vp9_md5
new file mode 100644
index 0000000..2727525
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x34_vp9_md5
@@ -0,0 +1,10 @@
+68d00958a78e6252dd75d632806e2022  vp90-2-02-size-64x34-64x34-0001.i420
+f7b6266e74200a669eecd241db787ee2  vp90-2-02-size-64x34-64x34-0002.i420
+c8b88d43aee037857310edeb74bc66f4  vp90-2-02-size-64x34-64x34-0003.i420
+c6d9a52baf3ca962574bff1364fcb8dc  vp90-2-02-size-64x34-64x34-0004.i420
+b384fbf3ceef0affa69f5e81681edc6e  vp90-2-02-size-64x34-64x34-0005.i420
+cd473f0c8d1cde98153402123a3ee7cf  vp90-2-02-size-64x34-64x34-0006.i420
+c0f320a23c3e39719a3b3590fe3c2ab5  vp90-2-02-size-64x34-64x34-0007.i420
+751207d15a791728c1022f711a25cd68  vp90-2-02-size-64x34-64x34-0008.i420
+7396df89a0d88044cf7527420d193636  vp90-2-02-size-64x34-64x34-0009.i420
+b772dd247838b0c3ed12713447894323  vp90-2-02-size-64x34-64x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x64.vp9
new file mode 100644
index 0000000..af3b43d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x64_vp9_md5
new file mode 100644
index 0000000..9733f63
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x64_vp9_md5
@@ -0,0 +1,10 @@
+35f17db9076fa20368fddfa01543c746  vp90-2-02-size-64x64-64x64-0001.i420
+61cd775dfc177262da9a91d3912e6718  vp90-2-02-size-64x64-64x64-0002.i420
+8b8cf175f91425d703332b22b46c1c0e  vp90-2-02-size-64x64-64x64-0003.i420
+6041afbdd81e228f8f16384d3f9e988e  vp90-2-02-size-64x64-64x64-0004.i420
+d30bd08897b50f518920014c7fa55df9  vp90-2-02-size-64x64-64x64-0005.i420
+fb67222a183876b502f93e48bb779b70  vp90-2-02-size-64x64-64x64-0006.i420
+60830425ca1dcf3df4ee9c6cd75f066a  vp90-2-02-size-64x64-64x64-0007.i420
+3e178df858f7fcaa2552a1c5c719b5cc  vp90-2-02-size-64x64-64x64-0008.i420
+66718eb0c3981beb7c1119df8a2cd27e  vp90-2-02-size-64x64-64x64-0009.i420
+7c1912448c7756f7451888050760d73d  vp90-2-02-size-64x64-64x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_64x66.vp9
new file mode 100644
index 0000000..eecb1c0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_64x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_64x66_vp9_md5
new file mode 100644
index 0000000..1c4d7e9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_64x66_vp9_md5
@@ -0,0 +1,10 @@
+88587de65acfc85ff56daac8ef5d12e6  vp90-2-02-size-64x66-64x66-0001.i420
+be41f6c788b929b5b6b27c5674f40abd  vp90-2-02-size-64x66-64x66-0002.i420
+04ab3f88ca062a6911405fd84c7e9de4  vp90-2-02-size-64x66-64x66-0003.i420
+231436e0a68d19d3882f285d38aca3fb  vp90-2-02-size-64x66-64x66-0004.i420
+1a067e147a6740bb4ce57c4184437eea  vp90-2-02-size-64x66-64x66-0005.i420
+be0c47e06c7e9439570473adf4713f5f  vp90-2-02-size-64x66-64x66-0006.i420
+a213b0611247eafab0711748c25e88a0  vp90-2-02-size-64x66-64x66-0007.i420
+b1df495aa3afb74399f91c74b527b93c  vp90-2-02-size-64x66-64x66-0008.i420
+46319f21069541e1ee1652621b957860  vp90-2-02-size-64x66-64x66-0009.i420
+313517a5721b2b14683e7eefc83e51b1  vp90-2-02-size-64x66-64x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x08.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x08.vp9
new file mode 100644
index 0000000..3b05d4f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x08.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x08_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x08_vp9_md5
new file mode 100644
index 0000000..1879fe4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x08_vp9_md5
@@ -0,0 +1,10 @@
+3b16847e60786706fc339abc452746ff  vp90-2-02-size-66x08-66x8-0001.i420
+365a5951cb127d6df183fe5d5000f493  vp90-2-02-size-66x08-66x8-0002.i420
+6d4bceb815ca7717c4a3f86a6670703a  vp90-2-02-size-66x08-66x8-0003.i420
+5a0a03d4788934285448c85788ae8d71  vp90-2-02-size-66x08-66x8-0004.i420
+8712f9a82d07447e7a0d0a37ddc3858d  vp90-2-02-size-66x08-66x8-0005.i420
+cff32e6c183c16962207a86d7c6cf0a0  vp90-2-02-size-66x08-66x8-0006.i420
+dc933d90f87110651d7efb39854d3d46  vp90-2-02-size-66x08-66x8-0007.i420
+d1299562a022521f0c3cb30668f83b6d  vp90-2-02-size-66x08-66x8-0008.i420
+5054254ca125d7c7e6df4001397170cd  vp90-2-02-size-66x08-66x8-0009.i420
+a6bd7c7c0b02afa8d25f911ec847c61a  vp90-2-02-size-66x08-66x8-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x10.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x10.vp9
new file mode 100644
index 0000000..32c62e4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x10.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x10_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x10_vp9_md5
new file mode 100644
index 0000000..56a9c16
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x10_vp9_md5
@@ -0,0 +1,10 @@
+7cbd8c6b2fb35c0c3063cb7a379944c9  vp90-2-02-size-66x10-66x10-0001.i420
+14062e74b98bed1ca982f408bc14326c  vp90-2-02-size-66x10-66x10-0002.i420
+f6d6868d849aa74b27df1c5f40c7096e  vp90-2-02-size-66x10-66x10-0003.i420
+719c8d7e3769466ee8e3dca3f4747a0e  vp90-2-02-size-66x10-66x10-0004.i420
+a72e1a7a4c82ec09ea77f87b0e6f25aa  vp90-2-02-size-66x10-66x10-0005.i420
+a5163d142b429afa155cc2f1401a0b8a  vp90-2-02-size-66x10-66x10-0006.i420
+27762d813dd1f80d6aaed5f197124fa5  vp90-2-02-size-66x10-66x10-0007.i420
+02e94454660f3528abbde8f50e94288f  vp90-2-02-size-66x10-66x10-0008.i420
+1d57dcfa57a55d96f14cfe471aac2e0b  vp90-2-02-size-66x10-66x10-0009.i420
+7804477923c0cd067bd09ebca3529775  vp90-2-02-size-66x10-66x10-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x16.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x16.vp9
new file mode 100644
index 0000000..6a0d1ac
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x16.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x16_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x16_vp9_md5
new file mode 100644
index 0000000..2aae0a2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x16_vp9_md5
@@ -0,0 +1,10 @@
+fa2f292d273c37dc2804a70d1cae1e9d  vp90-2-02-size-66x16-66x16-0001.i420
+ba75d90652c021bc7ca061352e6e94ce  vp90-2-02-size-66x16-66x16-0002.i420
+e65d9a205bd17d100e50c7b6a7ea772d  vp90-2-02-size-66x16-66x16-0003.i420
+46f9e9ff891576b9462f21d48b7b9e2b  vp90-2-02-size-66x16-66x16-0004.i420
+d23cedacf3a37cf6b2774e0b18b6b9d7  vp90-2-02-size-66x16-66x16-0005.i420
+84329f7716a6db5a7e64a68a1155bfc6  vp90-2-02-size-66x16-66x16-0006.i420
+ad62286b0e13f4e54df4445cdd4fd4e3  vp90-2-02-size-66x16-66x16-0007.i420
+4511529eb24b21eb63e280070f888642  vp90-2-02-size-66x16-66x16-0008.i420
+4e1c122df1785e0e9134c43c85082e05  vp90-2-02-size-66x16-66x16-0009.i420
+ac3a3747a00be3f9f58155648fcf9b24  vp90-2-02-size-66x16-66x16-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x18.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x18.vp9
new file mode 100644
index 0000000..e2535f0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x18.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x18_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x18_vp9_md5
new file mode 100644
index 0000000..05e3eaf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x18_vp9_md5
@@ -0,0 +1,10 @@
+fda5ad9bf70a51b3a41bdcabf2cce32a  vp90-2-02-size-66x18-66x18-0001.i420
+91916fb20ad542a7a3ad276e6505f9b0  vp90-2-02-size-66x18-66x18-0002.i420
+e18e5d11aec483c76afd68f7e64415a4  vp90-2-02-size-66x18-66x18-0003.i420
+c13da01c2b6c09101bda7af93ad5fd07  vp90-2-02-size-66x18-66x18-0004.i420
+ed8d2568b2ad9c7bd980cba0d3b95cff  vp90-2-02-size-66x18-66x18-0005.i420
+e6f3cf312b69d37579e77f2e52cc936b  vp90-2-02-size-66x18-66x18-0006.i420
+e509f3682e9c4bcdb0889e044b1979b7  vp90-2-02-size-66x18-66x18-0007.i420
+acc3945e557cd7a9642f08a656444976  vp90-2-02-size-66x18-66x18-0008.i420
+44ddd03aa8f03ba393f12fc6a1b3fc17  vp90-2-02-size-66x18-66x18-0009.i420
+fdd3e68132c742d9f0cf0ea6fff2a074  vp90-2-02-size-66x18-66x18-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x32.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x32.vp9
new file mode 100644
index 0000000..445d975
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x32.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x32_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x32_vp9_md5
new file mode 100644
index 0000000..996f32b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x32_vp9_md5
@@ -0,0 +1,10 @@
+013cd22aea6bfeccc8ec809abd52be5c  vp90-2-02-size-66x32-66x32-0001.i420
+0980adfb0ef879b3c960797272f025ad  vp90-2-02-size-66x32-66x32-0002.i420
+d1411ffa0429befb8c71d3ab45acee92  vp90-2-02-size-66x32-66x32-0003.i420
+6c6f825379eaf21709a45be77def7a63  vp90-2-02-size-66x32-66x32-0004.i420
+bab632ef00a080739a41c692f2b21c3a  vp90-2-02-size-66x32-66x32-0005.i420
+fc0f6045aca252f2e904730227b8f337  vp90-2-02-size-66x32-66x32-0006.i420
+c8dbea209329463bfd9238a11b8d5b17  vp90-2-02-size-66x32-66x32-0007.i420
+457247bf4186ed8459e0a1564f0e68f2  vp90-2-02-size-66x32-66x32-0008.i420
+baa55e20bd7c73960b080d8a0c8db4d5  vp90-2-02-size-66x32-66x32-0009.i420
+dc8933e8edc98cd0cfca44ae22997c62  vp90-2-02-size-66x32-66x32-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x34.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x34.vp9
new file mode 100644
index 0000000..8705e9f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x34.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x34_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x34_vp9_md5
new file mode 100644
index 0000000..ca0e251
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x34_vp9_md5
@@ -0,0 +1,10 @@
+6821eb3fcd1d10db32eff70468dcf9c1  vp90-2-02-size-66x34-66x34-0001.i420
+ed0094d347d9f250d46b4903cbc14801  vp90-2-02-size-66x34-66x34-0002.i420
+fd018555dc9a62b8074d46e7c0fd0b40  vp90-2-02-size-66x34-66x34-0003.i420
+05d5baf9f2e62bbeeb3809a099e84147  vp90-2-02-size-66x34-66x34-0004.i420
+7a150c265214269c08e05fe4f296122d  vp90-2-02-size-66x34-66x34-0005.i420
+9a7ae61d4bb125ee4c4ccce9cc1c3664  vp90-2-02-size-66x34-66x34-0006.i420
+5a88fd6d96dcbc4255e98dfe19ff96b8  vp90-2-02-size-66x34-66x34-0007.i420
+4192c273a46b2b196c871ead0e61ec71  vp90-2-02-size-66x34-66x34-0008.i420
+e79ebfc47e755f5db221f392c3216278  vp90-2-02-size-66x34-66x34-0009.i420
+b995c5f483a2e553baf4f66d1a47fc57  vp90-2-02-size-66x34-66x34-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x64.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x64.vp9
new file mode 100644
index 0000000..c91df34
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x64.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x64_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x64_vp9_md5
new file mode 100644
index 0000000..9802722
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x64_vp9_md5
@@ -0,0 +1,10 @@
+929086fbb3e117bd53110b64c1ee915b  vp90-2-02-size-66x64-66x64-0001.i420
+9ed45f5e40dd2393434e14a0c0160c63  vp90-2-02-size-66x64-66x64-0002.i420
+5cdade692b1baf23e61896da18e3e44f  vp90-2-02-size-66x64-66x64-0003.i420
+11a2ebac61a3f826ec41c8031899e55c  vp90-2-02-size-66x64-66x64-0004.i420
+621a1e0142b94d14db9c2121553a11fb  vp90-2-02-size-66x64-66x64-0005.i420
+029a29590f7255f1bc9ff9b7a000ca25  vp90-2-02-size-66x64-66x64-0006.i420
+5fde42becf6bf054d04e2a0fa1b2d55e  vp90-2-02-size-66x64-66x64-0007.i420
+5b8ba552cef1931e1412fb4f3420748b  vp90-2-02-size-66x64-66x64-0008.i420
+d41cd7d418f6ec1db802a01a90cfee1e  vp90-2-02-size-66x64-66x64-0009.i420
+cea99c93a84a82edff8c6069d131453f  vp90-2-02-size-66x64-66x64-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x66.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_66x66.vp9
new file mode 100644
index 0000000..e50c30a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x66.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_66x66_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_66x66_vp9_md5
new file mode 100644
index 0000000..4cf3ed2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_66x66_vp9_md5
@@ -0,0 +1,10 @@
+69f9028d52f95d2e7f986c57b19fc018  vp90-2-02-size-66x66-66x66-0001.i420
+068e611f62b3f6222f6b1699748c8fbf  vp90-2-02-size-66x66-66x66-0002.i420
+3d3fec78ff2274241a7958f17a773a19  vp90-2-02-size-66x66-66x66-0003.i420
+93d71ef1a2d00c7e70e76ccc1859143d  vp90-2-02-size-66x66-66x66-0004.i420
+5a35a640d52bc0930825b963b0b9e830  vp90-2-02-size-66x66-66x66-0005.i420
+782223239e6b1ca1bedbd25d9652a07c  vp90-2-02-size-66x66-66x66-0006.i420
+a4b5e8a319cbc9a12d3e36127c7f0fbb  vp90-2-02-size-66x66-66x66-0007.i420
+a3e2d9a78fa42b3c817aadfd31fd2d16  vp90-2-02-size-66x66-66x66-0008.i420
+e9fc6b83535735f46006f3e4b376755f  vp90-2-02-size-66x66-66x66-0009.i420
+80223f600dfe86021bd0e83fecdc4b2b  vp90-2-02-size-66x66-66x66-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080.vp9 b/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080.vp9
new file mode 100644
index 0000000..d7cfc93
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080_vp9_md5 b/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080_vp9_md5
new file mode 100644
index 0000000..557ac7a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_02_size_lf_1920x1080_vp9_md5
@@ -0,0 +1,217 @@
+3fb5a1b268b017332fda7fa981032c2c  vp90-2-02-size-lf-1920x1080-1920x1080-0001.i420
+7380f42c862bb0418274010f71f8291f  vp90-2-02-size-lf-1920x1080-1920x1080-0002.i420
+1931968e92c34f693582d1ae28e7a145  vp90-2-02-size-lf-1920x1080-1920x1080-0003.i420
+40606221248726f3412d8e08e489a94f  vp90-2-02-size-lf-1920x1080-1920x1080-0004.i420
+5ecd3fd1d4b607e3d84fb597a948d84b  vp90-2-02-size-lf-1920x1080-1920x1080-0005.i420
+db805d6f9289f1525c4ea594bf323fdc  vp90-2-02-size-lf-1920x1080-1920x1080-0006.i420
+7584c857279bfcf6e5e1e29557c2a6f0  vp90-2-02-size-lf-1920x1080-1920x1080-0007.i420
+bf436864c58c4d2db1d9b31ce06a8f70  vp90-2-02-size-lf-1920x1080-1920x1080-0008.i420
+9712ccf78bcddc0c44c221c2767e1f28  vp90-2-02-size-lf-1920x1080-1920x1080-0009.i420
+3071176342e59678d99dd8686336e476  vp90-2-02-size-lf-1920x1080-1920x1080-0010.i420
+92cfa56092e8e4d5269de441d31ec739  vp90-2-02-size-lf-1920x1080-1920x1080-0011.i420
+d0bc77ad1997bc38f312846a40d11a16  vp90-2-02-size-lf-1920x1080-1920x1080-0012.i420
+c656c39e3527eee973033b42d4b9deef  vp90-2-02-size-lf-1920x1080-1920x1080-0013.i420
+725ccfe5d0736997aa78f7d948692cdb  vp90-2-02-size-lf-1920x1080-1920x1080-0014.i420
+51f2245ebc2da1e3bdd0708e9d18e1eb  vp90-2-02-size-lf-1920x1080-1920x1080-0015.i420
+530c48d99fad9cddad22ee67ba4fd4d4  vp90-2-02-size-lf-1920x1080-1920x1080-0016.i420
+d55a6ebe71df8d47ac0f2b2f243f740a  vp90-2-02-size-lf-1920x1080-1920x1080-0017.i420
+aa84ff7d5dc665441376f8a75bd9bf05  vp90-2-02-size-lf-1920x1080-1920x1080-0018.i420
+70459811c09abf51e7e421656bff1939  vp90-2-02-size-lf-1920x1080-1920x1080-0019.i420
+bb69e3d69ef55a6d19506dd556168901  vp90-2-02-size-lf-1920x1080-1920x1080-0020.i420
+4f1daad761f0949509ffd9873ca03cd4  vp90-2-02-size-lf-1920x1080-1920x1080-0021.i420
+37a037e9de60b411701fda7706db37d6  vp90-2-02-size-lf-1920x1080-1920x1080-0022.i420
+09869838e806717791fe867b018d18ff  vp90-2-02-size-lf-1920x1080-1920x1080-0023.i420
+367385d264306ddd25231bb9f8681160  vp90-2-02-size-lf-1920x1080-1920x1080-0024.i420
+42c9da4939d435fcec3def2fa2bc5e26  vp90-2-02-size-lf-1920x1080-1920x1080-0025.i420
+26da302e6e86a632dfa8d8a78e83e269  vp90-2-02-size-lf-1920x1080-1920x1080-0026.i420
+8387287bfa4e62dd575941fab6f95f96  vp90-2-02-size-lf-1920x1080-1920x1080-0027.i420
+7fcc408015aed7f70c0c2321b61d166d  vp90-2-02-size-lf-1920x1080-1920x1080-0028.i420
+2394b1c14a156421cc7b30fa95c1a49b  vp90-2-02-size-lf-1920x1080-1920x1080-0029.i420
+34d91c69395380155f6f1020cda78bf9  vp90-2-02-size-lf-1920x1080-1920x1080-0030.i420
+3f081ccd624b2648b7fde66e23b05e1d  vp90-2-02-size-lf-1920x1080-1920x1080-0031.i420
+ca08738b7c81f2f10ea2f65bf5fd7876  vp90-2-02-size-lf-1920x1080-1920x1080-0032.i420
+f65c4dc7c172666ba3bb9bd402d5767c  vp90-2-02-size-lf-1920x1080-1920x1080-0033.i420
+d7ea91467fea6c268b6cd8da9067d12b  vp90-2-02-size-lf-1920x1080-1920x1080-0034.i420
+9888aa4a9b3ff09ada838b5ab0f1216c  vp90-2-02-size-lf-1920x1080-1920x1080-0035.i420
+015d788822a605d03877454c8ffd065a  vp90-2-02-size-lf-1920x1080-1920x1080-0036.i420
+d9d6a53eed5627764c107aafaa64d9a8  vp90-2-02-size-lf-1920x1080-1920x1080-0037.i420
+0b4a40dc0a6a1f5caf16ddd4dde26186  vp90-2-02-size-lf-1920x1080-1920x1080-0038.i420
+4a3f4c2e6d559a1a93b50e716dddf0bf  vp90-2-02-size-lf-1920x1080-1920x1080-0039.i420
+d10f631f4a15b6f1060233a6519eefcc  vp90-2-02-size-lf-1920x1080-1920x1080-0040.i420
+cc650873b637c244cb1415e39051d013  vp90-2-02-size-lf-1920x1080-1920x1080-0041.i420
+44a697f932e97b7f53a989e429fdca29  vp90-2-02-size-lf-1920x1080-1920x1080-0042.i420
+a09c7c567353412a36776398975fbe6a  vp90-2-02-size-lf-1920x1080-1920x1080-0043.i420
+49e3469e2b27fc776bcc0e146910ce2b  vp90-2-02-size-lf-1920x1080-1920x1080-0044.i420
+dd3261b098648b62fa0eab900b0056ba  vp90-2-02-size-lf-1920x1080-1920x1080-0045.i420
+853f90bb3e23e837ad0cb33106c2256f  vp90-2-02-size-lf-1920x1080-1920x1080-0046.i420
+0df1eadd74d643e029188f242af2f533  vp90-2-02-size-lf-1920x1080-1920x1080-0047.i420
+c1d3b56a0a622b176b81400421e87176  vp90-2-02-size-lf-1920x1080-1920x1080-0048.i420
+3c723084af1b727f78fdb9a0e5912a58  vp90-2-02-size-lf-1920x1080-1920x1080-0049.i420
+9806a519be5c399ae8c2b816772786ec  vp90-2-02-size-lf-1920x1080-1920x1080-0050.i420
+f25fd27140575595c5f944446e57e502  vp90-2-02-size-lf-1920x1080-1920x1080-0051.i420
+8c8e4f402372d76e2844794d2ddada43  vp90-2-02-size-lf-1920x1080-1920x1080-0052.i420
+c2cce3cc8291978008779f567e912361  vp90-2-02-size-lf-1920x1080-1920x1080-0053.i420
+d3d2819296938ded08b07b2206387afd  vp90-2-02-size-lf-1920x1080-1920x1080-0054.i420
+fce62f1e083bf305f966696617549fc8  vp90-2-02-size-lf-1920x1080-1920x1080-0055.i420
+70ccdb87e5d4458ab60fb6b7a263880f  vp90-2-02-size-lf-1920x1080-1920x1080-0056.i420
+a8def4b2a416924ac1a8933901e6cdee  vp90-2-02-size-lf-1920x1080-1920x1080-0057.i420
+a4f09f6e2f534716e0ab92c094cd0525  vp90-2-02-size-lf-1920x1080-1920x1080-0058.i420
+91e264c9da9dd14b631ef6483a458ead  vp90-2-02-size-lf-1920x1080-1920x1080-0059.i420
+8506e8b6033f50212c7a4fb751074667  vp90-2-02-size-lf-1920x1080-1920x1080-0060.i420
+eb14b107652f8f71ff06b1f73fbc8ec7  vp90-2-02-size-lf-1920x1080-1920x1080-0061.i420
+4684a67783e8663bdf275352108f4eef  vp90-2-02-size-lf-1920x1080-1920x1080-0062.i420
+9568285e9a9542f5a708a31e2e157c5b  vp90-2-02-size-lf-1920x1080-1920x1080-0063.i420
+b5349702a8cb8679a362ba8bc550bf7c  vp90-2-02-size-lf-1920x1080-1920x1080-0064.i420
+fb7920dc58fd81ddf221fc9031fbc19f  vp90-2-02-size-lf-1920x1080-1920x1080-0065.i420
+b8f752ad92003e481c94beb3b8599214  vp90-2-02-size-lf-1920x1080-1920x1080-0066.i420
+3d93fc99118832ac7c3897f3e9b3a82e  vp90-2-02-size-lf-1920x1080-1920x1080-0067.i420
+98003f945aa8ba7aae4d9f6255002f62  vp90-2-02-size-lf-1920x1080-1920x1080-0068.i420
+a18ff6d6fa7645f922de2f3ba4053f49  vp90-2-02-size-lf-1920x1080-1920x1080-0069.i420
+1232126ef24ff4787b11b32223d34018  vp90-2-02-size-lf-1920x1080-1920x1080-0070.i420
+a83f92c62e008939b3de91cdf9c1282f  vp90-2-02-size-lf-1920x1080-1920x1080-0071.i420
+cd47127ea0b864e5636222b40cdb5fbe  vp90-2-02-size-lf-1920x1080-1920x1080-0072.i420
+544233ce095abea8ffe427a603224ddd  vp90-2-02-size-lf-1920x1080-1920x1080-0073.i420
+7192883aca7eda74dd7e61d1cc6f6e2e  vp90-2-02-size-lf-1920x1080-1920x1080-0074.i420
+e8db34581dd264810ad683cd6475cf23  vp90-2-02-size-lf-1920x1080-1920x1080-0075.i420
+c215af24670915f3a123beb970ccba22  vp90-2-02-size-lf-1920x1080-1920x1080-0076.i420
+40d89931ddef819030a46d81e114f0b5  vp90-2-02-size-lf-1920x1080-1920x1080-0077.i420
+064781c2e9e9d564c9098be2aa5b6299  vp90-2-02-size-lf-1920x1080-1920x1080-0078.i420
+9ebab2d14446bdd11b62a6b308889b64  vp90-2-02-size-lf-1920x1080-1920x1080-0079.i420
+77ca0761cab449ea90bc8b1e1de5ae3a  vp90-2-02-size-lf-1920x1080-1920x1080-0080.i420
+74cb71b2755157dc7c1ef211b2346270  vp90-2-02-size-lf-1920x1080-1920x1080-0081.i420
+23ce88228df42b9e69ad3f4f25dd20cf  vp90-2-02-size-lf-1920x1080-1920x1080-0082.i420
+52ac5c9e14482dfde27ad838145c5986  vp90-2-02-size-lf-1920x1080-1920x1080-0083.i420
+929381d60199bb8c250324ca96323008  vp90-2-02-size-lf-1920x1080-1920x1080-0084.i420
+94f9ca3acbe3ed61bffec3f48e1dc43a  vp90-2-02-size-lf-1920x1080-1920x1080-0085.i420
+955a4095051cdf3699e5385396a04d69  vp90-2-02-size-lf-1920x1080-1920x1080-0086.i420
+dd784f3a18eae98cae4f795f854d6f03  vp90-2-02-size-lf-1920x1080-1920x1080-0087.i420
+1ebeb7d3d528292c8ae1b54b30692c81  vp90-2-02-size-lf-1920x1080-1920x1080-0088.i420
+f38b83c5b2827c4efddcb6777fd6cd5d  vp90-2-02-size-lf-1920x1080-1920x1080-0089.i420
+011dff2cf18e5b4bac6035edf57372d6  vp90-2-02-size-lf-1920x1080-1920x1080-0090.i420
+a1e8ae0f840b6aeddf283f44aa57262e  vp90-2-02-size-lf-1920x1080-1920x1080-0091.i420
+bf8f75c177756e4e8c8ad0d494b7921c  vp90-2-02-size-lf-1920x1080-1920x1080-0092.i420
+d3e9bf1a44f61e47a3d0f4ca04921a11  vp90-2-02-size-lf-1920x1080-1920x1080-0093.i420
+874f5b4db9dfdb78d9a654a9ce3da4ba  vp90-2-02-size-lf-1920x1080-1920x1080-0094.i420
+a8f7ef85e67a1b3c6c730565e0e1ab3e  vp90-2-02-size-lf-1920x1080-1920x1080-0095.i420
+33d6e20c9921719b4dcd9ccdcf242ebf  vp90-2-02-size-lf-1920x1080-1920x1080-0096.i420
+ee13704be5bb72bc91e05dc07154c8b4  vp90-2-02-size-lf-1920x1080-1920x1080-0097.i420
+8edfa18ab4a51243581302b7b12655c5  vp90-2-02-size-lf-1920x1080-1920x1080-0098.i420
+4d71c47f48e498c525b3a2907b4dad10  vp90-2-02-size-lf-1920x1080-1920x1080-0099.i420
+6de62f06881c7db2e37391f3928f9ac1  vp90-2-02-size-lf-1920x1080-1920x1080-0100.i420
+70f76a47c7ed5568ff4d21c53c58482e  vp90-2-02-size-lf-1920x1080-1920x1080-0101.i420
+e7faf1645e75a6d0927336c08a018a34  vp90-2-02-size-lf-1920x1080-1920x1080-0102.i420
+e206df8ed03f809e31f704863851ec77  vp90-2-02-size-lf-1920x1080-1920x1080-0103.i420
+03eb13cf9426514e58deeda33f4766d0  vp90-2-02-size-lf-1920x1080-1920x1080-0104.i420
+e06bc2064d306de26356f6d67c2bc21b  vp90-2-02-size-lf-1920x1080-1920x1080-0105.i420
+dd8a993039b6d9c78e2f03c7efcb4984  vp90-2-02-size-lf-1920x1080-1920x1080-0106.i420
+26cb793df8bc7f1ddcd9bd897e877ef0  vp90-2-02-size-lf-1920x1080-1920x1080-0107.i420
+7e3d32618b104c9c47d4464aa2df4709  vp90-2-02-size-lf-1920x1080-1920x1080-0108.i420
+64b1e12d7b87decd877e6c23ffd275d7  vp90-2-02-size-lf-1920x1080-1920x1080-0109.i420
+323ddc3a19c198f7768dacaf6faad602  vp90-2-02-size-lf-1920x1080-1920x1080-0110.i420
+126d984b9bdaf3397ea4ebec52775e7f  vp90-2-02-size-lf-1920x1080-1920x1080-0111.i420
+76a4586be73d0401c339790c1045abab  vp90-2-02-size-lf-1920x1080-1920x1080-0112.i420
+68466c976fb0309ada2cc7bc514c7d78  vp90-2-02-size-lf-1920x1080-1920x1080-0113.i420
+38135b5505f21ec8d23f97cb29ef1161  vp90-2-02-size-lf-1920x1080-1920x1080-0114.i420
+d657d27a111e9d81b1fbedc7f9c035c9  vp90-2-02-size-lf-1920x1080-1920x1080-0115.i420
+f399d1dc319f560206f09ca5fb59c837  vp90-2-02-size-lf-1920x1080-1920x1080-0116.i420
+269b8a8582e28e11ca3d21dc0f4dc2a6  vp90-2-02-size-lf-1920x1080-1920x1080-0117.i420
+3550fd48042d272f051bb4a6fc76c9df  vp90-2-02-size-lf-1920x1080-1920x1080-0118.i420
+5be1f4ed7eea3b62d6c55003ded2906a  vp90-2-02-size-lf-1920x1080-1920x1080-0119.i420
+7c607aade4b3451f9a081367584ae5f7  vp90-2-02-size-lf-1920x1080-1920x1080-0120.i420
+a724b1ee8504955503aca7af81425008  vp90-2-02-size-lf-1920x1080-1920x1080-0121.i420
+f58ea230bd73fa111982093742f22055  vp90-2-02-size-lf-1920x1080-1920x1080-0122.i420
+8ad4a70efa7bbc936049de2cd5b973b8  vp90-2-02-size-lf-1920x1080-1920x1080-0123.i420
+4ecbe738e3d31d546332ae248e6ba075  vp90-2-02-size-lf-1920x1080-1920x1080-0124.i420
+507a6fe3e6c95dfec41950382ed49f0e  vp90-2-02-size-lf-1920x1080-1920x1080-0125.i420
+833dc6d11dbfc1fa8465b292a66afa32  vp90-2-02-size-lf-1920x1080-1920x1080-0126.i420
+0ac2d4983e91ba36a69d11ae9a32f31a  vp90-2-02-size-lf-1920x1080-1920x1080-0127.i420
+0e61c144b842d46b7f63f433dc7be802  vp90-2-02-size-lf-1920x1080-1920x1080-0128.i420
+e93dc18eddef0a93ba652ed898fc4898  vp90-2-02-size-lf-1920x1080-1920x1080-0129.i420
+6745736a1f8ce3dae8532a007023ac6a  vp90-2-02-size-lf-1920x1080-1920x1080-0130.i420
+75f9739dc3e003fdb356221a5654c0e4  vp90-2-02-size-lf-1920x1080-1920x1080-0131.i420
+d189cf9fffb8118f31a294deab61585a  vp90-2-02-size-lf-1920x1080-1920x1080-0132.i420
+2738879f462aca9015e212e644420b7b  vp90-2-02-size-lf-1920x1080-1920x1080-0133.i420
+eff4b276b3c4f454b0822ae4f8d88a0b  vp90-2-02-size-lf-1920x1080-1920x1080-0134.i420
+2e461ae7d93bb4cfd4e072a35b651d17  vp90-2-02-size-lf-1920x1080-1920x1080-0135.i420
+bf9a82ea0e3628e4fd1eeb03cb1f50bc  vp90-2-02-size-lf-1920x1080-1920x1080-0136.i420
+c8dff3e50d37f9e1ce8b92a0762c57be  vp90-2-02-size-lf-1920x1080-1920x1080-0137.i420
+51e6f9efc88a795de0a4d16a6a71d497  vp90-2-02-size-lf-1920x1080-1920x1080-0138.i420
+761b5005e7f8ab8185ccedb660ded250  vp90-2-02-size-lf-1920x1080-1920x1080-0139.i420
+f98da0c03436b1c759d368b9d42db679  vp90-2-02-size-lf-1920x1080-1920x1080-0140.i420
+dec3590e5c11737670703e73ed69783f  vp90-2-02-size-lf-1920x1080-1920x1080-0141.i420
+0481f4aec0c9eafb3f9a10cf80c0b056  vp90-2-02-size-lf-1920x1080-1920x1080-0142.i420
+67478cb1e4de699d529046f983105477  vp90-2-02-size-lf-1920x1080-1920x1080-0143.i420
+80f371f7fa43cab698b832a4010e5a88  vp90-2-02-size-lf-1920x1080-1920x1080-0144.i420
+4e9095ab5204a387f63118949bb90f9e  vp90-2-02-size-lf-1920x1080-1920x1080-0145.i420
+f943ce3342b90b01fabd3d5bc779bb01  vp90-2-02-size-lf-1920x1080-1920x1080-0146.i420
+1b12d49c5685111fa4faa8edc8b683ad  vp90-2-02-size-lf-1920x1080-1920x1080-0147.i420
+8ee848ae53f7b86a254e49562bbfe849  vp90-2-02-size-lf-1920x1080-1920x1080-0148.i420
+2d83c434c41329ae3a8b56c10a27f2e7  vp90-2-02-size-lf-1920x1080-1920x1080-0149.i420
+af6a63fc13b919dabedd86db735990f3  vp90-2-02-size-lf-1920x1080-1920x1080-0150.i420
+a807fce07a52227202dcdcbbfb4eb1bc  vp90-2-02-size-lf-1920x1080-1920x1080-0151.i420
+95aebea323577226684914c6b74830c5  vp90-2-02-size-lf-1920x1080-1920x1080-0152.i420
+65d64ebdaadb116608f06add0e8fada2  vp90-2-02-size-lf-1920x1080-1920x1080-0153.i420
+b064af776f8c562ea6b41e0c74710869  vp90-2-02-size-lf-1920x1080-1920x1080-0154.i420
+26291594af160501023eb0035443b7c3  vp90-2-02-size-lf-1920x1080-1920x1080-0155.i420
+79a414d560d3e36314c981f1e30e053b  vp90-2-02-size-lf-1920x1080-1920x1080-0156.i420
+3455e01e2cd146aefbad54cb032b15f1  vp90-2-02-size-lf-1920x1080-1920x1080-0157.i420
+eaa2e271058202cbc0933dea8f46f570  vp90-2-02-size-lf-1920x1080-1920x1080-0158.i420
+42da27c94aaa56ae27fddf75bf51f47f  vp90-2-02-size-lf-1920x1080-1920x1080-0159.i420
+746cca013c7b6df41e3233214ca7a5d7  vp90-2-02-size-lf-1920x1080-1920x1080-0160.i420
+ab20ad95d6b3e0d689186cde51e4a86a  vp90-2-02-size-lf-1920x1080-1920x1080-0161.i420
+b8a02e44615a697da3de946e8cf4e8e4  vp90-2-02-size-lf-1920x1080-1920x1080-0162.i420
+4df5b10cb1c784362035f69bdb183be0  vp90-2-02-size-lf-1920x1080-1920x1080-0163.i420
+f2e5dd616e8125b1b46c410141180fb0  vp90-2-02-size-lf-1920x1080-1920x1080-0164.i420
+e09ab4ca180cb477a3a87bc8fd1e2ce0  vp90-2-02-size-lf-1920x1080-1920x1080-0165.i420
+5ee431b26d6c83689bf18eb8d805f31e  vp90-2-02-size-lf-1920x1080-1920x1080-0166.i420
+bca8aaf030c959ac37c3e084be6cf8b3  vp90-2-02-size-lf-1920x1080-1920x1080-0167.i420
+8dd977323d8a5dba5c98c6671821e066  vp90-2-02-size-lf-1920x1080-1920x1080-0168.i420
+aed8ef2c20f9726542c78fade0fb0968  vp90-2-02-size-lf-1920x1080-1920x1080-0169.i420
+e19775ba9c5b6dbf1e84fd0531bd1f2a  vp90-2-02-size-lf-1920x1080-1920x1080-0170.i420
+a69c5daf6e6e3b579a3430fc95f37dac  vp90-2-02-size-lf-1920x1080-1920x1080-0171.i420
+3503bc793f86b75d9aa1c9c51b2d0f6f  vp90-2-02-size-lf-1920x1080-1920x1080-0172.i420
+bdcee02e245b92acf06588370df2e5e6  vp90-2-02-size-lf-1920x1080-1920x1080-0173.i420
+8bbb9460d0f419969491669664891d88  vp90-2-02-size-lf-1920x1080-1920x1080-0174.i420
+d4b993d87c2f4042c0b647e4e50cca38  vp90-2-02-size-lf-1920x1080-1920x1080-0175.i420
+5acb9f10167b208a32babbe56fd07587  vp90-2-02-size-lf-1920x1080-1920x1080-0176.i420
+958900bb713559d272470f1e85cffcda  vp90-2-02-size-lf-1920x1080-1920x1080-0177.i420
+f355f1858fd2c8a4932dfd6d6cfe7673  vp90-2-02-size-lf-1920x1080-1920x1080-0178.i420
+45caac733e395f63c82c9d8ab050c858  vp90-2-02-size-lf-1920x1080-1920x1080-0179.i420
+8b05c2c352c4adc5cabc0184a1f510f5  vp90-2-02-size-lf-1920x1080-1920x1080-0180.i420
+167c3fe4df204bab9cceb17ae655aa61  vp90-2-02-size-lf-1920x1080-1920x1080-0181.i420
+3859339e9a63d0e05797f0de535f7be8  vp90-2-02-size-lf-1920x1080-1920x1080-0182.i420
+2d5cc539454cb6aace19ab9bba60b066  vp90-2-02-size-lf-1920x1080-1920x1080-0183.i420
+f51299a0601fb1621d2de6b0e2391a9a  vp90-2-02-size-lf-1920x1080-1920x1080-0184.i420
+92b0ed2528c0756b0c84721a306ba61b  vp90-2-02-size-lf-1920x1080-1920x1080-0185.i420
+8f1870cce38718b02d0a4e26a5a2619e  vp90-2-02-size-lf-1920x1080-1920x1080-0186.i420
+e0ed74a244b8698baaefd837ab1590ff  vp90-2-02-size-lf-1920x1080-1920x1080-0187.i420
+c8b10e2ac68bd0106e34a57943f23e12  vp90-2-02-size-lf-1920x1080-1920x1080-0188.i420
+f5e505e3d681763fd447214aed863ab9  vp90-2-02-size-lf-1920x1080-1920x1080-0189.i420
+c2cc70d65ba1c13c5e07a1d28611792a  vp90-2-02-size-lf-1920x1080-1920x1080-0190.i420
+e518aac5c551f7c09652c25905cce41f  vp90-2-02-size-lf-1920x1080-1920x1080-0191.i420
+66379f7a3b2de153486a76b459e2ce3b  vp90-2-02-size-lf-1920x1080-1920x1080-0192.i420
+552afad8181d6d138e2e62c971a10a42  vp90-2-02-size-lf-1920x1080-1920x1080-0193.i420
+ac21d5c2ef3ccaabbaa9f08fcc9d0db8  vp90-2-02-size-lf-1920x1080-1920x1080-0194.i420
+f67af966e3fa79a6fce48b7d9e1fb593  vp90-2-02-size-lf-1920x1080-1920x1080-0195.i420
+dd6331e4361f8b8bd45d571db2e0344b  vp90-2-02-size-lf-1920x1080-1920x1080-0196.i420
+14a0db3c0a39b7431c337622ed4078a5  vp90-2-02-size-lf-1920x1080-1920x1080-0197.i420
+8d3394abad260b5e4e24abe4a898cb7b  vp90-2-02-size-lf-1920x1080-1920x1080-0198.i420
+e085ce3274d77fa874ab70183353b4c1  vp90-2-02-size-lf-1920x1080-1920x1080-0199.i420
+de083fffb4226ec227d3aa9c873dfcf7  vp90-2-02-size-lf-1920x1080-1920x1080-0200.i420
+4628eff51846a97fb708c4d3753ffee4  vp90-2-02-size-lf-1920x1080-1920x1080-0201.i420
+b480e4409fa8ca9c2e0d4bd57b7e8cf6  vp90-2-02-size-lf-1920x1080-1920x1080-0202.i420
+ff21164cc573b6f79739165b61b68dd0  vp90-2-02-size-lf-1920x1080-1920x1080-0203.i420
+ec391026b77527ed48029adfbd1afc93  vp90-2-02-size-lf-1920x1080-1920x1080-0204.i420
+23186dd93e32603c3709aa3419963ca9  vp90-2-02-size-lf-1920x1080-1920x1080-0205.i420
+6a1968207b37594cc82736f086a0a023  vp90-2-02-size-lf-1920x1080-1920x1080-0206.i420
+57358a332af03e5d96d8c1cd5e4a497d  vp90-2-02-size-lf-1920x1080-1920x1080-0207.i420
+584ac2ecc56e1a9f0f1a5356b161a7a6  vp90-2-02-size-lf-1920x1080-1920x1080-0208.i420
+f566d1e385f25ef9b74989cbe7bbca7b  vp90-2-02-size-lf-1920x1080-1920x1080-0209.i420
+a4bf059ee8207d1edeebc3193e8db8e0  vp90-2-02-size-lf-1920x1080-1920x1080-0210.i420
+cc5948fa18d6e73afa253eedbfaecd41  vp90-2-02-size-lf-1920x1080-1920x1080-0211.i420
+61d44c8bfca18b6742fed974366898b8  vp90-2-02-size-lf-1920x1080-1920x1080-0212.i420
+c48d67da0d72daaf635226b9e30e05e3  vp90-2-02-size-lf-1920x1080-1920x1080-0213.i420
+b4596a68e708f304875fd2306fec56e9  vp90-2-02-size-lf-1920x1080-1920x1080-0214.i420
+b59be425ebea3d15b4be140e552ab944  vp90-2-02-size-lf-1920x1080-1920x1080-0215.i420
+1e966f137918375ae060d4c49cf38664  vp90-2-02-size-lf-1920x1080-1920x1080-0216.i420
+0ff25f8e98719fd57dc31d391bb930c4  vp90-2-02-size-lf-1920x1080-1920x1080-0217.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_deltaq.vp9 b/tests/tests/media/res/raw/vp90_2_03_deltaq.vp9
new file mode 100644
index 0000000..9033b23
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_deltaq.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_deltaq_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_deltaq_vp9_md5
new file mode 100644
index 0000000..aca350c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_deltaq_vp9_md5
@@ -0,0 +1,2 @@
+2f90d606edc511c8c960530dd915cb98  vp90-2-03-deltaq-352x240-0001.i420
+7fd451a057d6341b2b0d116f59e41a13  vp90-2-03-deltaq-352x240-0002.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x196.vp9
new file mode 100644
index 0000000..06988f1
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x196_vp9_md5
new file mode 100644
index 0000000..847972f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x196_vp9_md5
@@ -0,0 +1,10 @@
+14cc1c34b8106e35238d4650a9123852  vp90-2-03-size-196x196-196x196-0001.i420
+66e0bb9136ea24e30b781a4610b428a1  vp90-2-03-size-196x196-196x196-0002.i420
+8e36679c20a3a3e974fdacf7a9343817  vp90-2-03-size-196x196-196x196-0003.i420
+2669fd03ce7ce01f4fc9db23e06fffdb  vp90-2-03-size-196x196-196x196-0004.i420
+46ced29eb6edf2136c8ee19e9a87380f  vp90-2-03-size-196x196-196x196-0005.i420
+4e4138b65a30bc56cd18663a1799f98f  vp90-2-03-size-196x196-196x196-0006.i420
+580b0431b5f808c67e50ed34e62f39ad  vp90-2-03-size-196x196-196x196-0007.i420
+1339bbe256d8499ab17d6a550f7dac70  vp90-2-03-size-196x196-196x196-0008.i420
+89b9dac29a4c4136249c40a3763dc114  vp90-2-03-size-196x196-196x196-0009.i420
+a735d341d7df9dcd0b6e51a82b813f61  vp90-2-03-size-196x196-196x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x198.vp9
new file mode 100644
index 0000000..cffe250
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x198_vp9_md5
new file mode 100644
index 0000000..33056c5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x198_vp9_md5
@@ -0,0 +1,10 @@
+d2bd2dfaf2ac22b3f2499844f228d89a  vp90-2-03-size-196x198-196x198-0001.i420
+e066448baeb39da04b22d4d2ebd27b0a  vp90-2-03-size-196x198-196x198-0002.i420
+aace53c0ecca2596c51dd5e70da7abc4  vp90-2-03-size-196x198-196x198-0003.i420
+077256d024ab101918d10ae61142f203  vp90-2-03-size-196x198-196x198-0004.i420
+e2bfdad36b0365d41dc6813a371111ee  vp90-2-03-size-196x198-196x198-0005.i420
+17495af68b0a2c075899849382f3b046  vp90-2-03-size-196x198-196x198-0006.i420
+7853db163344798e5c37672adaac92d8  vp90-2-03-size-196x198-196x198-0007.i420
+7b2ee2e1ca709c58457c7d818e47c95c  vp90-2-03-size-196x198-196x198-0008.i420
+f7eb3ce10561628f932861358a30b414  vp90-2-03-size-196x198-196x198-0009.i420
+3182374f5aa539fd0faa44ed4a7492e5  vp90-2-03-size-196x198-196x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x200.vp9
new file mode 100644
index 0000000..53e2c03
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x200_vp9_md5
new file mode 100644
index 0000000..7746aba
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x200_vp9_md5
@@ -0,0 +1,10 @@
+b2f2ac3e3833ae1b4dd075fe00210373  vp90-2-03-size-196x200-196x200-0001.i420
+c0cce05e56a07111fe62553fa3a87074  vp90-2-03-size-196x200-196x200-0002.i420
+626aab3de03242073e03504e166b4697  vp90-2-03-size-196x200-196x200-0003.i420
+574d2c810f0bbfac57f1f06c2b97445c  vp90-2-03-size-196x200-196x200-0004.i420
+7d5bc5860bd1422d08396fe080452099  vp90-2-03-size-196x200-196x200-0005.i420
+5d47bbfb0f5cdecfe8415ca2caddc206  vp90-2-03-size-196x200-196x200-0006.i420
+fbef6a0fa51029d0475975945ccf4b36  vp90-2-03-size-196x200-196x200-0007.i420
+c9179c153bcb2a8e9d17ed04e5e2c39c  vp90-2-03-size-196x200-196x200-0008.i420
+107d796592cf2140d4d492beadba2d68  vp90-2-03-size-196x200-196x200-0009.i420
+eee46f9ee67fc1121bffb63aeb7c768f  vp90-2-03-size-196x200-196x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x202.vp9
new file mode 100644
index 0000000..87394bd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x202_vp9_md5
new file mode 100644
index 0000000..351cf95
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x202_vp9_md5
@@ -0,0 +1,10 @@
+7109d2ef160828ece26337f36fcfc092  vp90-2-03-size-196x202-196x202-0001.i420
+bdaa6612f81a956d9b20d55a04df8346  vp90-2-03-size-196x202-196x202-0002.i420
+15eb75495d2713a64415b990b058d5ca  vp90-2-03-size-196x202-196x202-0003.i420
+b997c84553475ba84e8ba3d7ee19ae4e  vp90-2-03-size-196x202-196x202-0004.i420
+63a8badd691bcf643cf676d029ce8a6c  vp90-2-03-size-196x202-196x202-0005.i420
+b8ca23d9b3418c4c36040a215b2b7917  vp90-2-03-size-196x202-196x202-0006.i420
+1be0da18386c35e4a5e5d5d32d9a4468  vp90-2-03-size-196x202-196x202-0007.i420
+e75a03fa70fe7e6b3a8d8ce7dc8305f1  vp90-2-03-size-196x202-196x202-0008.i420
+cbd2b60df9209025c8e890771a05321d  vp90-2-03-size-196x202-196x202-0009.i420
+c655d6fcc3333917b66358a9ac2b1357  vp90-2-03-size-196x202-196x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x208.vp9
new file mode 100644
index 0000000..d20e7cc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x208_vp9_md5
new file mode 100644
index 0000000..94a9277
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x208_vp9_md5
@@ -0,0 +1,10 @@
+efa2a2a76a0fe709a78e491346cfcf29  vp90-2-03-size-196x208-196x208-0001.i420
+97de85e21b408878853fa870104707d7  vp90-2-03-size-196x208-196x208-0002.i420
+419bd1157e156d3059190d6b561c57dd  vp90-2-03-size-196x208-196x208-0003.i420
+fbb6e01c524fc7c8007c6cfe2c64f467  vp90-2-03-size-196x208-196x208-0004.i420
+7453994c2e9901fa23f295ec0b556f9c  vp90-2-03-size-196x208-196x208-0005.i420
+ba39dc984789fa2c4b833cd88013cc97  vp90-2-03-size-196x208-196x208-0006.i420
+cea5061cac1be18d5f9a9301a5460491  vp90-2-03-size-196x208-196x208-0007.i420
+1c583018c425b1a91949e0c3eb0a4152  vp90-2-03-size-196x208-196x208-0008.i420
+b48be02280ac6f97731af69bcf18de25  vp90-2-03-size-196x208-196x208-0009.i420
+6f8ab465214d8374c9ff77b939da333e  vp90-2-03-size-196x208-196x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x210.vp9
new file mode 100644
index 0000000..c1dfbb3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x210_vp9_md5
new file mode 100644
index 0000000..eddddaf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x210_vp9_md5
@@ -0,0 +1,10 @@
+fccc18714a9ed3840bd6e9c6ca4858e5  vp90-2-03-size-196x210-196x210-0001.i420
+a8f6eb43cf6ed670eb180c5051de06f7  vp90-2-03-size-196x210-196x210-0002.i420
+6a9baf9eae6e799deaefd6e801f7ace3  vp90-2-03-size-196x210-196x210-0003.i420
+3bb44c8a45aab088c9887c11bc6a4acf  vp90-2-03-size-196x210-196x210-0004.i420
+0907a7e926be9e54bbb087251b4715d9  vp90-2-03-size-196x210-196x210-0005.i420
+10fef2876c20eb3f9570c0c23e5acc69  vp90-2-03-size-196x210-196x210-0006.i420
+ffe5d2b6d874af0f878075c97940ccfb  vp90-2-03-size-196x210-196x210-0007.i420
+d10fae10144ff88075048827203f7e9c  vp90-2-03-size-196x210-196x210-0008.i420
+bdf35736ac625f2178902c1f24d513c0  vp90-2-03-size-196x210-196x210-0009.i420
+30882bf2c21785be6234b637c4b16b28  vp90-2-03-size-196x210-196x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x224.vp9
new file mode 100644
index 0000000..605dddf
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x224_vp9_md5
new file mode 100644
index 0000000..18395ce
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x224_vp9_md5
@@ -0,0 +1,10 @@
+13263674ea5aa619250dfd139bda872f  vp90-2-03-size-196x224-196x224-0001.i420
+39f5cbd8917f2b3a1df8cf2b786266de  vp90-2-03-size-196x224-196x224-0002.i420
+f9aade31f9e3065f3d5b8645ef099ac6  vp90-2-03-size-196x224-196x224-0003.i420
+124f9664380f092e692b5e881f5a8fcc  vp90-2-03-size-196x224-196x224-0004.i420
+e8e040e417830f5e911537828ace21b7  vp90-2-03-size-196x224-196x224-0005.i420
+84ce09882b9c184a787e8022e6d8c8de  vp90-2-03-size-196x224-196x224-0006.i420
+b1397fd91814e4fdc4f75c89161ced26  vp90-2-03-size-196x224-196x224-0007.i420
+d64f39d64d248f0223ed359e092d46cb  vp90-2-03-size-196x224-196x224-0008.i420
+e04ee663dcc52eebd74255671c6f4ec9  vp90-2-03-size-196x224-196x224-0009.i420
+955303cb73bf072c693f37d9778ca2b6  vp90-2-03-size-196x224-196x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_196x226.vp9
new file mode 100644
index 0000000..29f7381
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_196x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_196x226_vp9_md5
new file mode 100644
index 0000000..1c250d6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_196x226_vp9_md5
@@ -0,0 +1,10 @@
+5cb240f10761f59687612ed589759800  vp90-2-03-size-196x226-196x226-0001.i420
+9d8d5b57336ddfa5c9c5100a0302197d  vp90-2-03-size-196x226-196x226-0002.i420
+9db74997d23b16f527c63e88795331dc  vp90-2-03-size-196x226-196x226-0003.i420
+52758cd901533e790334d464bee516da  vp90-2-03-size-196x226-196x226-0004.i420
+40e671b9b85d07b13acba85eb64bbbaa  vp90-2-03-size-196x226-196x226-0005.i420
+8524b2cd2c9bb3e41c6167f8269e75d2  vp90-2-03-size-196x226-196x226-0006.i420
+ff194ad6fa180fde86cc05a99c0580ec  vp90-2-03-size-196x226-196x226-0007.i420
+22ab303cb37745a73c227cd7d1c70003  vp90-2-03-size-196x226-196x226-0008.i420
+01986c58e82e0b5194418f5b75a8599c  vp90-2-03-size-196x226-196x226-0009.i420
+eedfc9c14cbf3fa10402dbed52103848  vp90-2-03-size-196x226-196x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x196.vp9
new file mode 100644
index 0000000..78d6b72
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x196_vp9_md5
new file mode 100644
index 0000000..fc8de27
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x196_vp9_md5
@@ -0,0 +1,10 @@
+c980866a6f17d4107ce128ee112d74cf  vp90-2-03-size-198x196-198x196-0001.i420
+d4d5d2a10e73f1d09919355dc4d63d48  vp90-2-03-size-198x196-198x196-0002.i420
+82c76ed020acb68ff9d8bd81899aa6f8  vp90-2-03-size-198x196-198x196-0003.i420
+8330705fa354fb5838af56dcf9cc0980  vp90-2-03-size-198x196-198x196-0004.i420
+e47b63d839a592e6372d18249bf5bc0c  vp90-2-03-size-198x196-198x196-0005.i420
+b6095b6f752a50e96cab52e7c3fd52f3  vp90-2-03-size-198x196-198x196-0006.i420
+fc4786f48b6ee31043d94f79c5c8a54f  vp90-2-03-size-198x196-198x196-0007.i420
+7d3d06c96496bd5ab44fe5489877771d  vp90-2-03-size-198x196-198x196-0008.i420
+5b96de089a9faa2dc01697fe9dd97f7f  vp90-2-03-size-198x196-198x196-0009.i420
+d7361203b4c264067dcb7bf6912e8df2  vp90-2-03-size-198x196-198x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x198.vp9
new file mode 100644
index 0000000..b66e0d8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x198_vp9_md5
new file mode 100644
index 0000000..7eae1b0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x198_vp9_md5
@@ -0,0 +1,10 @@
+ee0760611da9938e72f551d219671c76  vp90-2-03-size-198x198-198x198-0001.i420
+c512cb8a864c25318254438c7170f373  vp90-2-03-size-198x198-198x198-0002.i420
+aaea10aeb7dfd1f9f6dc77adccfcd56f  vp90-2-03-size-198x198-198x198-0003.i420
+fb4e68ce202d9c6ecbddc6fe50b1cd7b  vp90-2-03-size-198x198-198x198-0004.i420
+57a803d02f0d71ec4c3c17a112574525  vp90-2-03-size-198x198-198x198-0005.i420
+526d0beaf7ef721c3a6ae8bf3505fd78  vp90-2-03-size-198x198-198x198-0006.i420
+972ab31f81dbb79c2273bcfc98569e8b  vp90-2-03-size-198x198-198x198-0007.i420
+e1f05d62691bd1a9494d57449417415c  vp90-2-03-size-198x198-198x198-0008.i420
+bc39a559b25e5a1ac698e0101bd6bf29  vp90-2-03-size-198x198-198x198-0009.i420
+04caed04ac21c76af873e21899860fb2  vp90-2-03-size-198x198-198x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x200.vp9
new file mode 100644
index 0000000..5f6d62e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x200_vp9_md5
new file mode 100644
index 0000000..777aeef
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x200_vp9_md5
@@ -0,0 +1,10 @@
+fb0e8171b0f91d9b2ceb5430db27a67b  vp90-2-03-size-198x200-198x200-0001.i420
+73f121e6aa0e6290cfd06ac9b033c772  vp90-2-03-size-198x200-198x200-0002.i420
+4113897efc44f49f5169a579bee03596  vp90-2-03-size-198x200-198x200-0003.i420
+aec1d4cf1a15e12b689980cfe136d5d6  vp90-2-03-size-198x200-198x200-0004.i420
+1322af65f647254330120e67ddae38bd  vp90-2-03-size-198x200-198x200-0005.i420
+5d28c1684451812c9db41433e6286d85  vp90-2-03-size-198x200-198x200-0006.i420
+33843fc49d1d8655520c2f42332222ca  vp90-2-03-size-198x200-198x200-0007.i420
+92a8125d8c75eaf6159d5f431c5c71bf  vp90-2-03-size-198x200-198x200-0008.i420
+5bc96553842f65a3e37f012b72b580f5  vp90-2-03-size-198x200-198x200-0009.i420
+de5eb6299ee5034dc3b01cdc94bf810a  vp90-2-03-size-198x200-198x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x202.vp9
new file mode 100644
index 0000000..89f03df
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x202_vp9_md5
new file mode 100644
index 0000000..a5eef00
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x202_vp9_md5
@@ -0,0 +1,10 @@
+f5e1cf4cc56742fadddf42189a3f65e3  vp90-2-03-size-198x202-198x202-0001.i420
+f3e8ca2c8deb29a6b5bfe415b39c901e  vp90-2-03-size-198x202-198x202-0002.i420
+89c513049e41e145bca46a7f7119567c  vp90-2-03-size-198x202-198x202-0003.i420
+419089035739e84f1aa14ccdf34edcb1  vp90-2-03-size-198x202-198x202-0004.i420
+4962c98c23b16b9257869a8ad5138731  vp90-2-03-size-198x202-198x202-0005.i420
+fde9e858ec895c36c2d8071e69f68db6  vp90-2-03-size-198x202-198x202-0006.i420
+42e1271915f31a00be3627fa866ce3ee  vp90-2-03-size-198x202-198x202-0007.i420
+c15f794933f913861a6d0041ff2fccdb  vp90-2-03-size-198x202-198x202-0008.i420
+35dab245ba952dc6fddc1a9668c30b28  vp90-2-03-size-198x202-198x202-0009.i420
+30bb4ef77cdde9cf5aea0f1287183b23  vp90-2-03-size-198x202-198x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x208.vp9
new file mode 100644
index 0000000..49eca9f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x208_vp9_md5
new file mode 100644
index 0000000..eccf93d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x208_vp9_md5
@@ -0,0 +1,10 @@
+d45b561f81cbfcca8a1dddbc2bf8ca31  vp90-2-03-size-198x208-198x208-0001.i420
+3664f63b2e59e380622caadb7a05545e  vp90-2-03-size-198x208-198x208-0002.i420
+0662fa199512320704efecc10af1aaa4  vp90-2-03-size-198x208-198x208-0003.i420
+d8dc00882e73be89d0585663892cbcff  vp90-2-03-size-198x208-198x208-0004.i420
+ff64b8d50b7c5b484a06dab09a26147c  vp90-2-03-size-198x208-198x208-0005.i420
+1771b6a55112eb7ea10885d1390339cc  vp90-2-03-size-198x208-198x208-0006.i420
+0d5944e8a13e3c2faffb562bbe2671a8  vp90-2-03-size-198x208-198x208-0007.i420
+744bed3a88407b75a8ff27a1b0cec64e  vp90-2-03-size-198x208-198x208-0008.i420
+3887415f2ab10d2a265c4a413e7060b9  vp90-2-03-size-198x208-198x208-0009.i420
+7dd683019b19b464bc0436f41e0b7c87  vp90-2-03-size-198x208-198x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x210.vp9
new file mode 100644
index 0000000..97dfd89
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x210_vp9_md5
new file mode 100644
index 0000000..0c19c2f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x210_vp9_md5
@@ -0,0 +1,10 @@
+8525a27170982c059d5904c1af3b43fb  vp90-2-03-size-198x210-198x210-0001.i420
+c4eb329733913360384d3917a58f6f36  vp90-2-03-size-198x210-198x210-0002.i420
+ec118b87c9cba0e4bd89fd43567cca4e  vp90-2-03-size-198x210-198x210-0003.i420
+7e57c6caba7924823977e2c9bc11f7fa  vp90-2-03-size-198x210-198x210-0004.i420
+f77ffb7228a5eda848acc40ff636ecad  vp90-2-03-size-198x210-198x210-0005.i420
+c5dddafbe3badcbbcaaebe97076e0394  vp90-2-03-size-198x210-198x210-0006.i420
+34d69ae2e5b4c4fbcc51627237c9abc5  vp90-2-03-size-198x210-198x210-0007.i420
+d9c63fa8b18d6c54e5fa31db866c06cc  vp90-2-03-size-198x210-198x210-0008.i420
+7ab392764a399328bf35977539e3148a  vp90-2-03-size-198x210-198x210-0009.i420
+7fbb7bae3ec775298aaa49a286dfb9d1  vp90-2-03-size-198x210-198x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x224.vp9
new file mode 100644
index 0000000..360ab98
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x224_vp9_md5
new file mode 100644
index 0000000..12c6979
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x224_vp9_md5
@@ -0,0 +1,10 @@
+5f69230bfd8bb485bd85552b18339fc0  vp90-2-03-size-198x224-198x224-0001.i420
+f5c365774fc1d0bffd5025ce2e931aaf  vp90-2-03-size-198x224-198x224-0002.i420
+2898234103c3624e6470ae82c916e000  vp90-2-03-size-198x224-198x224-0003.i420
+d82a7fa705180b68a8ee8cb7de0cdd2d  vp90-2-03-size-198x224-198x224-0004.i420
+144a162d418deae62883a2cc4c341b4c  vp90-2-03-size-198x224-198x224-0005.i420
+b3419a48385e42ca15717289ff2daa1c  vp90-2-03-size-198x224-198x224-0006.i420
+d6306b5737f88f989bf2e6a1084a94fe  vp90-2-03-size-198x224-198x224-0007.i420
+5669761d7417b52b3cf81d44a13e3fb7  vp90-2-03-size-198x224-198x224-0008.i420
+3f730b8658d7a6657d1af38c75357512  vp90-2-03-size-198x224-198x224-0009.i420
+27df68d515148f732325bf821037d59f  vp90-2-03-size-198x224-198x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_198x226.vp9
new file mode 100644
index 0000000..c4d1a7c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_198x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_198x226_vp9_md5
new file mode 100644
index 0000000..31305ef
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_198x226_vp9_md5
@@ -0,0 +1,10 @@
+412c33a8fd71c99e68e6701b050b107c  vp90-2-03-size-198x226-198x226-0001.i420
+8e69483ff8a094096dd550b30be20dde  vp90-2-03-size-198x226-198x226-0002.i420
+b8df87ab3d2613be31a3743e34d7e794  vp90-2-03-size-198x226-198x226-0003.i420
+ec4b08a4014950f1fe04e83f8a790af0  vp90-2-03-size-198x226-198x226-0004.i420
+030da2b60627d879730108826ce6632c  vp90-2-03-size-198x226-198x226-0005.i420
+03aab0c9b4d75bc0b47fa5237e9efe3d  vp90-2-03-size-198x226-198x226-0006.i420
+fd01e369df258f340eb8e486c07ae136  vp90-2-03-size-198x226-198x226-0007.i420
+1c301f0e60c96008fd7b6e8de1ebaa29  vp90-2-03-size-198x226-198x226-0008.i420
+912723f43b2b36366c3e6ab122d31801  vp90-2-03-size-198x226-198x226-0009.i420
+b2774a66f7aa0fb7dd7e64b0d67818cd  vp90-2-03-size-198x226-198x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x196.vp9
new file mode 100644
index 0000000..2d8ea87
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x196_vp9_md5
new file mode 100644
index 0000000..0b38c2b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x196_vp9_md5
@@ -0,0 +1,10 @@
+651a0627c6cdaee8b46e1f8c4121a368  vp90-2-03-size-200x196-200x196-0001.i420
+3e63075148df16f69c933cf6c63e078c  vp90-2-03-size-200x196-200x196-0002.i420
+edf18e52b7d52af2bb7594ed358542d8  vp90-2-03-size-200x196-200x196-0003.i420
+30284124756d00d10f4f8428206ceab8  vp90-2-03-size-200x196-200x196-0004.i420
+6f6ecde53cd0ea5298f4529d396460c6  vp90-2-03-size-200x196-200x196-0005.i420
+0431d389278957fbef3e72f69f3ce008  vp90-2-03-size-200x196-200x196-0006.i420
+a047c60c4c60d2ea1f79c86dc98cdf8e  vp90-2-03-size-200x196-200x196-0007.i420
+dceda8bf128a8cdcadfa6c5db49cde51  vp90-2-03-size-200x196-200x196-0008.i420
+d8a6283637f5abda17e0bf150eac2983  vp90-2-03-size-200x196-200x196-0009.i420
+33dca31ef26fdd0daf9971c8de685d01  vp90-2-03-size-200x196-200x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x198.vp9
new file mode 100644
index 0000000..e910dea6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x198_vp9_md5
new file mode 100644
index 0000000..055811c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x198_vp9_md5
@@ -0,0 +1,10 @@
+d4b3578d800c747bcabaa484a140ffb0  vp90-2-03-size-200x198-200x198-0001.i420
+a40f6f8c384c5dc3d5546d960bb6d9e5  vp90-2-03-size-200x198-200x198-0002.i420
+e270ae8754d9906dd88b1c7d05280801  vp90-2-03-size-200x198-200x198-0003.i420
+bde7fde5012840c5e188f3b29f4f0003  vp90-2-03-size-200x198-200x198-0004.i420
+8f8510c1130615b64fb8469af66ff678  vp90-2-03-size-200x198-200x198-0005.i420
+79b9d4e0c64f82a6e9540394222a593d  vp90-2-03-size-200x198-200x198-0006.i420
+34852ac9ca5c6bfa51736296784343c7  vp90-2-03-size-200x198-200x198-0007.i420
+b055218509dbed644113642f8f0ac8a8  vp90-2-03-size-200x198-200x198-0008.i420
+1628866b436f1c4b892474025226e545  vp90-2-03-size-200x198-200x198-0009.i420
+3fdec760c04e30c90e74afb38dbf757c  vp90-2-03-size-200x198-200x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x200.vp9
new file mode 100644
index 0000000..039ccef
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x200_vp9_md5
new file mode 100644
index 0000000..b6d78f8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x200_vp9_md5
@@ -0,0 +1,10 @@
+b339f4e563afadb25f43b8c05b12dc03  vp90-2-03-size-200x200-200x200-0001.i420
+3bd5280e7fb42400085b0b1dbba1905e  vp90-2-03-size-200x200-200x200-0002.i420
+acf1c84cabff763fe2073d2c1f183bfc  vp90-2-03-size-200x200-200x200-0003.i420
+eaa4983b6baf907efb11d137644569d2  vp90-2-03-size-200x200-200x200-0004.i420
+8a1871c8dc38a19dfd4ac571ad7f39be  vp90-2-03-size-200x200-200x200-0005.i420
+0be539bd51f5f364828dd0abc70360be  vp90-2-03-size-200x200-200x200-0006.i420
+df60622d2c9f294f61d738be9e3bd16c  vp90-2-03-size-200x200-200x200-0007.i420
+22b3f1d51ddf92c7d2add305ba0ef405  vp90-2-03-size-200x200-200x200-0008.i420
+01ba29be721e64a5a50526de0797c7d3  vp90-2-03-size-200x200-200x200-0009.i420
+7b7aa7fa0e58202b3104671375762587  vp90-2-03-size-200x200-200x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x202.vp9
new file mode 100644
index 0000000..10ed70e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x202_vp9_md5
new file mode 100644
index 0000000..f93617e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x202_vp9_md5
@@ -0,0 +1,10 @@
+c4a13df44e66f06961dd72fc990439e9  vp90-2-03-size-200x202-200x202-0001.i420
+81c73b8d3806ad96af8f422914a253f8  vp90-2-03-size-200x202-200x202-0002.i420
+05f77526125e802be9cb306e375ded6e  vp90-2-03-size-200x202-200x202-0003.i420
+ab2e224840ff89abec2c675a23a73094  vp90-2-03-size-200x202-200x202-0004.i420
+c30f58f88819eb57102678b169e15188  vp90-2-03-size-200x202-200x202-0005.i420
+33e5e2799eb4a9c548c8372fd6769db9  vp90-2-03-size-200x202-200x202-0006.i420
+fa53c1c7e60bd1d00335af542ec69ed7  vp90-2-03-size-200x202-200x202-0007.i420
+534cafe658af10a314d6d084e55b3620  vp90-2-03-size-200x202-200x202-0008.i420
+502529e4fbecc8b890abf665fa21f53c  vp90-2-03-size-200x202-200x202-0009.i420
+bf1f73c6e77370bc51a770c8ae87bd12  vp90-2-03-size-200x202-200x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x208.vp9
new file mode 100644
index 0000000..a78b114
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x208_vp9_md5
new file mode 100644
index 0000000..4611a4a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x208_vp9_md5
@@ -0,0 +1,10 @@
+702748bec18c500dd41d93ae74b11d56  vp90-2-03-size-200x208-200x208-0001.i420
+4fb542190dab2fd673724d47451ff6ee  vp90-2-03-size-200x208-200x208-0002.i420
+dbb4d27d52797dab67e39d32092c9d44  vp90-2-03-size-200x208-200x208-0003.i420
+e4a0ed1572207b7ba433896bba711148  vp90-2-03-size-200x208-200x208-0004.i420
+28ec32bc165f4f9d455efec8a7aa8737  vp90-2-03-size-200x208-200x208-0005.i420
+a95910575a6423abffb28ca38c384b34  vp90-2-03-size-200x208-200x208-0006.i420
+791f1c558c5467725f4614a75a8a687e  vp90-2-03-size-200x208-200x208-0007.i420
+cfd3e12f84f7a811966721e890228313  vp90-2-03-size-200x208-200x208-0008.i420
+824c5fdf938551c28ac1c996645ae52f  vp90-2-03-size-200x208-200x208-0009.i420
+7465917fdd0206e393968232a0ec5193  vp90-2-03-size-200x208-200x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x210.vp9
new file mode 100644
index 0000000..27a3f40
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x210_vp9_md5
new file mode 100644
index 0000000..75c190c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x210_vp9_md5
@@ -0,0 +1,10 @@
+31ef44bd12ae702f306c55eba10d2ba7  vp90-2-03-size-200x210-200x210-0001.i420
+83e9d913f5aa058d79a81047ca45e4a2  vp90-2-03-size-200x210-200x210-0002.i420
+b5e21313b859f1e2c67aaac5fefc9f68  vp90-2-03-size-200x210-200x210-0003.i420
+959d63c1b219c3479af673a9a8b8d82c  vp90-2-03-size-200x210-200x210-0004.i420
+ffcfaf42b69c7cd92f6e3c21987ff7df  vp90-2-03-size-200x210-200x210-0005.i420
+e9667d3ee4d8179da44de4fbffcb7df2  vp90-2-03-size-200x210-200x210-0006.i420
+5e2c841bcf4ec6f3a05020d36986fe5b  vp90-2-03-size-200x210-200x210-0007.i420
+19fe287c30bd4c90b00a9631409568c0  vp90-2-03-size-200x210-200x210-0008.i420
+58a8843e50b19860a0a91e1e1bb63bfd  vp90-2-03-size-200x210-200x210-0009.i420
+0ebd31e18597a567f96645acbb2500cf  vp90-2-03-size-200x210-200x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x224.vp9
new file mode 100644
index 0000000..61d8df6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x224_vp9_md5
new file mode 100644
index 0000000..0f64dfc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x224_vp9_md5
@@ -0,0 +1,10 @@
+315d69847bf752a84231a368278eb0b6  vp90-2-03-size-200x224-200x224-0001.i420
+d245738f8627fc345ab38a547bc7d352  vp90-2-03-size-200x224-200x224-0002.i420
+982681cdca448919c2eead94435772ad  vp90-2-03-size-200x224-200x224-0003.i420
+7b67b2d96476e17cd407bbccb19fd070  vp90-2-03-size-200x224-200x224-0004.i420
+c38dde73ca097049d1fc689e18a49b5d  vp90-2-03-size-200x224-200x224-0005.i420
+525f323b81d780c669a03655bb0d0b56  vp90-2-03-size-200x224-200x224-0006.i420
+5dbeb96f65e383771c1c877ec559044a  vp90-2-03-size-200x224-200x224-0007.i420
+7d96e976265ef0f9faf173376caaa9e9  vp90-2-03-size-200x224-200x224-0008.i420
+6047c805a724701b80a133486aae0e65  vp90-2-03-size-200x224-200x224-0009.i420
+eb8895dd994076a52aa3a0c1758ccbb7  vp90-2-03-size-200x224-200x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_200x226.vp9
new file mode 100644
index 0000000..cc08073
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_200x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_200x226_vp9_md5
new file mode 100644
index 0000000..42f870c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_200x226_vp9_md5
@@ -0,0 +1,10 @@
+e45b6b9dce4a8509b7d26bc3cfdf7c86  vp90-2-03-size-200x226-200x226-0001.i420
+ddb9d5033ecfa2d6e9a5505dce374bda  vp90-2-03-size-200x226-200x226-0002.i420
+52c495d3137143e0bce9382fe5506057  vp90-2-03-size-200x226-200x226-0003.i420
+d09f3d6ad084f2966196acd48246f951  vp90-2-03-size-200x226-200x226-0004.i420
+1556d006d0119a3172b98a500b27f8d0  vp90-2-03-size-200x226-200x226-0005.i420
+904f86cfbcc3fa683d3d7744a286cd88  vp90-2-03-size-200x226-200x226-0006.i420
+b35907456b8ccab0ae8efc8405b04c89  vp90-2-03-size-200x226-200x226-0007.i420
+b7f2648fe0f873f7e9ea4a6d913e45ec  vp90-2-03-size-200x226-200x226-0008.i420
+2da76544bc7e295486c335e17047e12e  vp90-2-03-size-200x226-200x226-0009.i420
+10fd6424caf837d37564ef15f1c6f93d  vp90-2-03-size-200x226-200x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x196.vp9
new file mode 100644
index 0000000..5961c56
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x196_vp9_md5
new file mode 100644
index 0000000..1e76804
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x196_vp9_md5
@@ -0,0 +1,10 @@
+1261466179df96099e598e46c50fa7c1  vp90-2-03-size-202x196-202x196-0001.i420
+cc0fe373cd0399cf0c95edf92d9ab01f  vp90-2-03-size-202x196-202x196-0002.i420
+7a2dc0afd06ecfcf54321fb759f57601  vp90-2-03-size-202x196-202x196-0003.i420
+db9c138503d27f87449f870ab07cab03  vp90-2-03-size-202x196-202x196-0004.i420
+ddea2e5e2659e97132a537566d5ed989  vp90-2-03-size-202x196-202x196-0005.i420
+c31e90b5eee032526c4e0603332fd160  vp90-2-03-size-202x196-202x196-0006.i420
+7e5b40f03b905d9ee749d3097a484ea0  vp90-2-03-size-202x196-202x196-0007.i420
+93e9f7defa94ff03c041448ae1e55cea  vp90-2-03-size-202x196-202x196-0008.i420
+aef8e03f0146699faa16ec28dea49dbe  vp90-2-03-size-202x196-202x196-0009.i420
+a651d949b4c8f0e455c6592dc98385f7  vp90-2-03-size-202x196-202x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x198.vp9
new file mode 100644
index 0000000..de8d042
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x198_vp9_md5
new file mode 100644
index 0000000..fa76001
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x198_vp9_md5
@@ -0,0 +1,10 @@
+181edc4ebeeff7f0527b93b84d5d8efb  vp90-2-03-size-202x198-202x198-0001.i420
+132c71b634fb67eed51fcdef1775b6b2  vp90-2-03-size-202x198-202x198-0002.i420
+fd41144770765fc893adc5843ebe32e4  vp90-2-03-size-202x198-202x198-0003.i420
+77dcbaea101142940b6a78a271842829  vp90-2-03-size-202x198-202x198-0004.i420
+01737c38c1ac711a9744256788211177  vp90-2-03-size-202x198-202x198-0005.i420
+31cd0b5f621daac309c6f249f4c26cd8  vp90-2-03-size-202x198-202x198-0006.i420
+e06d34e570dc46904fdb9eeb55811464  vp90-2-03-size-202x198-202x198-0007.i420
+71bf55030373bde1eaeb52d1e97bfa4a  vp90-2-03-size-202x198-202x198-0008.i420
+e96063ff02e8a23a666222b59391de9c  vp90-2-03-size-202x198-202x198-0009.i420
+5aa0079168ab5069e8a3064f9e2a6d8b  vp90-2-03-size-202x198-202x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x200.vp9
new file mode 100644
index 0000000..79ec044
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x200_vp9_md5
new file mode 100644
index 0000000..1e7817e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x200_vp9_md5
@@ -0,0 +1,10 @@
+20c41d4a1271183dbbc7a44e6b90ea80  vp90-2-03-size-202x200-202x200-0001.i420
+bd8c1fba8d8742f4d98b7d5097c8c828  vp90-2-03-size-202x200-202x200-0002.i420
+55cbe06a925009c1b1f9b609b60b4c1d  vp90-2-03-size-202x200-202x200-0003.i420
+78e80c7cf1f142e2dda1bc269b5b3e00  vp90-2-03-size-202x200-202x200-0004.i420
+42ee8157a4c8af6670b81e9324b251e9  vp90-2-03-size-202x200-202x200-0005.i420
+022bdf5a2e1ea5f98503cd25b383ae53  vp90-2-03-size-202x200-202x200-0006.i420
+c2073865386a991da01966878ce1ce6d  vp90-2-03-size-202x200-202x200-0007.i420
+6a5b95cd4eff0836b9180a25f663d36a  vp90-2-03-size-202x200-202x200-0008.i420
+5e5498c357340d4755dc98eb0669f103  vp90-2-03-size-202x200-202x200-0009.i420
+0907d5e4020111b1ecfe707df71bcd8a  vp90-2-03-size-202x200-202x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x202.vp9
new file mode 100644
index 0000000..27a554c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x202_vp9_md5
new file mode 100644
index 0000000..f5ef776
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x202_vp9_md5
@@ -0,0 +1,10 @@
+610cef52d35e9c641f2b8c10489c3d12  vp90-2-03-size-202x202-202x202-0001.i420
+1f84062e607d4798b0544739fe0da99c  vp90-2-03-size-202x202-202x202-0002.i420
+ea379947b5c52ea3989dfc3f47c729d9  vp90-2-03-size-202x202-202x202-0003.i420
+1d06b72f06178cbb6bb5d188d22bff43  vp90-2-03-size-202x202-202x202-0004.i420
+25bd41bd7607f88a01aa0cdc336c9975  vp90-2-03-size-202x202-202x202-0005.i420
+86836a95a7a9fb1eefb20f7c5a15a9ab  vp90-2-03-size-202x202-202x202-0006.i420
+d8eb3fecce1b646b9877cd4fcca9f9bf  vp90-2-03-size-202x202-202x202-0007.i420
+a057e0b29e4ac9717452cc478c418c12  vp90-2-03-size-202x202-202x202-0008.i420
+9a3bab91b4f0fff174536b1609c9632c  vp90-2-03-size-202x202-202x202-0009.i420
+d1cd93975f746b6cae490aae31f89e7e  vp90-2-03-size-202x202-202x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x208.vp9
new file mode 100644
index 0000000..3a532a0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x208_vp9_md5
new file mode 100644
index 0000000..7eae1c8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x208_vp9_md5
@@ -0,0 +1,10 @@
+d2128e290be81bb0700ebe19e3faed4f  vp90-2-03-size-202x208-202x208-0001.i420
+dccaecb7e4ddb7e4224221a659af2a43  vp90-2-03-size-202x208-202x208-0002.i420
+be8e0966aaf3a9fe9164f63695dc3b62  vp90-2-03-size-202x208-202x208-0003.i420
+da944fadc3a239c2254678cadb4cf7fa  vp90-2-03-size-202x208-202x208-0004.i420
+3c270f3c02fcbd192b7f896f3f9ee6d9  vp90-2-03-size-202x208-202x208-0005.i420
+0b3ccda0a87c37e40104ae2f1060e8e9  vp90-2-03-size-202x208-202x208-0006.i420
+254253aba91758f302e7177e614596be  vp90-2-03-size-202x208-202x208-0007.i420
+b1501a4e372a5249e74aab77e57a28f1  vp90-2-03-size-202x208-202x208-0008.i420
+c4497fea1cefed5cf2b2908620153d26  vp90-2-03-size-202x208-202x208-0009.i420
+5ba20dfa2400b15b5394f315c5c3707d  vp90-2-03-size-202x208-202x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x210.vp9
new file mode 100644
index 0000000..69c00a0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x210_vp9_md5
new file mode 100644
index 0000000..3d0ee16
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x210_vp9_md5
@@ -0,0 +1,10 @@
+e4663a28cabbfdd3815efda2d38debcc  vp90-2-03-size-202x210-202x210-0001.i420
+3cc7dbec64e9f697f40d740a72c09fc7  vp90-2-03-size-202x210-202x210-0002.i420
+f108981e0ce9c6c501b9ac61d0f1ba44  vp90-2-03-size-202x210-202x210-0003.i420
+63191c7aceb8ac6b030cc1a4b3cda18c  vp90-2-03-size-202x210-202x210-0004.i420
+b0a527ae3aafe94d13573199c6f4944f  vp90-2-03-size-202x210-202x210-0005.i420
+1be14b213ebf1d653468b8c16bae03fb  vp90-2-03-size-202x210-202x210-0006.i420
+44e5a8333a043cd93b9d1cc78e5f188f  vp90-2-03-size-202x210-202x210-0007.i420
+bfd7619f990f20e23b47d0738a6a8449  vp90-2-03-size-202x210-202x210-0008.i420
+800405f45ca5198014ef8d8521b044fa  vp90-2-03-size-202x210-202x210-0009.i420
+dca4eda872349708f54486433efc8225  vp90-2-03-size-202x210-202x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x224.vp9
new file mode 100644
index 0000000..9e24686
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x224_vp9_md5
new file mode 100644
index 0000000..50b423d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x224_vp9_md5
@@ -0,0 +1,10 @@
+1d318f05310f6d40646f23c62c7eafe4  vp90-2-03-size-202x224-202x224-0001.i420
+42870bd73e1a0c5d84b986db3d24f0f0  vp90-2-03-size-202x224-202x224-0002.i420
+afaac676150286143c6fec7992a81467  vp90-2-03-size-202x224-202x224-0003.i420
+128f84400c272628e802c2369b6bf548  vp90-2-03-size-202x224-202x224-0004.i420
+9adc24d69f12349d8b17c84f5c111767  vp90-2-03-size-202x224-202x224-0005.i420
+b33d2f7a1955248652701f2ade8ab55d  vp90-2-03-size-202x224-202x224-0006.i420
+b8acc23721097fce6c8835f5fcfaa6ee  vp90-2-03-size-202x224-202x224-0007.i420
+b63bf9a08e4dc5879bbd91efaec95960  vp90-2-03-size-202x224-202x224-0008.i420
+96e8fe29935266f6bd486b99f917eabc  vp90-2-03-size-202x224-202x224-0009.i420
+54be14f8dde6857867cd4581f8557044  vp90-2-03-size-202x224-202x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_202x226.vp9
new file mode 100644
index 0000000..eff9809
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_202x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_202x226_vp9_md5
new file mode 100644
index 0000000..88d3400
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_202x226_vp9_md5
@@ -0,0 +1,10 @@
+5aa0f439c58c6335cd86d4238a8c4b68  vp90-2-03-size-202x226-202x226-0001.i420
+3616cc306ec05f89d9b0db63200e4abf  vp90-2-03-size-202x226-202x226-0002.i420
+424e98f8ec0ebf2a326a917ee0159bbe  vp90-2-03-size-202x226-202x226-0003.i420
+ed5710e412f056fa8c1a277d86dd45d7  vp90-2-03-size-202x226-202x226-0004.i420
+760b850feab485f0bda6cde9943102bc  vp90-2-03-size-202x226-202x226-0005.i420
+f4bd90ca72aa707f9b68e6192ac230fd  vp90-2-03-size-202x226-202x226-0006.i420
+58e4aad0bc2a9f3fc279df10208bd6f6  vp90-2-03-size-202x226-202x226-0007.i420
+b42f84723dd167d5c544d539275ad537  vp90-2-03-size-202x226-202x226-0008.i420
+5f54feca21331646e68797380260932a  vp90-2-03-size-202x226-202x226-0009.i420
+8e787dd318024aff25af8b4d85040f3c  vp90-2-03-size-202x226-202x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x196.vp9
new file mode 100644
index 0000000..6f6807f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x196_vp9_md5
new file mode 100644
index 0000000..f32709e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x196_vp9_md5
@@ -0,0 +1,10 @@
+6195975181969789e101a83a555d13f7  vp90-2-03-size-208x196-208x196-0001.i420
+2aca5e3307d68a5e969564a943b8e723  vp90-2-03-size-208x196-208x196-0002.i420
+aee4b00472ee0b6b7a13e31069181db4  vp90-2-03-size-208x196-208x196-0003.i420
+7808595b650a7c14d8a4800db7c014e0  vp90-2-03-size-208x196-208x196-0004.i420
+746eb763b176286aa875ae06b81118c4  vp90-2-03-size-208x196-208x196-0005.i420
+0e8a78ec061319e27d49ca25e333e017  vp90-2-03-size-208x196-208x196-0006.i420
+ac4432db2bb0971d5f70a7dda1210c19  vp90-2-03-size-208x196-208x196-0007.i420
+78870f4bd767f8ab65d369a5b322735d  vp90-2-03-size-208x196-208x196-0008.i420
+eee9ddd91209348a64259db6a4a3f80c  vp90-2-03-size-208x196-208x196-0009.i420
+c48d21e36a9c0d0d1c64db3f776b3002  vp90-2-03-size-208x196-208x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x198.vp9
new file mode 100644
index 0000000..d6bea55
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x198_vp9_md5
new file mode 100644
index 0000000..a57dc44
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x198_vp9_md5
@@ -0,0 +1,10 @@
+1f1fa3cdf865d8c75183f4ba6203b675  vp90-2-03-size-208x198-208x198-0001.i420
+ead33ead8fea5bd5d831a79f4c75a590  vp90-2-03-size-208x198-208x198-0002.i420
+9a406b4464989fd4bb7cbcb1b18aeaa7  vp90-2-03-size-208x198-208x198-0003.i420
+fab3d228e7032f2cdc440dbfcb17c4c1  vp90-2-03-size-208x198-208x198-0004.i420
+f2f3f8b8d9ece21c359c89245157c613  vp90-2-03-size-208x198-208x198-0005.i420
+321f5a8ecb2cec1780013fe72c237bde  vp90-2-03-size-208x198-208x198-0006.i420
+6f025b1f4ef61d261f05ca149a9470e6  vp90-2-03-size-208x198-208x198-0007.i420
+85abcc8d8e6b5f286ed6aa6c588cf416  vp90-2-03-size-208x198-208x198-0008.i420
+b28d710dd44389f774aa02edd6327d5c  vp90-2-03-size-208x198-208x198-0009.i420
+79374bef9819eecafa7396d70c80be7f  vp90-2-03-size-208x198-208x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x200.vp9
new file mode 100644
index 0000000..40aebf2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x200_vp9_md5
new file mode 100644
index 0000000..35756a2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x200_vp9_md5
@@ -0,0 +1,10 @@
+ff2dda3ddbe8b461d960baba0ad132bf  vp90-2-03-size-208x200-208x200-0001.i420
+d6935ac8f2250316f498e8f01afa04fd  vp90-2-03-size-208x200-208x200-0002.i420
+57173ebaef7b21698c62fa959cb40ead  vp90-2-03-size-208x200-208x200-0003.i420
+f354c76d7cf45e9f3adfdde0f6b3b5c9  vp90-2-03-size-208x200-208x200-0004.i420
+fbc968ecd214b01509a76996e45dd09a  vp90-2-03-size-208x200-208x200-0005.i420
+9c314b51a80f2a081adf9b9cc26f5f8a  vp90-2-03-size-208x200-208x200-0006.i420
+f22883a6a5b74ffa4bb16f22d496b5a5  vp90-2-03-size-208x200-208x200-0007.i420
+eb4fa914fc5658d43e32c48a0c39bab3  vp90-2-03-size-208x200-208x200-0008.i420
+d763c0c2f44b68e1e3fe9e165334eb0b  vp90-2-03-size-208x200-208x200-0009.i420
+344e1075a48cd61e79b0550809b4c91f  vp90-2-03-size-208x200-208x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x202.vp9
new file mode 100644
index 0000000..eb6c574
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x202_vp9_md5
new file mode 100644
index 0000000..cd27e7c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x202_vp9_md5
@@ -0,0 +1,10 @@
+e5164f87feadf4b65257f578affc3e04  vp90-2-03-size-208x202-208x202-0001.i420
+6aee5a3b6c3a096dfc1594762b2b248f  vp90-2-03-size-208x202-208x202-0002.i420
+cb1c9dce6fdf7372e0eb2397251f0ade  vp90-2-03-size-208x202-208x202-0003.i420
+4fe5f24c08690c966b6a14ac3422510b  vp90-2-03-size-208x202-208x202-0004.i420
+b22a273814523251b365f3278d8a3a9c  vp90-2-03-size-208x202-208x202-0005.i420
+190d9dff373023a25427fc859545ea24  vp90-2-03-size-208x202-208x202-0006.i420
+a6307f38718ed686cb195e3833ab27ab  vp90-2-03-size-208x202-208x202-0007.i420
+79630bec5a91d69aca42a910413c2800  vp90-2-03-size-208x202-208x202-0008.i420
+2231cec9c03714b8671e5e1456b148c9  vp90-2-03-size-208x202-208x202-0009.i420
+278458f6734a24f2eb9bc877a6e9d7df  vp90-2-03-size-208x202-208x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x208.vp9
new file mode 100644
index 0000000..16612c0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x208_vp9_md5
new file mode 100644
index 0000000..921cbdd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x208_vp9_md5
@@ -0,0 +1,10 @@
+6bff7c1f4c5ef8412ebf669852c70de6  vp90-2-03-size-208x208-208x208-0001.i420
+fdfd7a2308de9509a41fed2880a8f0f5  vp90-2-03-size-208x208-208x208-0002.i420
+d8b464811e9c3b8a6db9cc277ac88c59  vp90-2-03-size-208x208-208x208-0003.i420
+b8fa29e79be3126dd74310d6dd09c747  vp90-2-03-size-208x208-208x208-0004.i420
+dad29803fed686887a0873eb78a469c6  vp90-2-03-size-208x208-208x208-0005.i420
+684de29bbf800f52aea4af9850bcc5b3  vp90-2-03-size-208x208-208x208-0006.i420
+06862dbce7571b4487766b179a596e1d  vp90-2-03-size-208x208-208x208-0007.i420
+99582a966bc7070112e214ce7912e485  vp90-2-03-size-208x208-208x208-0008.i420
+a61158581a5719cb0cf13fb3301cb8c4  vp90-2-03-size-208x208-208x208-0009.i420
+9c2295332f34fee3a249262c8ba843bc  vp90-2-03-size-208x208-208x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x210.vp9
new file mode 100644
index 0000000..dfec3e8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x210_vp9_md5
new file mode 100644
index 0000000..ab5c7d8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x210_vp9_md5
@@ -0,0 +1,10 @@
+b15c7e98ddd137237b062cb51667522f  vp90-2-03-size-208x210-208x210-0001.i420
+00c594c68b19ef39a79a38e86853dc64  vp90-2-03-size-208x210-208x210-0002.i420
+e6742abe3d2c178af4298e121391c299  vp90-2-03-size-208x210-208x210-0003.i420
+efe5387b38c32f1c25c0fc9836921074  vp90-2-03-size-208x210-208x210-0004.i420
+e0e696f4c18af09a74e052903db1468c  vp90-2-03-size-208x210-208x210-0005.i420
+f1960270c6704ca47caed63161716025  vp90-2-03-size-208x210-208x210-0006.i420
+a1542d7749cfa447481acd7835db838a  vp90-2-03-size-208x210-208x210-0007.i420
+a91fb10a17d1d056667860cc43c81dae  vp90-2-03-size-208x210-208x210-0008.i420
+b673bfbb722522b4e7b5e9c5b85cc31f  vp90-2-03-size-208x210-208x210-0009.i420
+8b4bb57d3cf609cbf9564a96a6ca6ade  vp90-2-03-size-208x210-208x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x224.vp9
new file mode 100644
index 0000000..b60fb5d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x224_vp9_md5
new file mode 100644
index 0000000..bcb9657
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x224_vp9_md5
@@ -0,0 +1,10 @@
+479d07bb96905ad7d5f0ec3ee12b41ba  vp90-2-03-size-208x224-208x224-0001.i420
+4b6555aaed8e5a45879773f1bf87962e  vp90-2-03-size-208x224-208x224-0002.i420
+c5f42cb796dd7b6622957016ca6b502f  vp90-2-03-size-208x224-208x224-0003.i420
+f06c954483560866fbff10bae7ba0785  vp90-2-03-size-208x224-208x224-0004.i420
+af83aff39999852310395fe241ccb49b  vp90-2-03-size-208x224-208x224-0005.i420
+108377d6f30ceba6f2377330af2da38f  vp90-2-03-size-208x224-208x224-0006.i420
+e81e6e0b37a7b92368ede9cab124567c  vp90-2-03-size-208x224-208x224-0007.i420
+59dbe51caaed8e6e825c78c5901fb22c  vp90-2-03-size-208x224-208x224-0008.i420
+24686123ea14c8d1a9b447733df0aaab  vp90-2-03-size-208x224-208x224-0009.i420
+ce2035c49237c8076f8dac0d3f61848e  vp90-2-03-size-208x224-208x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_208x226.vp9
new file mode 100644
index 0000000..4541cf9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_208x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_208x226_vp9_md5
new file mode 100644
index 0000000..e0a7e53
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_208x226_vp9_md5
@@ -0,0 +1,10 @@
+33aa4af6153570518c59960a0c959053  vp90-2-03-size-208x226-208x226-0001.i420
+024fa27dee80ad199528052aaa8d42c7  vp90-2-03-size-208x226-208x226-0002.i420
+b949ef118c7e7e62a8b88e2308219ef9  vp90-2-03-size-208x226-208x226-0003.i420
+3061ee13696ced5e10a646fdd5ca6c34  vp90-2-03-size-208x226-208x226-0004.i420
+c4984bd53dcb7b9e2570f2965d077b2f  vp90-2-03-size-208x226-208x226-0005.i420
+d564c35c5caadcfd9f80377fa414af72  vp90-2-03-size-208x226-208x226-0006.i420
+9b7d7b10ee2f3eb7a9ffddcebff45b97  vp90-2-03-size-208x226-208x226-0007.i420
+a0ede7085b04cbb3519d56b2e4347d14  vp90-2-03-size-208x226-208x226-0008.i420
+63d7af745f9e6a34b618db28fe878ffd  vp90-2-03-size-208x226-208x226-0009.i420
+85077809087e7bdfb9215bfcd1f1bbc0  vp90-2-03-size-208x226-208x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x196.vp9
new file mode 100644
index 0000000..a5eca1f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x196_vp9_md5
new file mode 100644
index 0000000..c23a9af
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x196_vp9_md5
@@ -0,0 +1,10 @@
+5c69f80da667bfd20394995e93e4cd2b  vp90-2-03-size-210x196-210x196-0001.i420
+13363cd8e52ca8c1053db1c84c111bc9  vp90-2-03-size-210x196-210x196-0002.i420
+108976afdf99f59276d6f89879e3bdc3  vp90-2-03-size-210x196-210x196-0003.i420
+770ce25985e6b479d52a9185876cfe83  vp90-2-03-size-210x196-210x196-0004.i420
+eba7cbb3c91989aa4c13487ed01675b5  vp90-2-03-size-210x196-210x196-0005.i420
+f391c30a47c33a250dd20cb12f0a6e01  vp90-2-03-size-210x196-210x196-0006.i420
+c38e12de302177d19dd744a3ea227e90  vp90-2-03-size-210x196-210x196-0007.i420
+8c9370439a0b7289919c6ee68e00570f  vp90-2-03-size-210x196-210x196-0008.i420
+ac3748c4b99c4f1aba7430ae12c19cfd  vp90-2-03-size-210x196-210x196-0009.i420
+e5228dc84f7933ccc9306907d737ad3c  vp90-2-03-size-210x196-210x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x198.vp9
new file mode 100644
index 0000000..b11e214
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x198_vp9_md5
new file mode 100644
index 0000000..7776c06
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x198_vp9_md5
@@ -0,0 +1,10 @@
+d83ee2413e701ae405a2b74863d4c5a9  vp90-2-03-size-210x198-210x198-0001.i420
+f2ebc0f7dc171e0e5d2911c7ee2df5e1  vp90-2-03-size-210x198-210x198-0002.i420
+e189ef4d8add227352a0d6ee62748ee7  vp90-2-03-size-210x198-210x198-0003.i420
+6dcb1dca1a0e2ba85034aba9f021427e  vp90-2-03-size-210x198-210x198-0004.i420
+e98c633ba8912f6d65374055ec9af543  vp90-2-03-size-210x198-210x198-0005.i420
+82111cb7d5addce16d9bcba9e0a99503  vp90-2-03-size-210x198-210x198-0006.i420
+bbbc73002f794ab0261fe384b2524226  vp90-2-03-size-210x198-210x198-0007.i420
+0bcdc427df47123959f7de9c44fe291e  vp90-2-03-size-210x198-210x198-0008.i420
+505776b3d82e38612393d60b6aa55c1d  vp90-2-03-size-210x198-210x198-0009.i420
+feb93758242b847f3d53bb4c97b0ad9c  vp90-2-03-size-210x198-210x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x200.vp9
new file mode 100644
index 0000000..93ace8c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x200_vp9_md5
new file mode 100644
index 0000000..20dea3f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x200_vp9_md5
@@ -0,0 +1,10 @@
+2465560246c1ee24d937cb9cbc1422f1  vp90-2-03-size-210x200-210x200-0001.i420
+8926b628dcdf2182516822c7d0d778ec  vp90-2-03-size-210x200-210x200-0002.i420
+9bd14d3ebc7fe81c4223116de1b9c2ec  vp90-2-03-size-210x200-210x200-0003.i420
+2d029d8461c20236066c0786950540fb  vp90-2-03-size-210x200-210x200-0004.i420
+39412b6e62de43bd40c58d4e2e38daf8  vp90-2-03-size-210x200-210x200-0005.i420
+3ea211c24f606b29582147bf872994dd  vp90-2-03-size-210x200-210x200-0006.i420
+261c37f88bf7f40549642578d9464aeb  vp90-2-03-size-210x200-210x200-0007.i420
+98551d44de1e23165e05975babb72446  vp90-2-03-size-210x200-210x200-0008.i420
+1d85ad052dd27e7e6bfea5d2babf5176  vp90-2-03-size-210x200-210x200-0009.i420
+ad18b6a3698a3674c2488f927810eb0d  vp90-2-03-size-210x200-210x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x202.vp9
new file mode 100644
index 0000000..e84b816
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x202_vp9_md5
new file mode 100644
index 0000000..8d7e06e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x202_vp9_md5
@@ -0,0 +1,10 @@
+5d01848aee2b324f2e356627f9c39532  vp90-2-03-size-210x202-210x202-0001.i420
+b671fe34bc0e5a682baff929d26ea627  vp90-2-03-size-210x202-210x202-0002.i420
+e9a40f87ca5aaa5af9772e286feb9063  vp90-2-03-size-210x202-210x202-0003.i420
+4730f60d4c856e8ad877c0d8b1729ec4  vp90-2-03-size-210x202-210x202-0004.i420
+317fc01349e0984c23d15f97a3a0f442  vp90-2-03-size-210x202-210x202-0005.i420
+aea89116ffe48340d1752d1ad5195529  vp90-2-03-size-210x202-210x202-0006.i420
+14694ba65b6308e5f5571486b62ca1cc  vp90-2-03-size-210x202-210x202-0007.i420
+53c6102d877c9a30eaa20ddc45207ea0  vp90-2-03-size-210x202-210x202-0008.i420
+7d1e898b1bead878224e8ff15d624bd9  vp90-2-03-size-210x202-210x202-0009.i420
+37b684bfae5dbd33e8dbb8332b94ce8a  vp90-2-03-size-210x202-210x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x208.vp9
new file mode 100644
index 0000000..c69fb3f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x208_vp9_md5
new file mode 100644
index 0000000..72f9259
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x208_vp9_md5
@@ -0,0 +1,10 @@
+1156d318c00d299cf5bdc7e485966dab  vp90-2-03-size-210x208-210x208-0001.i420
+a8094f8f1e7e04e54251bee8c4c800ce  vp90-2-03-size-210x208-210x208-0002.i420
+e2a07d99ffe1cfe6b9fce36e93677fe1  vp90-2-03-size-210x208-210x208-0003.i420
+63d179b00816dbad75b778d2c23955c6  vp90-2-03-size-210x208-210x208-0004.i420
+407de5fb2dfdd52e6173905b09ff22f2  vp90-2-03-size-210x208-210x208-0005.i420
+36900199c56310e651723de4e3ad2f2c  vp90-2-03-size-210x208-210x208-0006.i420
+908db56e975b5db07af17fdc51b12be8  vp90-2-03-size-210x208-210x208-0007.i420
+400e32490b1262009a481cc331a00e44  vp90-2-03-size-210x208-210x208-0008.i420
+dc43b786cba033cc92b9921d12f7b3d7  vp90-2-03-size-210x208-210x208-0009.i420
+e8c94c5965c729f5d1ef3ba4509c97c8  vp90-2-03-size-210x208-210x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x210.vp9
new file mode 100644
index 0000000..ad6e896
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x210_vp9_md5
new file mode 100644
index 0000000..6b88d01
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x210_vp9_md5
@@ -0,0 +1,10 @@
+b65725c68978bdaaafdf735dfbafa9e3  vp90-2-03-size-210x210-210x210-0001.i420
+35be2f16bd5dedc9d3f7a016f0d71701  vp90-2-03-size-210x210-210x210-0002.i420
+8c2873a97b51510d7449869e24a348f5  vp90-2-03-size-210x210-210x210-0003.i420
+724a30e8ae539e797db8889dc08aec5e  vp90-2-03-size-210x210-210x210-0004.i420
+e3ae1246a63ea22afd026bfb859fe165  vp90-2-03-size-210x210-210x210-0005.i420
+7e1fa363cf3f44c7a3019f29c14a6da4  vp90-2-03-size-210x210-210x210-0006.i420
+c6f26619ab5687a2a698c8766b79f2eb  vp90-2-03-size-210x210-210x210-0007.i420
+be5b8c50a772afe95d72bf3cc7c4fd2f  vp90-2-03-size-210x210-210x210-0008.i420
+9eab1417ac249ce31c79750143d52084  vp90-2-03-size-210x210-210x210-0009.i420
+9d2455048dbc3cdc2343a818c5a2bcb1  vp90-2-03-size-210x210-210x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x224.vp9
new file mode 100644
index 0000000..4a01426
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x224_vp9_md5
new file mode 100644
index 0000000..7bd7a82
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x224_vp9_md5
@@ -0,0 +1,10 @@
+bb903b926c4b34ae336e21d65ad8fd25  vp90-2-03-size-210x224-210x224-0001.i420
+c4c0bc3b112487e994d22176817ace3c  vp90-2-03-size-210x224-210x224-0002.i420
+24e699f7a92ab1b0fe12e0b747470b5b  vp90-2-03-size-210x224-210x224-0003.i420
+200f403694d3acfda63f52e8373f1420  vp90-2-03-size-210x224-210x224-0004.i420
+6df417a8ec1810562301c89724b739d1  vp90-2-03-size-210x224-210x224-0005.i420
+55757b633d8fe669fc0f507dab4fa9f7  vp90-2-03-size-210x224-210x224-0006.i420
+45bc82bee02cb45422be3ac1019896d0  vp90-2-03-size-210x224-210x224-0007.i420
+4aaf5d07d2796910767d5084556c9cf9  vp90-2-03-size-210x224-210x224-0008.i420
+f100fa26da47250b98d95a18915f521d  vp90-2-03-size-210x224-210x224-0009.i420
+f5a8def53b4638b6ce7c8588d595d0ad  vp90-2-03-size-210x224-210x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_210x226.vp9
new file mode 100644
index 0000000..f88afa6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_210x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_210x226_vp9_md5
new file mode 100644
index 0000000..48fa3d4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_210x226_vp9_md5
@@ -0,0 +1,10 @@
+03707b2f5c392933f7336f380423a0a1  vp90-2-03-size-210x226-210x226-0001.i420
+b388553c79573555a3b660f5e36d4e36  vp90-2-03-size-210x226-210x226-0002.i420
+a1a7fd8ba7fb0fe7733cdf5440c7c1f3  vp90-2-03-size-210x226-210x226-0003.i420
+9daff7ef71dd54951f0b75a902065259  vp90-2-03-size-210x226-210x226-0004.i420
+60218a4b8bc0a5b0b40fa560a40fb4c0  vp90-2-03-size-210x226-210x226-0005.i420
+21229bfed833468fafc27ce93db1450c  vp90-2-03-size-210x226-210x226-0006.i420
+7aa290c6e503315d7aa3517258d5f63a  vp90-2-03-size-210x226-210x226-0007.i420
+63fd08ae2e859ff3d874ab2c2ce41a42  vp90-2-03-size-210x226-210x226-0008.i420
+725b371247fae28ef4b912368738df64  vp90-2-03-size-210x226-210x226-0009.i420
+7cf2d8d9e464307311b499ff0c3ea05e  vp90-2-03-size-210x226-210x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x196.vp9
new file mode 100644
index 0000000..8fd0876
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x196_vp9_md5
new file mode 100644
index 0000000..3edb492
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x196_vp9_md5
@@ -0,0 +1,10 @@
+3ffc096f1b42b4d319d4a9efbefc7625  vp90-2-03-size-224x196-224x196-0001.i420
+78b3655d5cad30fa6b2c2d8fd29463de  vp90-2-03-size-224x196-224x196-0002.i420
+ab197553d9599b2a03aff62d1d694848  vp90-2-03-size-224x196-224x196-0003.i420
+be368d1f3d3fcc710565b5433940f0df  vp90-2-03-size-224x196-224x196-0004.i420
+374c5db60ea9c110b871bb45be0efff1  vp90-2-03-size-224x196-224x196-0005.i420
+ec50085400d626de5833bc0a94d9941f  vp90-2-03-size-224x196-224x196-0006.i420
+d4ae69937e2a8d9bf2023d4215749635  vp90-2-03-size-224x196-224x196-0007.i420
+9b0b81eb6d62b8014e0639932fe35bc0  vp90-2-03-size-224x196-224x196-0008.i420
+cd02d0cc268e6b6df0b2dbd3f3b137e6  vp90-2-03-size-224x196-224x196-0009.i420
+5322ba1085c114f93534e1761a0d8aa1  vp90-2-03-size-224x196-224x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x198.vp9
new file mode 100644
index 0000000..c0b6e4c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x198_vp9_md5
new file mode 100644
index 0000000..d0b35cd
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x198_vp9_md5
@@ -0,0 +1,10 @@
+cf35dffc80946e87bb9d3e18aab9d320  vp90-2-03-size-224x198-224x198-0001.i420
+a76ac92f05e9b097f8ac5882e1ffe656  vp90-2-03-size-224x198-224x198-0002.i420
+faa1e8a11c9df3e9c9a9dafbebea6d04  vp90-2-03-size-224x198-224x198-0003.i420
+905a28289c8ac793b335096ca7f84e1d  vp90-2-03-size-224x198-224x198-0004.i420
+cb480fa6977baf98a74bddf213ecba82  vp90-2-03-size-224x198-224x198-0005.i420
+35224d3708e3ba1dafcc58b803d5ea77  vp90-2-03-size-224x198-224x198-0006.i420
+d166d764e87854bca47ab7a2bc8b1f9b  vp90-2-03-size-224x198-224x198-0007.i420
+562f1e06ae36abba5f1fb53e3d6cd7e8  vp90-2-03-size-224x198-224x198-0008.i420
+1599cebef060f6464aeef15aacbde446  vp90-2-03-size-224x198-224x198-0009.i420
+3316ebca2864a9dc04db86069efb1dd1  vp90-2-03-size-224x198-224x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x200.vp9
new file mode 100644
index 0000000..94cc4c7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x200_vp9_md5
new file mode 100644
index 0000000..bb368ce
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x200_vp9_md5
@@ -0,0 +1,10 @@
+0819e6d715c9b4d94f05f63a7ca86199  vp90-2-03-size-224x200-224x200-0001.i420
+9b9a4b01ed4c8a93687e45245b3092a3  vp90-2-03-size-224x200-224x200-0002.i420
+3a076f5b8dba60552e84a391ee04d1c7  vp90-2-03-size-224x200-224x200-0003.i420
+7aafc561f5b96e9d286bd8deb5687774  vp90-2-03-size-224x200-224x200-0004.i420
+daa43a89ab6b2761eedaa183e33a3465  vp90-2-03-size-224x200-224x200-0005.i420
+c14874409872357b11b65f35a283e058  vp90-2-03-size-224x200-224x200-0006.i420
+37d2ef52a9c694b2596d58ed9ca0d90b  vp90-2-03-size-224x200-224x200-0007.i420
+c97bc860c006896d80f52ccc0759f472  vp90-2-03-size-224x200-224x200-0008.i420
+5f8618114a723a017e39a1af695996f3  vp90-2-03-size-224x200-224x200-0009.i420
+ee8234fc5ccd41d05eb87e1510f9795e  vp90-2-03-size-224x200-224x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x202.vp9
new file mode 100644
index 0000000..ac4f494
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x202_vp9_md5
new file mode 100644
index 0000000..0c6b78c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x202_vp9_md5
@@ -0,0 +1,10 @@
+e1e3b4af5910383ff6f66b6ab1a29544  vp90-2-03-size-224x202-224x202-0001.i420
+8668ef92b72f35728ebb456665d48b95  vp90-2-03-size-224x202-224x202-0002.i420
+dffc7c28f86f07bf28451292990e9594  vp90-2-03-size-224x202-224x202-0003.i420
+aebfb446fa6d48db36dbd9b5cd147f1e  vp90-2-03-size-224x202-224x202-0004.i420
+e3c6cb8c5bb3a26928493bfc297ab827  vp90-2-03-size-224x202-224x202-0005.i420
+68dabae76c1d27ab0e1079d99cb6d413  vp90-2-03-size-224x202-224x202-0006.i420
+d1f7745eef748688f3871d00a7e67ef8  vp90-2-03-size-224x202-224x202-0007.i420
+36738851cc2af83fd250dea4cd63941b  vp90-2-03-size-224x202-224x202-0008.i420
+16c0315c43427e7e6719806a89551703  vp90-2-03-size-224x202-224x202-0009.i420
+c4d589c0ea4cdfc1dd6dff72084c61fd  vp90-2-03-size-224x202-224x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x208.vp9
new file mode 100644
index 0000000..47eae82
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x208_vp9_md5
new file mode 100644
index 0000000..1bcdd2c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x208_vp9_md5
@@ -0,0 +1,10 @@
+85f08afadfd1204d4131b9ee9c8cc10b  vp90-2-03-size-224x208-224x208-0001.i420
+f893de5432a082b3dffcf7499827f548  vp90-2-03-size-224x208-224x208-0002.i420
+cb81e0d7b657bc5a4a9cf8ad75a76a77  vp90-2-03-size-224x208-224x208-0003.i420
+8a40842123965731c15fc23fb6366d1d  vp90-2-03-size-224x208-224x208-0004.i420
+09c6d92af14a3fcfb12705cd5da57f2a  vp90-2-03-size-224x208-224x208-0005.i420
+6bede4dc8770df534b599021b0425309  vp90-2-03-size-224x208-224x208-0006.i420
+334b0b0448e9e4e6a0cddcd2e3a0af3f  vp90-2-03-size-224x208-224x208-0007.i420
+09f491f0f3870ef96cff0384cd7183d1  vp90-2-03-size-224x208-224x208-0008.i420
+c9e5f81186ac947a77b051c8f0e76eac  vp90-2-03-size-224x208-224x208-0009.i420
+917565c3327bff78b53a78ea739472ff  vp90-2-03-size-224x208-224x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x210.vp9
new file mode 100644
index 0000000..50d6389
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x210_vp9_md5
new file mode 100644
index 0000000..d522202
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x210_vp9_md5
@@ -0,0 +1,10 @@
+427421e5fd2087c6ff7b87a27982332f  vp90-2-03-size-224x210-224x210-0001.i420
+b68311fd44e189e4174ac357d5415068  vp90-2-03-size-224x210-224x210-0002.i420
+2c822ff45be7a1ea412d21ff82c7bc1d  vp90-2-03-size-224x210-224x210-0003.i420
+34659186d93516eae1dd4d9a391d1c3f  vp90-2-03-size-224x210-224x210-0004.i420
+1990dd822abc3a10f511589db5aa50f4  vp90-2-03-size-224x210-224x210-0005.i420
+4a4dc076172c79d9fde3e17b47109835  vp90-2-03-size-224x210-224x210-0006.i420
+51874c79850120537fa5c405721d0107  vp90-2-03-size-224x210-224x210-0007.i420
+15d7897a128de9be90be17f1679012c9  vp90-2-03-size-224x210-224x210-0008.i420
+a8d9480accf8585e94161a5f7c371cef  vp90-2-03-size-224x210-224x210-0009.i420
+8a9d3f09561b895b423ae9428f620b9b  vp90-2-03-size-224x210-224x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x224.vp9
new file mode 100644
index 0000000..6397922
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x224_vp9_md5
new file mode 100644
index 0000000..1a8a55e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x224_vp9_md5
@@ -0,0 +1,10 @@
+bedd5d2725ffff06a50e23841bc2dfb8  vp90-2-03-size-224x224-224x224-0001.i420
+8c363f68b0b30f507563516aa99e23ac  vp90-2-03-size-224x224-224x224-0002.i420
+9cb7d51ca4439614dc3f5980507a4d32  vp90-2-03-size-224x224-224x224-0003.i420
+b393a18de28ab6b8d1c6afd67a7794e0  vp90-2-03-size-224x224-224x224-0004.i420
+81f69ee1e3d89cb78cac192c352f7741  vp90-2-03-size-224x224-224x224-0005.i420
+aabb51f029a9a02e71524cf3500931e9  vp90-2-03-size-224x224-224x224-0006.i420
+6581aec620c508d2b42ccceaa2c6044d  vp90-2-03-size-224x224-224x224-0007.i420
+993cde759158c30dcf0f0a9fdcdfb0d8  vp90-2-03-size-224x224-224x224-0008.i420
+85985ae8d35514d601800a06c8226625  vp90-2-03-size-224x224-224x224-0009.i420
+0eba1d7c193e473586e4a5c87d0e0d21  vp90-2-03-size-224x224-224x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_224x226.vp9
new file mode 100644
index 0000000..7672e82
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_224x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_224x226_vp9_md5
new file mode 100644
index 0000000..b3a8eee
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_224x226_vp9_md5
@@ -0,0 +1,10 @@
+dca556e648a576b3973fbe4b34d0328c  vp90-2-03-size-224x226-224x226-0001.i420
+34a49e4aba4aca5c76ab0f751341c32b  vp90-2-03-size-224x226-224x226-0002.i420
+4b7cc6d500b273efe7e30fc3a3946f74  vp90-2-03-size-224x226-224x226-0003.i420
+1960f0f1edf9196c96b0de742a3cd53c  vp90-2-03-size-224x226-224x226-0004.i420
+3cb7d90178636911c5d53a5f8e75599c  vp90-2-03-size-224x226-224x226-0005.i420
+84b56c60c2282f85102048cc2cf40b88  vp90-2-03-size-224x226-224x226-0006.i420
+3ca34d2978307ec0fca05130d81bcc26  vp90-2-03-size-224x226-224x226-0007.i420
+c15560be737e02ea9d1deeca0af9bb77  vp90-2-03-size-224x226-224x226-0008.i420
+391439789a6aa7bb02d7e699795a9559  vp90-2-03-size-224x226-224x226-0009.i420
+9f681e91cbcbe9920f21236b8ff093c7  vp90-2-03-size-224x226-224x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x196.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x196.vp9
new file mode 100644
index 0000000..e88ffc4
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x196.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x196_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x196_vp9_md5
new file mode 100644
index 0000000..a995846
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x196_vp9_md5
@@ -0,0 +1,10 @@
+4757a31842453f806de2f2256329547e  vp90-2-03-size-226x196-226x196-0001.i420
+fe5fb955a4143091c5bfae7c4a4afe0f  vp90-2-03-size-226x196-226x196-0002.i420
+93766c5a03d71f99afb7705add7b63f0  vp90-2-03-size-226x196-226x196-0003.i420
+30c91162aa6fb0ed3e47325146bb6d8a  vp90-2-03-size-226x196-226x196-0004.i420
+501fe67785b970b1b62c2ae0b36b19ad  vp90-2-03-size-226x196-226x196-0005.i420
+836be5e778e3d20e75c4fcd71f765b3d  vp90-2-03-size-226x196-226x196-0006.i420
+21a9fd5e78212fe71719e173844bc6e6  vp90-2-03-size-226x196-226x196-0007.i420
+81b3919208e345d93dde62740b47dd93  vp90-2-03-size-226x196-226x196-0008.i420
+df010555a929ba88a2f25c6267e3786e  vp90-2-03-size-226x196-226x196-0009.i420
+d2cff8282e5e7a5bbd879c73df0670c3  vp90-2-03-size-226x196-226x196-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x198.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x198.vp9
new file mode 100644
index 0000000..fa201ed
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x198.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x198_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x198_vp9_md5
new file mode 100644
index 0000000..3c4d3f5b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x198_vp9_md5
@@ -0,0 +1,10 @@
+b97087eb8c53cf56dc44576912654fb2  vp90-2-03-size-226x198-226x198-0001.i420
+219bb68a59dc166806a5b5689a943b66  vp90-2-03-size-226x198-226x198-0002.i420
+67b2ec19dd3b74d828b51912c25249d6  vp90-2-03-size-226x198-226x198-0003.i420
+73dd9625538e10a0f94d31ac9fe3db23  vp90-2-03-size-226x198-226x198-0004.i420
+51e68f201130da18beb0cb27adcf6fa9  vp90-2-03-size-226x198-226x198-0005.i420
+455d9753b3c0ac5ad7d9da022f69acd0  vp90-2-03-size-226x198-226x198-0006.i420
+60a8905a63db4cdd2560583fb6415030  vp90-2-03-size-226x198-226x198-0007.i420
+48c156f4b2c9f936487b43713a4573fd  vp90-2-03-size-226x198-226x198-0008.i420
+a5c8f4190cb34b3ecd42ca8e09bf1646  vp90-2-03-size-226x198-226x198-0009.i420
+233a5d5187137e047993532fc2e725d3  vp90-2-03-size-226x198-226x198-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x200.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x200.vp9
new file mode 100644
index 0000000..a61270b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x200.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x200_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x200_vp9_md5
new file mode 100644
index 0000000..edab982
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x200_vp9_md5
@@ -0,0 +1,10 @@
+0ae27db338f73f37eaed806b1c789593  vp90-2-03-size-226x200-226x200-0001.i420
+3f69273752f43699a3bc7b22a88cc3aa  vp90-2-03-size-226x200-226x200-0002.i420
+ce0dfafb59910241d2b1a2275a2c2143  vp90-2-03-size-226x200-226x200-0003.i420
+8d20f404e25766c819ee728858bcbc76  vp90-2-03-size-226x200-226x200-0004.i420
+67bc5604c5b0f6c3484b605c1f93c83a  vp90-2-03-size-226x200-226x200-0005.i420
+1c82def3a06430d205cce0db7b5714de  vp90-2-03-size-226x200-226x200-0006.i420
+654d7a676e3b8b64541ed8cdefbd7286  vp90-2-03-size-226x200-226x200-0007.i420
+6c80c78c7b652c5b3b117a0960e89951  vp90-2-03-size-226x200-226x200-0008.i420
+ae73e3c69ec6747c5234d58c5e1e36eb  vp90-2-03-size-226x200-226x200-0009.i420
+e40d716efd8caf2d4004d299fb914328  vp90-2-03-size-226x200-226x200-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x202.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x202.vp9
new file mode 100644
index 0000000..28732e2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x202.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x202_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x202_vp9_md5
new file mode 100644
index 0000000..80e7ac2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x202_vp9_md5
@@ -0,0 +1,10 @@
+0cd2876640e71de3a6df7839bd6f0b51  vp90-2-03-size-226x202-226x202-0001.i420
+f887db6839c0cddd1ea9ae6bfd2cc16d  vp90-2-03-size-226x202-226x202-0002.i420
+ff2a890cf4c4973bf181ba8424c2eadc  vp90-2-03-size-226x202-226x202-0003.i420
+f69f2e4f3036a21deb43a0bf4b95771f  vp90-2-03-size-226x202-226x202-0004.i420
+93f511739c19f1a3b356dda39d945c93  vp90-2-03-size-226x202-226x202-0005.i420
+7f79633c93765b504fef0324bd10fdba  vp90-2-03-size-226x202-226x202-0006.i420
+d6c53d3937c9a40b227b4486452e0b33  vp90-2-03-size-226x202-226x202-0007.i420
+4e26625e8997ad6fe08ae68fbdfdbfd7  vp90-2-03-size-226x202-226x202-0008.i420
+3bf4c8ac0279351bf904cf57b0fc13c1  vp90-2-03-size-226x202-226x202-0009.i420
+12d64d856025185fa9e610dfa62b05af  vp90-2-03-size-226x202-226x202-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x208.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x208.vp9
new file mode 100644
index 0000000..f88a8b8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x208.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x208_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x208_vp9_md5
new file mode 100644
index 0000000..364227a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x208_vp9_md5
@@ -0,0 +1,10 @@
+6006cac6628cf9e7cea58aec07471b06  vp90-2-03-size-226x208-226x208-0001.i420
+f7e994921248b6933920c984880ec96c  vp90-2-03-size-226x208-226x208-0002.i420
+c0aeeb9d2009538d8d5e837f45e1542d  vp90-2-03-size-226x208-226x208-0003.i420
+7dacf9d00e85bd52045eb47bae5225b3  vp90-2-03-size-226x208-226x208-0004.i420
+024fd008a099ae954e38a3f0a8ebb6c9  vp90-2-03-size-226x208-226x208-0005.i420
+fb6c368a1b3578ab59aa30e0b5cc4853  vp90-2-03-size-226x208-226x208-0006.i420
+07815251f7020b627c365a7a7be694c7  vp90-2-03-size-226x208-226x208-0007.i420
+db8b8f48f3693867d2bd8208cf4f929a  vp90-2-03-size-226x208-226x208-0008.i420
+88b42d943c0978d832333a8a3f7b6bbc  vp90-2-03-size-226x208-226x208-0009.i420
+7aa760190f9328ba4f6fa87d1d9e8d3e  vp90-2-03-size-226x208-226x208-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x210.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x210.vp9
new file mode 100644
index 0000000..2a60796
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x210.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x210_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x210_vp9_md5
new file mode 100644
index 0000000..f4afd83
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x210_vp9_md5
@@ -0,0 +1,10 @@
+a6c1b7686202f5cc64335f92be595309  vp90-2-03-size-226x210-226x210-0001.i420
+3e573d4c693a39c5d6cd46b8873e99bb  vp90-2-03-size-226x210-226x210-0002.i420
+d2388f6f641c8ddec98f11493f1a1390  vp90-2-03-size-226x210-226x210-0003.i420
+16473e33532ebc8de2f02077c406346b  vp90-2-03-size-226x210-226x210-0004.i420
+6c75d1c01276838fce40837e373f49db  vp90-2-03-size-226x210-226x210-0005.i420
+b718e7445e2b08dde78fa7f30be01346  vp90-2-03-size-226x210-226x210-0006.i420
+2f556ed5afd60b1bbae76984ce073107  vp90-2-03-size-226x210-226x210-0007.i420
+4e5d59daed044c39a14c35f18cb4fb7a  vp90-2-03-size-226x210-226x210-0008.i420
+c14901a9906ffcd0eb1efc068ce32941  vp90-2-03-size-226x210-226x210-0009.i420
+3d73b7f87bcd16c1ec565b5cc8d0fe93  vp90-2-03-size-226x210-226x210-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x224.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x224.vp9
new file mode 100644
index 0000000..8735e4d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x224.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x224_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x224_vp9_md5
new file mode 100644
index 0000000..24df8e0
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x224_vp9_md5
@@ -0,0 +1,10 @@
+80fb3a643384386beadc0991f171669d  vp90-2-03-size-226x224-226x224-0001.i420
+65a4a51163f49a75f8eeecd94cb2ba47  vp90-2-03-size-226x224-226x224-0002.i420
+d5b2aac9889d2991b83fd4360ada0258  vp90-2-03-size-226x224-226x224-0003.i420
+7958ff5535358567ea7df351d78256a7  vp90-2-03-size-226x224-226x224-0004.i420
+7e7413b9a61967d0ade07b81944e9a15  vp90-2-03-size-226x224-226x224-0005.i420
+40a008016adbf9673adbbc4c0edb4454  vp90-2-03-size-226x224-226x224-0006.i420
+fef7b5e2809ef79917ab394a067ef4be  vp90-2-03-size-226x224-226x224-0007.i420
+91ee2360faf46a25b95927c55eea603f  vp90-2-03-size-226x224-226x224-0008.i420
+a47f14a80a529f79f97accbe23188046  vp90-2-03-size-226x224-226x224-0009.i420
+3613bcd41ff13006fbba3bd0087c44f4  vp90-2-03-size-226x224-226x224-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x226.vp9 b/tests/tests/media/res/raw/vp90_2_03_size_226x226.vp9
new file mode 100644
index 0000000..c7f8202
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x226.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_03_size_226x226_vp9_md5 b/tests/tests/media/res/raw/vp90_2_03_size_226x226_vp9_md5
new file mode 100644
index 0000000..24f20a6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_03_size_226x226_vp9_md5
@@ -0,0 +1,10 @@
+f2370fc802dafdf5082beffc1907a9c6  vp90-2-03-size-226x226-226x226-0001.i420
+aad6de7b986234a1d621935b272501c9  vp90-2-03-size-226x226-226x226-0002.i420
+8a6d3784e22e3b4f735e78916fbc3821  vp90-2-03-size-226x226-226x226-0003.i420
+0c4afce19c43fdf3bb1b972810cc9126  vp90-2-03-size-226x226-226x226-0004.i420
+814a68dd76a3135221131988910f51ba  vp90-2-03-size-226x226-226x226-0005.i420
+b2379c4b28dca10e67ac58631f9731c0  vp90-2-03-size-226x226-226x226-0006.i420
+b16fd651884340a428cea3fe0ac18ba6  vp90-2-03-size-226x226-226x226-0007.i420
+cb65cd4c421cfd6a19fb123ec27abbe6  vp90-2-03-size-226x226-226x226-0008.i420
+7f1d2686b9808de8ecc723b18136d57d  vp90-2-03-size-226x226-226x226-0009.i420
+da7fd4bff4b6db0221c42492876c5c4d  vp90-2-03-size-226x226-226x226-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_06_bilinear.vp9 b/tests/tests/media/res/raw/vp90_2_06_bilinear.vp9
new file mode 100644
index 0000000..a492d03
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_06_bilinear.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_06_bilinear_vp9_md5 b/tests/tests/media/res/raw/vp90_2_06_bilinear_vp9_md5
new file mode 100644
index 0000000..25231b98
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_06_bilinear_vp9_md5
@@ -0,0 +1,10 @@
+818a5af531c921ae58dfedc75234f3c5  -352x288-0001.i420
+f863f8c68b5c87c721d345c5a894336d  -352x288-0002.i420
+3f1213e44db416530bc0717f0a795b5d  -352x288-0003.i420
+4b99c16a62c3d6687c78236fa13e1f41  -352x288-0004.i420
+80f23a3f04215dd7542128e7c53d68d0  -352x288-0005.i420
+b40b7aa34a77fe773d82d75b5bdd9c13  -352x288-0006.i420
+dd4af6263d20bbaf9afedb6695c1ba67  -352x288-0007.i420
+1f2ccf88f15c10e3c27b2368dacc3727  -352x288-0008.i420
+232b027c4e9b598f50d078bb7b7a165e  -352x288-0009.i420
+2b44367332aa0fe42362d61f18e7f8dd  -352x288-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_07_frame_parallel.vp9 b/tests/tests/media/res/raw/vp90_2_07_frame_parallel.vp9
new file mode 100644
index 0000000..2c80a2d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_07_frame_parallel.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1.vp9 b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1.vp9
new file mode 100644
index 0000000..10f6eb7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1_vp9_md5 b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1_vp9_md5
new file mode 100644
index 0000000..a6261c8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_1_vp9_md5
@@ -0,0 +1,40 @@
+b5d461894f957709576d15f6dce3d69e  vp90-2-07-frame_parallel-1.webm-352x288-0001.i420
+54e45dfe575d9843c198270f62154c09  vp90-2-07-frame_parallel-1.webm-352x288-0002.i420
+c3798fe06d2c0adbb43410b76c67c0cd  vp90-2-07-frame_parallel-1.webm-352x288-0003.i420
+2cc4ad256a586ff2be650adce4d7f332  vp90-2-07-frame_parallel-1.webm-352x288-0004.i420
+3e63839f0aaedfeaf71cf2868e506bdd  vp90-2-07-frame_parallel-1.webm-352x288-0005.i420
+ca0a10c9144084231f801fa6f0433eb4  vp90-2-07-frame_parallel-1.webm-352x288-0006.i420
+c920d177c21a8b0dee8fdbce1edfd75c  vp90-2-07-frame_parallel-1.webm-352x288-0007.i420
+6afe32287ff1dcaa42630bbf9fe32bad  vp90-2-07-frame_parallel-1.webm-352x288-0008.i420
+0bc39f7c6fbc1fb18dce622d17b0856e  vp90-2-07-frame_parallel-1.webm-352x288-0009.i420
+6f92688afcd228649627c1757417bfe5  vp90-2-07-frame_parallel-1.webm-352x288-0010.i420
+338920379e1746eff6bc1c53553c400e  vp90-2-07-frame_parallel-1.webm-352x288-0011.i420
+2beb514ca62779c7c20e1dff0ccc496a  vp90-2-07-frame_parallel-1.webm-352x288-0012.i420
+e7b4dcc8437af45f363a3b24439323d2  vp90-2-07-frame_parallel-1.webm-352x288-0013.i420
+10bac4f44ae04e2d9f3219044a273f3c  vp90-2-07-frame_parallel-1.webm-352x288-0014.i420
+45581dbebb5074f698ad6d22d52f02b6  vp90-2-07-frame_parallel-1.webm-352x288-0015.i420
+9480f12b47b834003d6d572b9fdfdda1  vp90-2-07-frame_parallel-1.webm-352x288-0016.i420
+b31f361b8971a56338b3960c18177b7c  vp90-2-07-frame_parallel-1.webm-352x288-0017.i420
+79d631a53008d36f8ff5248a8592ffdc  vp90-2-07-frame_parallel-1.webm-352x288-0018.i420
+0efc005919f5a1cdded77ae91245d3be  vp90-2-07-frame_parallel-1.webm-352x288-0019.i420
+bf0d1144000094b3eb333b3dab466ace  vp90-2-07-frame_parallel-1.webm-352x288-0020.i420
+80c0d7ccfa044dc8fe1967951c4d4fea  vp90-2-07-frame_parallel-1.webm-352x288-0021.i420
+28c8e8c406a804cde7feba37e0fda689  vp90-2-07-frame_parallel-1.webm-352x288-0022.i420
+8bef0cfaa4c298d93d20b88c17ef4864  vp90-2-07-frame_parallel-1.webm-352x288-0023.i420
+9488e35310228d5930fccc4a2ee5a96d  vp90-2-07-frame_parallel-1.webm-352x288-0024.i420
+638394b668015141ba1ff97c89034e32  vp90-2-07-frame_parallel-1.webm-352x288-0025.i420
+85aff2c821b25962d3f72208a5f05992  vp90-2-07-frame_parallel-1.webm-352x288-0026.i420
+ec68bb46a7ef2e90c07b7dcfb406eb20  vp90-2-07-frame_parallel-1.webm-352x288-0027.i420
+7b0f3a57f320b1fe33ad5ac03ba0e568  vp90-2-07-frame_parallel-1.webm-352x288-0028.i420
+da461e5510f591c17675d9d7ec9532c4  vp90-2-07-frame_parallel-1.webm-352x288-0029.i420
+d2997aa173f757dd2ef78b58f5d5a109  vp90-2-07-frame_parallel-1.webm-352x288-0030.i420
+ff70094752edf348767a47db71d2dfd0  vp90-2-07-frame_parallel-1.webm-352x288-0031.i420
+52ec9a87ad6df24714fbe6b3384b3f10  vp90-2-07-frame_parallel-1.webm-352x288-0032.i420
+665a0ee3f3ce1a100aae8ff12e8f5193  vp90-2-07-frame_parallel-1.webm-352x288-0033.i420
+98e6fcabfa61b3ca20844c4ce02cdc59  vp90-2-07-frame_parallel-1.webm-352x288-0034.i420
+8e9a1c517df8a280b27e525e3b60ec6f  vp90-2-07-frame_parallel-1.webm-352x288-0035.i420
+58701ab08edeed3f9f969742b64dbb35  vp90-2-07-frame_parallel-1.webm-352x288-0036.i420
+d901de4fdc5fc2352578116bacefade2  vp90-2-07-frame_parallel-1.webm-352x288-0037.i420
+3b9d9902ea331b3fb5ceb255e66731b3  vp90-2-07-frame_parallel-1.webm-352x288-0038.i420
+3ac2e9b87a373667686c82fc7f14e6be  vp90-2-07-frame_parallel-1.webm-352x288-0039.i420
+fe198064dd4e6ef3ef829ba41c92d002  vp90-2-07-frame_parallel-1.webm-352x288-0040.i420
diff --git a/tests/tests/media/res/raw/vp90_2_07_frame_parallel_vp9_md5 b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_vp9_md5
new file mode 100644
index 0000000..7e598ae
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_07_frame_parallel_vp9_md5
@@ -0,0 +1,10 @@
+4480e19849cb7b042355a42011fa2d89  vp90-2-07-frame_parallel-352x240-0001.i420
+1d48490e61c0109b301938facb648987  vp90-2-07-frame_parallel-352x240-0002.i420
+9c9140e23a56114ea3cc9bae01c6f2be  vp90-2-07-frame_parallel-352x240-0003.i420
+cbdd934532bd9c9c27079d17e570e4af  vp90-2-07-frame_parallel-352x240-0004.i420
+db86f11f02c0936371f59a292e32976d  vp90-2-07-frame_parallel-352x240-0005.i420
+6fc5f675eb7e1ccdfa5230208dcbc608  vp90-2-07-frame_parallel-352x240-0006.i420
+39fcd15c8cf524a9acce7a66982acec5  vp90-2-07-frame_parallel-352x240-0007.i420
+8c24475c41ec9d5aaa7954f997da12c4  vp90-2-07-frame_parallel-352x240-0008.i420
+5b9747332e303f62b73d4cd2728ac93c  vp90-2-07-frame_parallel-352x240-0009.i420
+706f3fc0042b9e6e8b91318ecd55fce8  vp90-2-07-frame_parallel-352x240-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x2.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x2.vp9
new file mode 100644
index 0000000..de3593a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x2.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel.vp9
new file mode 100644
index 0000000..1895056
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel_vp9_md5
new file mode 100644
index 0000000..7e6b4f2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_frame_parallel_vp9_md5
@@ -0,0 +1,10 @@
+124dcaf4393bbc676cefc1dcfc1474b9  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0001.i420
+02e0c145da3e3c711f13dad6d5d9f2ec  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0002.i420
+bd276b44124d01ea89cb428a3532a87e  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0003.i420
+fc1eb96ba3b93382a8cf3dee39928d85  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0004.i420
+0b7b92b084684377795f6fcc549f7677  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0005.i420
+208972b2d34f0a7a6616570d8279c1f1  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0006.i420
+33f15b325f9367cf1f58e2e25ccc7bed  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0007.i420
+d7f75036195e89dcbcaba566c1d6cad8  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0008.i420
+bdc3a5b228f0afa3f969d5f99685a501  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0009.i420
+d436084146d6be84df15f5fb94067d53  /tmp/test-vector/vp90-2-08-tile_1x2_frame_parallel-1920x1080-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x2_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_vp9_md5
new file mode 100644
index 0000000..f979f7f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x2_vp9_md5
@@ -0,0 +1,10 @@
+124dcaf4393bbc676cefc1dcfc1474b9  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0001.i420
+5f3357dc102c9db11e7b68d277f31f99  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0002.i420
+a5fb34b4a52fbc7b8290bffe988ffb01  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0003.i420
+1405fa1086ac63d4f5e8ed1ca0ad192a  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0004.i420
+0ead62c1d7c7c44f316e601d8fea16ba  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0005.i420
+204e05b399becce6e936bb3ac739fbe3  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0006.i420
+a27c70e46f6b2c40d6d0a13befede3ac  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0007.i420
+71434072992ec693ae809086760cad22  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0008.i420
+790a525234048c0645cc81f6a042c9c3  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0009.i420
+751b37a7b9401a5ca30dc2673070f881  /tmp/test-vector/vp90-2-08-tile_1x2-1920x1080-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x4.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x4.vp9
new file mode 100644
index 0000000..2cc32ae
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x4.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel.vp9
new file mode 100644
index 0000000..d712a9c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel_vp9_md5
new file mode 100644
index 0000000..0541f98
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_frame_parallel_vp9_md5
@@ -0,0 +1,10 @@
+c8a7f0299fb945318bbb6fd531885339  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0001.i420
+88001dece48c52b0f34afc9137915c9e  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0002.i420
+71c3bc238c76f1e3a81bc70aa7dcacfc  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0003.i420
+32726efd04e67dc09c055481f0189c76  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0004.i420
+7c8fa7372885d16b73f79cbddfd7d45c  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0005.i420
+0d9a3324f574bccd9903ee040eee1787  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0006.i420
+630fb9507a52803b50ea959a36ff60b8  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0007.i420
+d5d7b249db773ec3c5b49567aff761e9  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0008.i420
+b480f582b52d291aeffb97e6d572731b  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0009.i420
+be72a4c2f29317441344cc4d73b24333  /tmp/test-vector/vp90-2-08-tile_1x4_frame_parallel-1920x1080-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x4_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_vp9_md5
new file mode 100644
index 0000000..23297f5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x4_vp9_md5
@@ -0,0 +1,10 @@
+c8a7f0299fb945318bbb6fd531885339  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0001.i420
+22dde3e7feb2177aa350db7331e8fa8f  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0002.i420
+ba644eea2bd5cded05a7b82224a02d30  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0003.i420
+0611f83948b22eb4bd5973fa0485dcda  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0004.i420
+a8eea6193af51dbd06d953165b3de261  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0005.i420
+1e76d8ec66941c9185e0747307a1496c  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0006.i420
+d8404c3e80c2773173e362ff622b6f3c  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0007.i420
+beed5600864a9b961c983d7a7a670bc1  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0008.i420
+9efbe9228f6a437fe450215f711ea429  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0009.i420
+1b65f47a5c11c5b763123d337482bd92  /tmp/test-vector/vp90-2-08-tile_1x4-1920x1080-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x8.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x8.vp9
new file mode 100644
index 0000000..4e9374f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x8.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel.vp9
new file mode 100644
index 0000000..ba4e864
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel_vp9_md5
new file mode 100644
index 0000000..f36f297
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_frame_parallel_vp9_md5
@@ -0,0 +1,10 @@
+f91ceda125d592a3f9537d02df06c4f3  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0001.i420
+563dae097075cd4002b16ffb2be42cf2  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0002.i420
+1f035d79632516b58c56813c113e0f23  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0003.i420
+0db334dafa73ec37699a96e21bf065d0  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0004.i420
+445a1d62a17f7362c1a14179bededcab  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0005.i420
+4c80d03262518f957c54afd6e02d3610  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0006.i420
+bc6be97c7e509af0903509a260f5ccb6  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0007.i420
+27a679a8bbf2eef3eb1dc6cb221ec467  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0008.i420
+eb3b064727f265bd29407f334a51c1ab  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0009.i420
+3e0caeeef59797f9ec278e190170c285  /tmp/vids/vp90-2-08-tile_1x8_frame_parallel-3840x2160-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_1x8_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_vp9_md5
new file mode 100644
index 0000000..a13a4d7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_1x8_vp9_md5
@@ -0,0 +1,10 @@
+f91ceda125d592a3f9537d02df06c4f3  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0001.i420
+a911be78a743ed0f21463bfb82efbd44  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0002.i420
+85d7cddba48b9e26b089da7f40fd4c71  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0003.i420
+39241fe3e171fafbc95966c03042699d  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0004.i420
+7b8500c53fce2702d204b6fc888f33fb  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0005.i420
+8197c61dcecdbd975fe54771f34c5df2  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0006.i420
+f28ebf18412521df51b9d6a3ffd44f4b  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0007.i420
+0d576800a02952e825f1721fc13ac695  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0008.i420
+0eb34a14d7a89ee4c951759a35673b13  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0009.i420
+11fb21038d63e3b431f92e0a4152c2f4  /tmp/vids/vp90-2-08-tile_1x8-3840x2160-0010.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_4x1.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_4x1.vp9
new file mode 100644
index 0000000..e4f9580
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_4x1.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_4x1_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_4x1_vp9_md5
new file mode 100644
index 0000000..85d3f2a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_4x1_vp9_md5
@@ -0,0 +1,5 @@
+82fe82552fc693418e68f7757c67bbcb  vp90-2-08-tile-4x1-1920x1080-0001.i420
+28db6328c54d2dbe7e9efae5ca58cec8  vp90-2-08-tile-4x1-1920x1080-0002.i420
+72f6459dd217ddd05f42cd9e8d6f689f  vp90-2-08-tile-4x1-1920x1080-0003.i420
+12eeebc1533f812d01df0e2b2b8cf0f3  vp90-2-08-tile-4x1-1920x1080-0004.i420
+7ddc1f11bb28f6ad235832e6a1bb88dd  vp90-2-08-tile-4x1-1920x1080-0005.i420
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_4x4.vp9 b/tests/tests/media/res/raw/vp90_2_08_tile_4x4.vp9
new file mode 100644
index 0000000..99e18c7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_4x4.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_08_tile_4x4_vp9_md5 b/tests/tests/media/res/raw/vp90_2_08_tile_4x4_vp9_md5
new file mode 100644
index 0000000..5bb175c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_08_tile_4x4_vp9_md5
@@ -0,0 +1,5 @@
+a3b9b715a7e2aed15430faabb3c8b7b3  vp90-2-08-tile-4x4-1920x1080-0001.i420
+85fa2105aa554e680056d1a413ac9673  vp90-2-08-tile-4x4-1920x1080-0002.i420
+4abb371be22d7914bb62b30d901c30ce  vp90-2-08-tile-4x4-1920x1080-0003.i420
+83c2528204ae3fd4d4cc8fc67b641d3a  vp90-2-08-tile-4x4-1920x1080-0004.i420
+86fcc862b8c8d64690ba3c4a6bff9f74  vp90-2-08-tile-4x4-1920x1080-0005.i420
diff --git a/tests/tests/media/res/raw/vp90_2_09_aq2.vp9 b/tests/tests/media/res/raw/vp90_2_09_aq2.vp9
new file mode 100644
index 0000000..26c09a5
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_aq2.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_09_aq2_vp9_md5 b/tests/tests/media/res/raw/vp90_2_09_aq2_vp9_md5
new file mode 100644
index 0000000..57ce2c8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_aq2_vp9_md5
@@ -0,0 +1,100 @@
+7fd2573f979a4c0fcc74c6ed37599738  vp90-2-09-aq2-352x240-0001.i420
+c2fba96de0561d78d96425813bdf0da0  vp90-2-09-aq2-352x240-0002.i420
+108b4bfeae261da9758675bce8b4645f  vp90-2-09-aq2-352x240-0003.i420
+43b6e3bb1c3f6d15033f16fbd4355265  vp90-2-09-aq2-352x240-0004.i420
+e5a63b53ba5c19370c6f5fdb812014b5  vp90-2-09-aq2-352x240-0005.i420
+de4aa11cfd57d3fa11c8e29faec64bea  vp90-2-09-aq2-352x240-0006.i420
+b70e555bc41eafa68db19d81780fe7b9  vp90-2-09-aq2-352x240-0007.i420
+8a49e3307faef41ecfecfdaa29f48d1f  vp90-2-09-aq2-352x240-0008.i420
+ed01509dcb01ba6644137e7f0f588f13  vp90-2-09-aq2-352x240-0009.i420
+15630dcfe0ec0f27abace3e2ac80d47a  vp90-2-09-aq2-352x240-0010.i420
+2f023d334f0d0d7ea7724ddd075b41a3  vp90-2-09-aq2-352x240-0011.i420
+3fd72535813e4943d1e4b19f7e554b00  vp90-2-09-aq2-352x240-0012.i420
+360db62794959e018a04c3650e832d60  vp90-2-09-aq2-352x240-0013.i420
+33638c46202958cabd78356f18101b88  vp90-2-09-aq2-352x240-0014.i420
+d8a3d7541654307f3b500cb6399fccd1  vp90-2-09-aq2-352x240-0015.i420
+cd2a41d7d0f21c02919ffb87b9510b55  vp90-2-09-aq2-352x240-0016.i420
+54b8f6b3d7e2edb67db7c3aa7f5a973b  vp90-2-09-aq2-352x240-0017.i420
+ddabc76c8b2af158e5feed0f48106429  vp90-2-09-aq2-352x240-0018.i420
+b22c40581501676d588a77b502cb5e48  vp90-2-09-aq2-352x240-0019.i420
+e25c4976462fe37b0119e719e7a9a65b  vp90-2-09-aq2-352x240-0020.i420
+1fcf289ba81a469926b63e9fa70fc184  vp90-2-09-aq2-352x240-0021.i420
+6a7392c22ffac7c6a4bfe7012e8dfa29  vp90-2-09-aq2-352x240-0022.i420
+9b74dc670c67073a582b3c8d390caaf5  vp90-2-09-aq2-352x240-0023.i420
+23b18dc9b7eb27b55e0068c1d75de8ad  vp90-2-09-aq2-352x240-0024.i420
+0a94a263b90e08e88909deafd5c42b7c  vp90-2-09-aq2-352x240-0025.i420
+9b940506b41816d2030f7a2089d83ea3  vp90-2-09-aq2-352x240-0026.i420
+da88cae2ec9324ad19365871ec893d45  vp90-2-09-aq2-352x240-0027.i420
+323cf97cddde5a9cea5f338b7ab17860  vp90-2-09-aq2-352x240-0028.i420
+455506b023df603e494bcc36ffcce179  vp90-2-09-aq2-352x240-0029.i420
+7dc8cf924ca17b6f19c7ed5e7d584835  vp90-2-09-aq2-352x240-0030.i420
+88e4c47e343182051fef005676fc3112  vp90-2-09-aq2-352x240-0031.i420
+e4891dfcc239d80f3240b85fe48f3957  vp90-2-09-aq2-352x240-0032.i420
+e559abcb6717ca8b211159010beebef8  vp90-2-09-aq2-352x240-0033.i420
+3b96d340f65e415d40d60bf6a3bedefc  vp90-2-09-aq2-352x240-0034.i420
+51131241975195394fb3eaa13ca1b43f  vp90-2-09-aq2-352x240-0035.i420
+ceefc4774251000943f2d58c68f2b3d3  vp90-2-09-aq2-352x240-0036.i420
+76524ef8a7f1ab5199124e8bff7bc559  vp90-2-09-aq2-352x240-0037.i420
+906cf4fc07aacb1f0a3ceaf7eeda2e74  vp90-2-09-aq2-352x240-0038.i420
+c7ad9d7bc30af316285b962b9eda4c9a  vp90-2-09-aq2-352x240-0039.i420
+424a7133c0bb45a2601733a39f8d70fa  vp90-2-09-aq2-352x240-0040.i420
+e76eac1e8e9529609ad1bf3e4c44e4d0  vp90-2-09-aq2-352x240-0041.i420
+e238dcef853fed9f7322cb1d73dceef5  vp90-2-09-aq2-352x240-0042.i420
+a0f2d7cd7f628fca6992ccb2ca418133  vp90-2-09-aq2-352x240-0043.i420
+4d07e59c0935554b624409bd904264ef  vp90-2-09-aq2-352x240-0044.i420
+d0944fdf52b02c4ff8fd7fcb944ae00c  vp90-2-09-aq2-352x240-0045.i420
+f719c346201b393262d4764bc989c4fd  vp90-2-09-aq2-352x240-0046.i420
+951d18cb2791c55ebed8321dba537eb9  vp90-2-09-aq2-352x240-0047.i420
+f764f5aaac4f19b131377e16d034de9a  vp90-2-09-aq2-352x240-0048.i420
+871f7a2201dd951ba541625219a8f000  vp90-2-09-aq2-352x240-0049.i420
+05e9bf3f38aacd65a796400247c8d149  vp90-2-09-aq2-352x240-0050.i420
+7bdc6fc1fe6a1e24cb952e10ed19ab68  vp90-2-09-aq2-352x240-0051.i420
+a92e8a9e7ba4d24adcf63ab897057e68  vp90-2-09-aq2-352x240-0052.i420
+7ec84b978b27052954fac85142582c2c  vp90-2-09-aq2-352x240-0053.i420
+10153d3889093a27aa2aa7a4380d6372  vp90-2-09-aq2-352x240-0054.i420
+1313e1ab4c7c6c01b3b25ff7fc84da9f  vp90-2-09-aq2-352x240-0055.i420
+810d9122895dcb90fae58be03af9980b  vp90-2-09-aq2-352x240-0056.i420
+f77fb637d12d958099d534f4a1689eb7  vp90-2-09-aq2-352x240-0057.i420
+3570f0094d3f06efa648ff4d9db2a25d  vp90-2-09-aq2-352x240-0058.i420
+8f22721b7e56e04d41d2af7cbf2ca349  vp90-2-09-aq2-352x240-0059.i420
+fee5d638fa94a6d1a2fa1dfc86a3f131  vp90-2-09-aq2-352x240-0060.i420
+c9e2f58d5f3f8c3ad527e9bd53e12372  vp90-2-09-aq2-352x240-0061.i420
+6507534d0c9fbd22c76f1f7753f000ce  vp90-2-09-aq2-352x240-0062.i420
+cd944cf2a7dbd30ab4fc4b99f4041379  vp90-2-09-aq2-352x240-0063.i420
+15bbc0674190eeb1112a27746dce3726  vp90-2-09-aq2-352x240-0064.i420
+7270c42f643a9f27095dade9f1b6b62e  vp90-2-09-aq2-352x240-0065.i420
+7f47919091ccd7072a2068904f582679  vp90-2-09-aq2-352x240-0066.i420
+1e3c77d769a978bf9dc9188c0f1ed105  vp90-2-09-aq2-352x240-0067.i420
+4a4613749f272b7a04e6ead37844f73c  vp90-2-09-aq2-352x240-0068.i420
+8967e0f52af43110004dce3f78c8fc75  vp90-2-09-aq2-352x240-0069.i420
+e3b979ec8ed4e389abaeea149b86b407  vp90-2-09-aq2-352x240-0070.i420
+fd3c72c5249c214a85e0957279090781  vp90-2-09-aq2-352x240-0071.i420
+7fe861180df75e21f4b8937ae506d601  vp90-2-09-aq2-352x240-0072.i420
+8804a39483b5a8d7ae03003ee8b3152a  vp90-2-09-aq2-352x240-0073.i420
+30a1b0bd147277f8fc50de11c2c8dc93  vp90-2-09-aq2-352x240-0074.i420
+7cb788efedd325f45bd4785f89432115  vp90-2-09-aq2-352x240-0075.i420
+a162c8ab7fa0dafdc3313a69bc7f1e38  vp90-2-09-aq2-352x240-0076.i420
+83905de481bd1cafa16cd96698337c25  vp90-2-09-aq2-352x240-0077.i420
+3d75f99043ea4bf2364844474e180079  vp90-2-09-aq2-352x240-0078.i420
+89975274a8a72af7d2cdee9fbe907852  vp90-2-09-aq2-352x240-0079.i420
+e05c9a7af0ea61d4ef4476de4d7c97cd  vp90-2-09-aq2-352x240-0080.i420
+dfc99210a942a7427033cce9b596e0fa  vp90-2-09-aq2-352x240-0081.i420
+544361eecb8c3b45feb1dbef5c0a39a2  vp90-2-09-aq2-352x240-0082.i420
+7aaae6bbf8af4f7f6556f2285a9d9476  vp90-2-09-aq2-352x240-0083.i420
+485716ddd13576464d1ca47b4859cc22  vp90-2-09-aq2-352x240-0084.i420
+00194b66bafdb6a252852bd087200c6b  vp90-2-09-aq2-352x240-0085.i420
+d21b316ba1006c2381d78e5b7652b12a  vp90-2-09-aq2-352x240-0086.i420
+56506d53dc2333ccddcedb449977ce57  vp90-2-09-aq2-352x240-0087.i420
+0c6787858208959270dde59e38c544ca  vp90-2-09-aq2-352x240-0088.i420
+913b906f645964f57913db70e21aa6d8  vp90-2-09-aq2-352x240-0089.i420
+f9c5d447dd4c060d3610d22b6ff8f1d7  vp90-2-09-aq2-352x240-0090.i420
+ece0a0110c14dccde0ea4d0484b60d38  vp90-2-09-aq2-352x240-0091.i420
+fbcb7e878673c8287a1ed57a6feef818  vp90-2-09-aq2-352x240-0092.i420
+be5aed5dd5538c3ad8c9d88fb4a4207f  vp90-2-09-aq2-352x240-0093.i420
+4c668204dd2c45d039bf7c5f44203803  vp90-2-09-aq2-352x240-0094.i420
+06f9b1207289ed7fbf03c4be3f0349f5  vp90-2-09-aq2-352x240-0095.i420
+26275672bc752789d0a175ca48344643  vp90-2-09-aq2-352x240-0096.i420
+1b56fde58558ec9ae00f24815c13f672  vp90-2-09-aq2-352x240-0097.i420
+ff65dec4cab5d10ea34321f34d369b5e  vp90-2-09-aq2-352x240-0098.i420
+3d419dded34673cf487b39106af08da6  vp90-2-09-aq2-352x240-0099.i420
+ab8a99b2a88bab0238e5d3d3204098e0  vp90-2-09-aq2-352x240-0100.i420
diff --git a/tests/tests/media/res/raw/vp90_2_09_lf_deltas.vp9 b/tests/tests/media/res/raw/vp90_2_09_lf_deltas.vp9
new file mode 100644
index 0000000..72c747b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_lf_deltas.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_09_lf_deltas_vp9_md5 b/tests/tests/media/res/raw/vp90_2_09_lf_deltas_vp9_md5
new file mode 100644
index 0000000..b212aaa
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_lf_deltas_vp9_md5
@@ -0,0 +1,30 @@
+a83c7f4602f595fd09e97f8c8a7277ec  vp90-2-09-lf_deltas-352x240-0001.i420
+53e1a3fd44932883a8dd112bbb0e359f  vp90-2-09-lf_deltas-352x240-0002.i420
+4bb16d168f9f0a7702c31a68bb8ff36c  vp90-2-09-lf_deltas-352x240-0003.i420
+1b2df157913aba96553aaf8d51491bf3  vp90-2-09-lf_deltas-352x240-0004.i420
+9d041532e42fca7a4062cd3e9b75413b  vp90-2-09-lf_deltas-352x240-0005.i420
+0dbac5ca06e13714d10e99042aefe375  vp90-2-09-lf_deltas-352x240-0006.i420
+bb83a507a65d2a640b08f42a77bb37f6  vp90-2-09-lf_deltas-352x240-0007.i420
+176f992d37c7daa36135cddb49398de3  vp90-2-09-lf_deltas-352x240-0008.i420
+c41834f72b3281cf6aaa66fd7416e6c3  vp90-2-09-lf_deltas-352x240-0009.i420
+790d4e6b1609dec782ff978e2003d318  vp90-2-09-lf_deltas-352x240-0010.i420
+449622f741f7577c1d721f2e9eb25091  vp90-2-09-lf_deltas-352x240-0011.i420
+8ef8543f7895c87ab04491b0150628e5  vp90-2-09-lf_deltas-352x240-0012.i420
+88ef626aca4b2bcb8c58a69db20a7b02  vp90-2-09-lf_deltas-352x240-0013.i420
+4b2f7adc2e1872ecdd9ffa7d1f1df4a6  vp90-2-09-lf_deltas-352x240-0014.i420
+7b162660225022ef31e39c34fee3418e  vp90-2-09-lf_deltas-352x240-0015.i420
+2b439a4b846edcc69cdf6075de5ac8fb  vp90-2-09-lf_deltas-352x240-0016.i420
+ba2eb1ba0ed9abf701a53a94c9c626fc  vp90-2-09-lf_deltas-352x240-0017.i420
+9fbec5d5334fd5e917feee756b652d93  vp90-2-09-lf_deltas-352x240-0018.i420
+93b5eb99ea54abc5fa90c5674499e27e  vp90-2-09-lf_deltas-352x240-0019.i420
+04a98408e9b0aed28932ef1dfdcfdb6c  vp90-2-09-lf_deltas-352x240-0020.i420
+9856ba976bed30bc790a3f28e926b092  vp90-2-09-lf_deltas-352x240-0021.i420
+2b0f450e9724cfc57b846148ff876e51  vp90-2-09-lf_deltas-352x240-0022.i420
+163757f3529369b9789ea606387b831d  vp90-2-09-lf_deltas-352x240-0023.i420
+de5ed2aff936c54f3378d0dcc2575d13  vp90-2-09-lf_deltas-352x240-0024.i420
+1f642826b8a6fb111c7c6130481dab89  vp90-2-09-lf_deltas-352x240-0025.i420
+b8e3a77c7d3c5c56f67aa7409fb5404c  vp90-2-09-lf_deltas-352x240-0026.i420
+eb06cb4f471e42d7fc06929a442cca8b  vp90-2-09-lf_deltas-352x240-0027.i420
+53471649a5080b306d2c04a4f7673bdf  vp90-2-09-lf_deltas-352x240-0028.i420
+70996be0cc5d2bd97025015dd50caa99  vp90-2-09-lf_deltas-352x240-0029.i420
+ff3280a8562fdf6697c4a7cb9c1bf0a0  vp90-2-09-lf_deltas-352x240-0030.i420
diff --git a/tests/tests/media/res/raw/vp90_2_09_subpixel_00.vp9 b/tests/tests/media/res/raw/vp90_2_09_subpixel_00.vp9
new file mode 100644
index 0000000..78900f9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_subpixel_00.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_09_subpixel_00_vp9_md5 b/tests/tests/media/res/raw/vp90_2_09_subpixel_00_vp9_md5
new file mode 100644
index 0000000..1144632
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_09_subpixel_00_vp9_md5
@@ -0,0 +1,20 @@
+50233551e96b74ebfdaabbc8a154303c  vp90-hantro-stream-001-320x180-0001.i420
+047109ae2e488be8ee953dca4f09a0e2  vp90-hantro-stream-001-320x180-0002.i420
+5e2ba01240e39566a607f10f0d7eaed3  vp90-hantro-stream-001-320x180-0003.i420
+01f1c635ce56efcc13def2ac3bcccc3f  vp90-hantro-stream-001-320x180-0004.i420
+6e800d75da797409eb2f5b458027b05d  vp90-hantro-stream-001-320x180-0005.i420
+a88b9c2cfad5367d934fd067c2c6452d  vp90-hantro-stream-001-320x180-0006.i420
+a898a33e443dba4c2d61c27caa0fb068  vp90-hantro-stream-001-320x180-0007.i420
+321f16df155169f1fbd117a258b065ed  vp90-hantro-stream-001-320x180-0008.i420
+a71b4df17c37e423a2a6129be8058c66  vp90-hantro-stream-001-320x180-0009.i420
+b168dad8dd0be2e945ada495320e1ec3  vp90-hantro-stream-001-320x180-0010.i420
+4b4e227f6558b9a0e80bbeaebdc50b63  vp90-hantro-stream-001-320x180-0011.i420
+929ad97d05c62b56d908378beeedb68e  vp90-hantro-stream-001-320x180-0012.i420
+f952dc4b2a6e6cdcb0740e67eec87c96  vp90-hantro-stream-001-320x180-0013.i420
+f42500b60e2bbfee44b7e5b4068d9061  vp90-hantro-stream-001-320x180-0014.i420
+802f7975005cc8d77a3801b72ee08ca1  vp90-hantro-stream-001-320x180-0015.i420
+e685e147c9400dd6742c749dc1e18fd6  vp90-hantro-stream-001-320x180-0016.i420
+4080f9db1e9a98478af9c0575a7f31fc  vp90-hantro-stream-001-320x180-0017.i420
+70fcce378d2bade12d2dab44b3fbd4b6  vp90-hantro-stream-001-320x180-0018.i420
+81e539130d2dbb2eb69fe63eb1bb9cbb  vp90-hantro-stream-001-320x180-0019.i420
+2952c0eae93f3dadd1aa84c50d3fd6d2  vp90-hantro-stream-001-320x180-0020.i420
diff --git a/tests/tests/media/res/raw/vp90_2_10_show_existing_frame.vp9 b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame.vp9
new file mode 100644
index 0000000..bd5531e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2.vp9 b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2.vp9
new file mode 100644
index 0000000..665a236
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2_vp9_md5 b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2_vp9_md5
new file mode 100644
index 0000000..51940b6
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame2_vp9_md5
@@ -0,0 +1,16 @@
+382b12c33cd86b38758706b8ebca8a85  -352x288-0001.i420
+799544370b35c91711a5b49a28cf86a8  -352x288-0002.i420
+7218eb4b6d1c7aea4f96ee47ad675e8e  -352x288-0003.i420
+627466200370e6ad60ea570d31be66e3  -352x288-0004.i420
+7dc65a2af108379f2b9265a9a1ea7cf8  -352x288-0005.i420
+c979e2f084760775a567f60f79f28198  -352x288-0006.i420
+fe668a6417aa0543e4ed4d1c67c5cbcb  -352x288-0007.i420
+bf9901e39815fa93cce0ed5b02b2ef2d  -352x288-0008.i420
+627466200370e6ad60ea570d31be66e3  -352x288-0009.i420
+7dc65a2af108379f2b9265a9a1ea7cf8  -352x288-0010.i420
+c979e2f084760775a567f60f79f28198  -352x288-0011.i420
+fe668a6417aa0543e4ed4d1c67c5cbcb  -352x288-0012.i420
+bf9901e39815fa93cce0ed5b02b2ef2d  -352x288-0013.i420
+627466200370e6ad60ea570d31be66e3  -352x288-0014.i420
+7dc65a2af108379f2b9265a9a1ea7cf8  -352x288-0015.i420
+c979e2f084760775a567f60f79f28198  -352x288-0016.i420
diff --git a/tests/tests/media/res/raw/vp90_2_10_show_existing_frame_vp9_md5 b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame_vp9_md5
new file mode 100644
index 0000000..85d421d
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_10_show_existing_frame_vp9_md5
@@ -0,0 +1,13 @@
+18981342ec178e082519451062c3a67f  vp90-2-10-show-existing-frame-352x288-0001.i420
+04ab9dbeac49ec31be58f6e671698e05  vp90-2-10-show-existing-frame-352x288-0002.i420
+4ed58a0ba93a5d97a232a50c5876cda2  vp90-2-10-show-existing-frame-352x288-0003.i420
+a41f00034923e56ba51a0b598acc2e3a  vp90-2-10-show-existing-frame-352x288-0004.i420
+63fa55ae9535ccdf06d44cce8065dda6  vp90-2-10-show-existing-frame-352x288-0005.i420
+a41f00034923e56ba51a0b598acc2e3a  vp90-2-10-show-existing-frame-352x288-0006.i420
+0e4b08e14d919edee2bbff2ecd47de57  vp90-2-10-show-existing-frame-352x288-0007.i420
+0e4b08e14d919edee2bbff2ecd47de57  vp90-2-10-show-existing-frame-352x288-0008.i420
+5d4af03fc3d410413ef2b5a6275528b7  vp90-2-10-show-existing-frame-352x288-0009.i420
+9e932915c67a789f6877e6d3f76d3649  vp90-2-10-show-existing-frame-352x288-0010.i420
+12f2e975c217e7ffcf334524e8acec35  vp90-2-10-show-existing-frame-352x288-0011.i420
+9e932915c67a789f6877e6d3f76d3649  vp90-2-10-show-existing-frame-352x288-0012.i420
+12f2e975c217e7ffcf334524e8acec35  vp90-2-10-show-existing-frame-352x288-0013.i420
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_1.vp9 b/tests/tests/media/res/raw/vp90_2_12_droppable_1.vp9
new file mode 100644
index 0000000..666d187
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_1.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_1_vp9_md5 b/tests/tests/media/res/raw/vp90_2_12_droppable_1_vp9_md5
new file mode 100644
index 0000000..7b1abf8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_1_vp9_md5
@@ -0,0 +1,99 @@
+1839e5db94dc99681d690d544cbe28a4  vp90-2-12-droppable_1.ivf-352x288-0001.i420
+dae2db51b91745edddb33ddbeb4e0988  vp90-2-12-droppable_1.ivf-352x288-0002.i420
+046639dbef310bf9016a54498a3ef0a3  vp90-2-12-droppable_1.ivf-352x288-0003.i420
+947044a5dbc918e8be468c2bc9eaeeaa  vp90-2-12-droppable_1.ivf-352x288-0004.i420
+f96322ba3bf86065829d15c4394a1ab2  vp90-2-12-droppable_1.ivf-352x288-0005.i420
+4dfcf05608b399d56b0b29e3447ac24a  vp90-2-12-droppable_1.ivf-352x288-0006.i420
+b772fd5f5e3221d9c1daf690aeca89e8  vp90-2-12-droppable_1.ivf-352x288-0007.i420
+d8838cf1a4316c6c9ba7f42f8cba205c  vp90-2-12-droppable_1.ivf-352x288-0008.i420
+368f762830ed3d29d642798ff88107bd  vp90-2-12-droppable_1.ivf-352x288-0009.i420
+f3e614a8f67681f814242c75e6ac66f7  vp90-2-12-droppable_1.ivf-352x288-0010.i420
+f49458a915dd853e53c15e52e280085b  vp90-2-12-droppable_1.ivf-352x288-0011.i420
+65cbd3f3f8447d3caf935cddfcb6cb15  vp90-2-12-droppable_1.ivf-352x288-0012.i420
+8f4764c45093050a78b4b6055648cda0  vp90-2-12-droppable_1.ivf-352x288-0013.i420
+16d399bff977cdac0543daffba3a14bd  vp90-2-12-droppable_1.ivf-352x288-0014.i420
+59f16bc632697d20514a55814cf0a9ae  vp90-2-12-droppable_1.ivf-352x288-0015.i420
+058ba53139a3f48883ae4e668177d564  vp90-2-12-droppable_1.ivf-352x288-0016.i420
+85796d9edf6a5fe5d0c804e8b80f4469  vp90-2-12-droppable_1.ivf-352x288-0017.i420
+94b7bf54b3dd8d007cb932c330e4e7cf  vp90-2-12-droppable_1.ivf-352x288-0018.i420
+964732ac0abf132fe8c65a845eeaea39  vp90-2-12-droppable_1.ivf-352x288-0019.i420
+dda8408b95868ea683f921e88ca0f8f4  vp90-2-12-droppable_1.ivf-352x288-0020.i420
+33b008d0b3932abd28d1c0d484a89cb0  vp90-2-12-droppable_1.ivf-352x288-0021.i420
+bbf8f8edda10ab20cde304b362f6fc7c  vp90-2-12-droppable_1.ivf-352x288-0022.i420
+6a08c9c1d4444f6b706a9193823e4866  vp90-2-12-droppable_1.ivf-352x288-0023.i420
+f3cfb225730f103c76083220b55aaf7e  vp90-2-12-droppable_1.ivf-352x288-0024.i420
+aa43de9fd852ffca405f9e1be0c517b9  vp90-2-12-droppable_1.ivf-352x288-0025.i420
+e5bcd2084c06d7e391af0710a3f56f86  vp90-2-12-droppable_1.ivf-352x288-0026.i420
+e16276389746853039a5c1353e3f830e  vp90-2-12-droppable_1.ivf-352x288-0027.i420
+8ecf32a7649dd9df718b5a31512aa17b  vp90-2-12-droppable_1.ivf-352x288-0028.i420
+db63be2b267a77061f40a48a5ad94129  vp90-2-12-droppable_1.ivf-352x288-0029.i420
+94c6a699e9b5382e1e4a30d462d1b05d  vp90-2-12-droppable_1.ivf-352x288-0030.i420
+340102d21a9c8d9119aed97d7bd408ba  vp90-2-12-droppable_1.ivf-352x288-0031.i420
+a369b32d71a6daf9a589614cba76d06c  vp90-2-12-droppable_1.ivf-352x288-0032.i420
+7c6f24525d07f08cfaaf8b57c1b1e0c7  vp90-2-12-droppable_1.ivf-352x288-0033.i420
+f99b35baf3e4f3967ad08b5475041959  vp90-2-12-droppable_1.ivf-352x288-0034.i420
+b1dede9bbe4a9542d10e7e2dcc225208  vp90-2-12-droppable_1.ivf-352x288-0035.i420
+d627915070dd5e6e11d1dff7b1dc4243  vp90-2-12-droppable_1.ivf-352x288-0036.i420
+2f176951d8716e1ac316f30388be269d  vp90-2-12-droppable_1.ivf-352x288-0037.i420
+215828b89c294b2568a575438c75d4e0  vp90-2-12-droppable_1.ivf-352x288-0038.i420
+3a29b4bf698713cbd575e6b14257fc87  vp90-2-12-droppable_1.ivf-352x288-0039.i420
+b930a1eef6838edc9abb769909b87cd9  vp90-2-12-droppable_1.ivf-352x288-0040.i420
+532c260abbd6d1181be3ff7a77f2d350  vp90-2-12-droppable_1.ivf-352x288-0041.i420
+b9ee7c0ab6c7cf8881fe5ed165454638  vp90-2-12-droppable_1.ivf-352x288-0042.i420
+d516f6949c3704ab9f154e3720f5f9ec  vp90-2-12-droppable_1.ivf-352x288-0043.i420
+bf05478086e97057856c3c987b220958  vp90-2-12-droppable_1.ivf-352x288-0044.i420
+92202af7ea355a8d4678e618c0344134  vp90-2-12-droppable_1.ivf-352x288-0045.i420
+ca870c59afab60c5da07e688a89be1a9  vp90-2-12-droppable_1.ivf-352x288-0046.i420
+92429a1763b07d2a0bf843a2953fcc1c  vp90-2-12-droppable_1.ivf-352x288-0047.i420
+1614a4655799cd08875b1271767ce85e  vp90-2-12-droppable_1.ivf-352x288-0048.i420
+2b30362c459109cafcff5f1bb8217e34  vp90-2-12-droppable_1.ivf-352x288-0049.i420
+6568f3dd687762489b7fd2c4a59dd38c  vp90-2-12-droppable_1.ivf-352x288-0050.i420
+6121d029cf4e402f9999a6719b3d6d97  vp90-2-12-droppable_1.ivf-352x288-0051.i420
+085cc85c56e35b4a19b48b502d606ffb  vp90-2-12-droppable_1.ivf-352x288-0052.i420
+63a7dc5d70bd142cb167c20f645a90bb  vp90-2-12-droppable_1.ivf-352x288-0053.i420
+b3ae931ee6f2724304f6a67070a386c0  vp90-2-12-droppable_1.ivf-352x288-0054.i420
+07fcd2b18c1c8a6c46151acff26ce2c0  vp90-2-12-droppable_1.ivf-352x288-0055.i420
+658758a58b92693bafeff41a2424e2a9  vp90-2-12-droppable_1.ivf-352x288-0056.i420
+3619120dfca7b24434ebe8e87936996c  vp90-2-12-droppable_1.ivf-352x288-0057.i420
+17152bbf314be8c30837cbece6fb53cd  vp90-2-12-droppable_1.ivf-352x288-0058.i420
+bc3352c6948fac5a681bf37abcc9b8b4  vp90-2-12-droppable_1.ivf-352x288-0059.i420
+5a4e0a19a7653a5ad120b1f46f9905b4  vp90-2-12-droppable_1.ivf-352x288-0060.i420
+2632db035652049f5340d1e59d577d42  vp90-2-12-droppable_1.ivf-352x288-0061.i420
+95a28f288602ae1f859a02055103aa39  vp90-2-12-droppable_1.ivf-352x288-0062.i420
+3d01e40359a3cfca996908d331492848  vp90-2-12-droppable_1.ivf-352x288-0063.i420
+4b6243114b09dbf590c1250419327b01  vp90-2-12-droppable_1.ivf-352x288-0064.i420
+f9aae29d9168366933f2bcc57a5afcb8  vp90-2-12-droppable_1.ivf-352x288-0065.i420
+6bca12015a807fdf48cda90cbe042ab4  vp90-2-12-droppable_1.ivf-352x288-0066.i420
+7769b6fa16f8c09973d1a2c08cf18dbb  vp90-2-12-droppable_1.ivf-352x288-0067.i420
+3457395b67960b1566007e764b0c0e81  vp90-2-12-droppable_1.ivf-352x288-0068.i420
+0d0ea9bdd5c4b164bbefc31000a28e49  vp90-2-12-droppable_1.ivf-352x288-0069.i420
+9fb6b2afb53b73a658b579beb3008bcd  vp90-2-12-droppable_1.ivf-352x288-0070.i420
+c9a941b87dcdd09afaab68cca0ed668a  vp90-2-12-droppable_1.ivf-352x288-0071.i420
+9a2baa4c442f3ebdf251e9bbef0dbf83  vp90-2-12-droppable_1.ivf-352x288-0072.i420
+ef90237bc4ed3d795ba78c8a4ef9f1d6  vp90-2-12-droppable_1.ivf-352x288-0073.i420
+68cabdcf5d934e279f1c45207e983d43  vp90-2-12-droppable_1.ivf-352x288-0074.i420
+ac5d93877691c05bb581a10bfcd058e5  vp90-2-12-droppable_1.ivf-352x288-0075.i420
+c4e09feb0a88d765c7681c7d427eda87  vp90-2-12-droppable_1.ivf-352x288-0076.i420
+690734960471ab41d5cdf052be87bd30  vp90-2-12-droppable_1.ivf-352x288-0077.i420
+4abaaa7e31a3a6e30b242e42587363d5  vp90-2-12-droppable_1.ivf-352x288-0078.i420
+b9c46f294e7a23b608004ff8aa2b9ea3  vp90-2-12-droppable_1.ivf-352x288-0079.i420
+b6a6a0e45c30de0f03880f753b6e75de  vp90-2-12-droppable_1.ivf-352x288-0080.i420
+c8725906463cb71ed8a64ba8af6a79be  vp90-2-12-droppable_1.ivf-352x288-0081.i420
+d0e28c090e859834a33bc0867a0f7ed7  vp90-2-12-droppable_1.ivf-352x288-0082.i420
+1ad8bf201d9898d562631226a2ef85fa  vp90-2-12-droppable_1.ivf-352x288-0083.i420
+962fe544b1a76bafe8a1b77cd64679ba  vp90-2-12-droppable_1.ivf-352x288-0084.i420
+89f9a77223961cc5ad49a11913ff9774  vp90-2-12-droppable_1.ivf-352x288-0085.i420
+483782bf6d14bbb19c749d58b8535e3e  vp90-2-12-droppable_1.ivf-352x288-0086.i420
+dfbe1b7ecc880ce5da758728f7375d63  vp90-2-12-droppable_1.ivf-352x288-0087.i420
+11a51b22418cc8dad57a20b37dd10630  vp90-2-12-droppable_1.ivf-352x288-0088.i420
+50b90506f9666ccb7dd94b6d59096489  vp90-2-12-droppable_1.ivf-352x288-0089.i420
+101294ecaff7edf5155ddc6cf3595021  vp90-2-12-droppable_1.ivf-352x288-0090.i420
+177e8f9d8aaf40b17d0b677133fc7955  vp90-2-12-droppable_1.ivf-352x288-0091.i420
+c029f78e758a27b8fc4214abf5ddad07  vp90-2-12-droppable_1.ivf-352x288-0092.i420
+45b6df0756e3f98218f4e9f0f33b1f13  vp90-2-12-droppable_1.ivf-352x288-0093.i420
+82d1fd8cc9fa0a072a0fc6177e7f8805  vp90-2-12-droppable_1.ivf-352x288-0094.i420
+bf6c3e8df105fdb82a614f8e8f6d68af  vp90-2-12-droppable_1.ivf-352x288-0095.i420
+2e66eccd31c0e1792f3019c0a7b43af6  vp90-2-12-droppable_1.ivf-352x288-0096.i420
+d7eab4f351bd3c03e873b93afc9b7803  vp90-2-12-droppable_1.ivf-352x288-0097.i420
+f7bc200d54ec154779521311c54a22d1  vp90-2-12-droppable_1.ivf-352x288-0098.i420
+8e2624d762102b6dbe13b7cf20ee1708  vp90-2-12-droppable_1.ivf-352x288-0099.i420
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_2.vp9 b/tests/tests/media/res/raw/vp90_2_12_droppable_2.vp9
new file mode 100644
index 0000000..672af0b
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_2.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_2_vp9_md5 b/tests/tests/media/res/raw/vp90_2_12_droppable_2_vp9_md5
new file mode 100644
index 0000000..4ee5724
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_2_vp9_md5
@@ -0,0 +1,99 @@
+1839e5db94dc99681d690d544cbe28a4  vp90-2-12-droppable_2.ivf-352x288-0001.i420
+dae2db51b91745edddb33ddbeb4e0988  vp90-2-12-droppable_2.ivf-352x288-0002.i420
+046639dbef310bf9016a54498a3ef0a3  vp90-2-12-droppable_2.ivf-352x288-0003.i420
+947044a5dbc918e8be468c2bc9eaeeaa  vp90-2-12-droppable_2.ivf-352x288-0004.i420
+f96322ba3bf86065829d15c4394a1ab2  vp90-2-12-droppable_2.ivf-352x288-0005.i420
+4dfcf05608b399d56b0b29e3447ac24a  vp90-2-12-droppable_2.ivf-352x288-0006.i420
+b772fd5f5e3221d9c1daf690aeca89e8  vp90-2-12-droppable_2.ivf-352x288-0007.i420
+d8838cf1a4316c6c9ba7f42f8cba205c  vp90-2-12-droppable_2.ivf-352x288-0008.i420
+368f762830ed3d29d642798ff88107bd  vp90-2-12-droppable_2.ivf-352x288-0009.i420
+f3e614a8f67681f814242c75e6ac66f7  vp90-2-12-droppable_2.ivf-352x288-0010.i420
+f49458a915dd853e53c15e52e280085b  vp90-2-12-droppable_2.ivf-352x288-0011.i420
+65cbd3f3f8447d3caf935cddfcb6cb15  vp90-2-12-droppable_2.ivf-352x288-0012.i420
+8f4764c45093050a78b4b6055648cda0  vp90-2-12-droppable_2.ivf-352x288-0013.i420
+16d399bff977cdac0543daffba3a14bd  vp90-2-12-droppable_2.ivf-352x288-0014.i420
+59f16bc632697d20514a55814cf0a9ae  vp90-2-12-droppable_2.ivf-352x288-0015.i420
+058ba53139a3f48883ae4e668177d564  vp90-2-12-droppable_2.ivf-352x288-0016.i420
+85796d9edf6a5fe5d0c804e8b80f4469  vp90-2-12-droppable_2.ivf-352x288-0017.i420
+94b7bf54b3dd8d007cb932c330e4e7cf  vp90-2-12-droppable_2.ivf-352x288-0018.i420
+964732ac0abf132fe8c65a845eeaea39  vp90-2-12-droppable_2.ivf-352x288-0019.i420
+dda8408b95868ea683f921e88ca0f8f4  vp90-2-12-droppable_2.ivf-352x288-0020.i420
+33b008d0b3932abd28d1c0d484a89cb0  vp90-2-12-droppable_2.ivf-352x288-0021.i420
+bbf8f8edda10ab20cde304b362f6fc7c  vp90-2-12-droppable_2.ivf-352x288-0022.i420
+6a08c9c1d4444f6b706a9193823e4866  vp90-2-12-droppable_2.ivf-352x288-0023.i420
+f3cfb225730f103c76083220b55aaf7e  vp90-2-12-droppable_2.ivf-352x288-0024.i420
+aa43de9fd852ffca405f9e1be0c517b9  vp90-2-12-droppable_2.ivf-352x288-0025.i420
+e5bcd2084c06d7e391af0710a3f56f86  vp90-2-12-droppable_2.ivf-352x288-0026.i420
+e16276389746853039a5c1353e3f830e  vp90-2-12-droppable_2.ivf-352x288-0027.i420
+8ecf32a7649dd9df718b5a31512aa17b  vp90-2-12-droppable_2.ivf-352x288-0028.i420
+db63be2b267a77061f40a48a5ad94129  vp90-2-12-droppable_2.ivf-352x288-0029.i420
+94c6a699e9b5382e1e4a30d462d1b05d  vp90-2-12-droppable_2.ivf-352x288-0030.i420
+340102d21a9c8d9119aed97d7bd408ba  vp90-2-12-droppable_2.ivf-352x288-0031.i420
+a369b32d71a6daf9a589614cba76d06c  vp90-2-12-droppable_2.ivf-352x288-0032.i420
+7c6f24525d07f08cfaaf8b57c1b1e0c7  vp90-2-12-droppable_2.ivf-352x288-0033.i420
+f99b35baf3e4f3967ad08b5475041959  vp90-2-12-droppable_2.ivf-352x288-0034.i420
+b1dede9bbe4a9542d10e7e2dcc225208  vp90-2-12-droppable_2.ivf-352x288-0035.i420
+d627915070dd5e6e11d1dff7b1dc4243  vp90-2-12-droppable_2.ivf-352x288-0036.i420
+2f176951d8716e1ac316f30388be269d  vp90-2-12-droppable_2.ivf-352x288-0037.i420
+215828b89c294b2568a575438c75d4e0  vp90-2-12-droppable_2.ivf-352x288-0038.i420
+3a29b4bf698713cbd575e6b14257fc87  vp90-2-12-droppable_2.ivf-352x288-0039.i420
+b930a1eef6838edc9abb769909b87cd9  vp90-2-12-droppable_2.ivf-352x288-0040.i420
+532c260abbd6d1181be3ff7a77f2d350  vp90-2-12-droppable_2.ivf-352x288-0041.i420
+b9ee7c0ab6c7cf8881fe5ed165454638  vp90-2-12-droppable_2.ivf-352x288-0042.i420
+d516f6949c3704ab9f154e3720f5f9ec  vp90-2-12-droppable_2.ivf-352x288-0043.i420
+bf05478086e97057856c3c987b220958  vp90-2-12-droppable_2.ivf-352x288-0044.i420
+92202af7ea355a8d4678e618c0344134  vp90-2-12-droppable_2.ivf-352x288-0045.i420
+ca870c59afab60c5da07e688a89be1a9  vp90-2-12-droppable_2.ivf-352x288-0046.i420
+92429a1763b07d2a0bf843a2953fcc1c  vp90-2-12-droppable_2.ivf-352x288-0047.i420
+1614a4655799cd08875b1271767ce85e  vp90-2-12-droppable_2.ivf-352x288-0048.i420
+2b30362c459109cafcff5f1bb8217e34  vp90-2-12-droppable_2.ivf-352x288-0049.i420
+6568f3dd687762489b7fd2c4a59dd38c  vp90-2-12-droppable_2.ivf-352x288-0050.i420
+6121d029cf4e402f9999a6719b3d6d97  vp90-2-12-droppable_2.ivf-352x288-0051.i420
+085cc85c56e35b4a19b48b502d606ffb  vp90-2-12-droppable_2.ivf-352x288-0052.i420
+63a7dc5d70bd142cb167c20f645a90bb  vp90-2-12-droppable_2.ivf-352x288-0053.i420
+b3ae931ee6f2724304f6a67070a386c0  vp90-2-12-droppable_2.ivf-352x288-0054.i420
+07fcd2b18c1c8a6c46151acff26ce2c0  vp90-2-12-droppable_2.ivf-352x288-0055.i420
+658758a58b92693bafeff41a2424e2a9  vp90-2-12-droppable_2.ivf-352x288-0056.i420
+3619120dfca7b24434ebe8e87936996c  vp90-2-12-droppable_2.ivf-352x288-0057.i420
+17152bbf314be8c30837cbece6fb53cd  vp90-2-12-droppable_2.ivf-352x288-0058.i420
+bc3352c6948fac5a681bf37abcc9b8b4  vp90-2-12-droppable_2.ivf-352x288-0059.i420
+5a4e0a19a7653a5ad120b1f46f9905b4  vp90-2-12-droppable_2.ivf-352x288-0060.i420
+2632db035652049f5340d1e59d577d42  vp90-2-12-droppable_2.ivf-352x288-0061.i420
+95a28f288602ae1f859a02055103aa39  vp90-2-12-droppable_2.ivf-352x288-0062.i420
+3d01e40359a3cfca996908d331492848  vp90-2-12-droppable_2.ivf-352x288-0063.i420
+4b6243114b09dbf590c1250419327b01  vp90-2-12-droppable_2.ivf-352x288-0064.i420
+f9aae29d9168366933f2bcc57a5afcb8  vp90-2-12-droppable_2.ivf-352x288-0065.i420
+6bca12015a807fdf48cda90cbe042ab4  vp90-2-12-droppable_2.ivf-352x288-0066.i420
+7769b6fa16f8c09973d1a2c08cf18dbb  vp90-2-12-droppable_2.ivf-352x288-0067.i420
+3457395b67960b1566007e764b0c0e81  vp90-2-12-droppable_2.ivf-352x288-0068.i420
+0d0ea9bdd5c4b164bbefc31000a28e49  vp90-2-12-droppable_2.ivf-352x288-0069.i420
+9fb6b2afb53b73a658b579beb3008bcd  vp90-2-12-droppable_2.ivf-352x288-0070.i420
+c9a941b87dcdd09afaab68cca0ed668a  vp90-2-12-droppable_2.ivf-352x288-0071.i420
+9a2baa4c442f3ebdf251e9bbef0dbf83  vp90-2-12-droppable_2.ivf-352x288-0072.i420
+ef90237bc4ed3d795ba78c8a4ef9f1d6  vp90-2-12-droppable_2.ivf-352x288-0073.i420
+68cabdcf5d934e279f1c45207e983d43  vp90-2-12-droppable_2.ivf-352x288-0074.i420
+ac5d93877691c05bb581a10bfcd058e5  vp90-2-12-droppable_2.ivf-352x288-0075.i420
+c4e09feb0a88d765c7681c7d427eda87  vp90-2-12-droppable_2.ivf-352x288-0076.i420
+690734960471ab41d5cdf052be87bd30  vp90-2-12-droppable_2.ivf-352x288-0077.i420
+4abaaa7e31a3a6e30b242e42587363d5  vp90-2-12-droppable_2.ivf-352x288-0078.i420
+b9c46f294e7a23b608004ff8aa2b9ea3  vp90-2-12-droppable_2.ivf-352x288-0079.i420
+b6a6a0e45c30de0f03880f753b6e75de  vp90-2-12-droppable_2.ivf-352x288-0080.i420
+c8725906463cb71ed8a64ba8af6a79be  vp90-2-12-droppable_2.ivf-352x288-0081.i420
+d0e28c090e859834a33bc0867a0f7ed7  vp90-2-12-droppable_2.ivf-352x288-0082.i420
+1ad8bf201d9898d562631226a2ef85fa  vp90-2-12-droppable_2.ivf-352x288-0083.i420
+962fe544b1a76bafe8a1b77cd64679ba  vp90-2-12-droppable_2.ivf-352x288-0084.i420
+89f9a77223961cc5ad49a11913ff9774  vp90-2-12-droppable_2.ivf-352x288-0085.i420
+483782bf6d14bbb19c749d58b8535e3e  vp90-2-12-droppable_2.ivf-352x288-0086.i420
+dfbe1b7ecc880ce5da758728f7375d63  vp90-2-12-droppable_2.ivf-352x288-0087.i420
+11a51b22418cc8dad57a20b37dd10630  vp90-2-12-droppable_2.ivf-352x288-0088.i420
+50b90506f9666ccb7dd94b6d59096489  vp90-2-12-droppable_2.ivf-352x288-0089.i420
+101294ecaff7edf5155ddc6cf3595021  vp90-2-12-droppable_2.ivf-352x288-0090.i420
+177e8f9d8aaf40b17d0b677133fc7955  vp90-2-12-droppable_2.ivf-352x288-0091.i420
+c029f78e758a27b8fc4214abf5ddad07  vp90-2-12-droppable_2.ivf-352x288-0092.i420
+45b6df0756e3f98218f4e9f0f33b1f13  vp90-2-12-droppable_2.ivf-352x288-0093.i420
+82d1fd8cc9fa0a072a0fc6177e7f8805  vp90-2-12-droppable_2.ivf-352x288-0094.i420
+bf6c3e8df105fdb82a614f8e8f6d68af  vp90-2-12-droppable_2.ivf-352x288-0095.i420
+2e66eccd31c0e1792f3019c0a7b43af6  vp90-2-12-droppable_2.ivf-352x288-0096.i420
+d7eab4f351bd3c03e873b93afc9b7803  vp90-2-12-droppable_2.ivf-352x288-0097.i420
+f7bc200d54ec154779521311c54a22d1  vp90-2-12-droppable_2.ivf-352x288-0098.i420
+8e2624d762102b6dbe13b7cf20ee1708  vp90-2-12-droppable_2.ivf-352x288-0099.i420
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_3.vp9 b/tests/tests/media/res/raw/vp90_2_12_droppable_3.vp9
new file mode 100644
index 0000000..1f26178
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_3.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_12_droppable_3_vp9_md5 b/tests/tests/media/res/raw/vp90_2_12_droppable_3_vp9_md5
new file mode 100644
index 0000000..9fdb07c
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_12_droppable_3_vp9_md5
@@ -0,0 +1,31 @@
+7ab6428314a7bce2ebae83b78acf9d1c  vp90-2-12-droppable_3.ivf-640x480-0001.i420
+373cfc7765ea8038e64d95ff90b6d9e8  vp90-2-12-droppable_3.ivf-640x480-0002.i420
+58d782daf8249542df4a4f0e66994b86  vp90-2-12-droppable_3.ivf-640x480-0003.i420
+38b13b37c460f67dbbda8847a37e5a58  vp90-2-12-droppable_3.ivf-640x480-0004.i420
+902d00e196093fcebad74ef608d7c3ff  vp90-2-12-droppable_3.ivf-640x480-0005.i420
+f3549650a4581de21916b189576b6a52  vp90-2-12-droppable_3.ivf-640x480-0006.i420
+a44d4bf06a241f31d1755ff6a118060a  vp90-2-12-droppable_3.ivf-640x480-0007.i420
+8eeef076eec9eec2861f3376ebf87d0a  vp90-2-12-droppable_3.ivf-640x480-0008.i420
+9a81bf95fc7210526b79c47ff80ae968  vp90-2-12-droppable_3.ivf-640x480-0009.i420
+bf215dfd9b764292de4d064389015e55  vp90-2-12-droppable_3.ivf-640x480-0010.i420
+283b1efdedde5633606d8a5d68097768  vp90-2-12-droppable_3.ivf-640x480-0011.i420
+dbb74ee6ec5f32b9ecb58b73d465be26  vp90-2-12-droppable_3.ivf-640x480-0012.i420
+ca1e21e458f674036addf08a79f6164e  vp90-2-12-droppable_3.ivf-640x480-0013.i420
+24c3b279ecb0559ac146abed5976c54a  vp90-2-12-droppable_3.ivf-640x480-0014.i420
+5f6796e3fa0e85d65b46ba66932ee09c  vp90-2-12-droppable_3.ivf-640x480-0015.i420
+7b22b5642e42e79fcc339ca6652f8f39  vp90-2-12-droppable_3.ivf-640x480-0016.i420
+7478595483ce62a5906f979ad296b6c5  vp90-2-12-droppable_3.ivf-640x480-0017.i420
+55d843f54af65305f7e298013e90a839  vp90-2-12-droppable_3.ivf-640x480-0018.i420
+6ab0a82b5f0736d951b58f2245adb793  vp90-2-12-droppable_3.ivf-640x480-0019.i420
+1a9f6adde0d6ecd7bc83301ffeb15e51  vp90-2-12-droppable_3.ivf-640x480-0020.i420
+07552d44c99801657a3301d50c6d3897  vp90-2-12-droppable_3.ivf-640x480-0021.i420
+e9cdeec3accd4d19aa199a64e6cd163d  vp90-2-12-droppable_3.ivf-640x480-0022.i420
+5dedc5eeb214bc4356bfa53e1c00d723  vp90-2-12-droppable_3.ivf-640x480-0023.i420
+dfd4bf2f664b46c36de24edf799c5c2a  vp90-2-12-droppable_3.ivf-640x480-0024.i420
+deb33fefe4f20f09b6e84a037a7c2755  vp90-2-12-droppable_3.ivf-640x480-0025.i420
+e7425d6d380be060a89a2ca85660042f  vp90-2-12-droppable_3.ivf-640x480-0026.i420
+74e3b4f750566b09c2fd0baafa5d69d1  vp90-2-12-droppable_3.ivf-640x480-0027.i420
+dd9f990aa7d858290a970be4681b7a1f  vp90-2-12-droppable_3.ivf-640x480-0028.i420
+f7e8c6e20722b6a69e7f6766f41f2805  vp90-2-12-droppable_3.ivf-640x480-0029.i420
+835fca0a38539ef2632f85a051544326  vp90-2-12-droppable_3.ivf-640x480-0030.i420
+9c10a225363aa167ccef6e53b19ee64f  vp90-2-12-droppable_3.ivf-640x480-0031.i420
diff --git a/tests/tests/media/res/raw/vp90_2_15_segkey.vp9 b/tests/tests/media/res/raw/vp90_2_15_segkey.vp9
new file mode 100644
index 0000000..b67d891
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_15_segkey.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_15_segkey_adpq.vp9 b/tests/tests/media/res/raw/vp90_2_15_segkey_adpq.vp9
new file mode 100644
index 0000000..9e54de9
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_15_segkey_adpq.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_15_segkey_adpq_vp9_md5 b/tests/tests/media/res/raw/vp90_2_15_segkey_adpq_vp9_md5
new file mode 100644
index 0000000..e3ee4d7
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_15_segkey_adpq_vp9_md5
@@ -0,0 +1,150 @@
+d4f0e4b606ddb40b482aecb24cf3bc63  vp90-2-15-segkey_adpq.webm-1280x720-0001.i420
+692ec092bc5928fa6430d056e883759a  vp90-2-15-segkey_adpq.webm-1280x720-0002.i420
+dad790df33430899fed98886a24b37e5  vp90-2-15-segkey_adpq.webm-1280x720-0003.i420
+7e66e793ac9462a40dd5b963fb62e667  vp90-2-15-segkey_adpq.webm-1280x720-0004.i420
+0d795c6e20f42f09aca0ddb9dffaa6e8  vp90-2-15-segkey_adpq.webm-1280x720-0005.i420
+0ef3739c4ab2c51f0ab8e290eadad77e  vp90-2-15-segkey_adpq.webm-1280x720-0006.i420
+04a15f765960263c1b4a5a8822e17322  vp90-2-15-segkey_adpq.webm-1280x720-0007.i420
+116d518830c958bf46759fd79bc74198  vp90-2-15-segkey_adpq.webm-1280x720-0008.i420
+58ea67addab05825cc2e5f2ab99fca4b  vp90-2-15-segkey_adpq.webm-1280x720-0009.i420
+590f6e5deea6dde21dc1098fa2017c2f  vp90-2-15-segkey_adpq.webm-1280x720-0010.i420
+895479957b0882ccce4159782dee8deb  vp90-2-15-segkey_adpq.webm-1280x720-0011.i420
+cc8e05afdfb6f9c7042fd6f9e9d49140  vp90-2-15-segkey_adpq.webm-1280x720-0012.i420
+3e47c556a63af90f1ca4609f97f25d2c  vp90-2-15-segkey_adpq.webm-1280x720-0013.i420
+e5ca5dce8cbd39412db2fe219d6d2594  vp90-2-15-segkey_adpq.webm-1280x720-0014.i420
+c62b456e12230660d26eb7226f257d0c  vp90-2-15-segkey_adpq.webm-1280x720-0015.i420
+e184c961b373de465d3242f32f7cf3ed  vp90-2-15-segkey_adpq.webm-1280x720-0016.i420
+7466b91858f740fc28965a63effe05d6  vp90-2-15-segkey_adpq.webm-1280x720-0017.i420
+c8f06a3b1e471c4e7a9efd71a30dfe3b  vp90-2-15-segkey_adpq.webm-1280x720-0018.i420
+d4fb95148963b2eaff0211ddc5117c13  vp90-2-15-segkey_adpq.webm-1280x720-0019.i420
+c646526b40277289520d47ed8ca3b644  vp90-2-15-segkey_adpq.webm-1280x720-0020.i420
+e441ae686fa444e4e3584543611043ba  vp90-2-15-segkey_adpq.webm-1280x720-0021.i420
+68d707ef6909bfbc02dcbd9e392a04f6  vp90-2-15-segkey_adpq.webm-1280x720-0022.i420
+1ff285d17a26622b61bd2651754602b1  vp90-2-15-segkey_adpq.webm-1280x720-0023.i420
+c272192987e44e54e5335e6416bd15a5  vp90-2-15-segkey_adpq.webm-1280x720-0024.i420
+8f6f02572181eb4855dcd4c957e57d2e  vp90-2-15-segkey_adpq.webm-1280x720-0025.i420
+baf03eb567fd092eeb6f08ff5e098350  vp90-2-15-segkey_adpq.webm-1280x720-0026.i420
+479c78bd3da0892b8d4e32c99ec4739f  vp90-2-15-segkey_adpq.webm-1280x720-0027.i420
+d39a52f6e30ef10462bdef1006809e88  vp90-2-15-segkey_adpq.webm-1280x720-0028.i420
+d58395369806221efe9ba88513319d8a  vp90-2-15-segkey_adpq.webm-1280x720-0029.i420
+459e77e83c510ee1d79bf069752d44e5  vp90-2-15-segkey_adpq.webm-1280x720-0030.i420
+438027c8eacb9c795f8267a151ef5a4e  vp90-2-15-segkey_adpq.webm-1280x720-0031.i420
+ea6b73fb0d4b23ebbdaeb0267135d083  vp90-2-15-segkey_adpq.webm-1280x720-0032.i420
+48160c624d4d5050a4c8abcbe0edf4b2  vp90-2-15-segkey_adpq.webm-1280x720-0033.i420
+6fc6d5b4751cf137fc0204c0026f2503  vp90-2-15-segkey_adpq.webm-1280x720-0034.i420
+5ea20f6483fc5cde854313ed8288c7ca  vp90-2-15-segkey_adpq.webm-1280x720-0035.i420
+dafa41fa3468f684ca5538593cd1a0de  vp90-2-15-segkey_adpq.webm-1280x720-0036.i420
+b73d3336c83a27874e24b691c34c3421  vp90-2-15-segkey_adpq.webm-1280x720-0037.i420
+d0b0488a5871a49442746ac8ea1343bc  vp90-2-15-segkey_adpq.webm-1280x720-0038.i420
+df6fe9cb354624b69908730f24f51b88  vp90-2-15-segkey_adpq.webm-1280x720-0039.i420
+a388b159a024ace9437976206e62473c  vp90-2-15-segkey_adpq.webm-1280x720-0040.i420
+9007423410201a70b6997477ed9040f6  vp90-2-15-segkey_adpq.webm-1280x720-0041.i420
+7f7425cc018ad391e06b867f51d69513  vp90-2-15-segkey_adpq.webm-1280x720-0042.i420
+2ef51a3a15c627f803eee7f351cdfa4e  vp90-2-15-segkey_adpq.webm-1280x720-0043.i420
+260cded2461ab87181d650c58a8a0656  vp90-2-15-segkey_adpq.webm-1280x720-0044.i420
+fdd7a93b5f25ec2b74d93736fa7bb475  vp90-2-15-segkey_adpq.webm-1280x720-0045.i420
+810bb95ef0221b50ef12c7d0a4740fec  vp90-2-15-segkey_adpq.webm-1280x720-0046.i420
+f7eb4d63c16aebfeba4804c4e9c2c134  vp90-2-15-segkey_adpq.webm-1280x720-0047.i420
+a1ae94b85bced552e2c4f15ab5c5096d  vp90-2-15-segkey_adpq.webm-1280x720-0048.i420
+4b7b9e460b4a4ceab5deb5c6876cea05  vp90-2-15-segkey_adpq.webm-1280x720-0049.i420
+514472399dc39fcc4e833e166b81ea8e  vp90-2-15-segkey_adpq.webm-1280x720-0050.i420
+dca73ca76936d0a7eeb71c20955ea3a3  vp90-2-15-segkey_adpq.webm-1280x720-0051.i420
+927b185567b515a6bd102e1199ee1836  vp90-2-15-segkey_adpq.webm-1280x720-0052.i420
+63e1fffd59b77c53811d75a116fbac60  vp90-2-15-segkey_adpq.webm-1280x720-0053.i420
+5ca302497e81d564cfd455e2b606b262  vp90-2-15-segkey_adpq.webm-1280x720-0054.i420
+6e317d469ee664bc511a8286650f0b79  vp90-2-15-segkey_adpq.webm-1280x720-0055.i420
+d93e1909f3bdda983e0b3c73a8c51754  vp90-2-15-segkey_adpq.webm-1280x720-0056.i420
+836072cb1c4dc3dc32c935ba4ac3f716  vp90-2-15-segkey_adpq.webm-1280x720-0057.i420
+014e61666ba819260a25f09ae97768a8  vp90-2-15-segkey_adpq.webm-1280x720-0058.i420
+997fa6283e48ff017ce04041b9022fb9  vp90-2-15-segkey_adpq.webm-1280x720-0059.i420
+b2c35749c6b848601193c2eff7f0bdf1  vp90-2-15-segkey_adpq.webm-1280x720-0060.i420
+813e9f562ef53589afbfe7d73002c136  vp90-2-15-segkey_adpq.webm-1280x720-0061.i420
+be876a05cfc72fe6138e1c24b6e94c3f  vp90-2-15-segkey_adpq.webm-1280x720-0062.i420
+2a33b99f67fe5579ddbd62bac085ae8a  vp90-2-15-segkey_adpq.webm-1280x720-0063.i420
+8d374a1886861cfd9ca6f16a0aff1b6c  vp90-2-15-segkey_adpq.webm-1280x720-0064.i420
+eff4e17b08c67a1663c8f1cc614bd94a  vp90-2-15-segkey_adpq.webm-1280x720-0065.i420
+39e4d97460cf02ecfbc666e0413d7db1  vp90-2-15-segkey_adpq.webm-1280x720-0066.i420
+732f41606146dfb0c6a8cf130df969a8  vp90-2-15-segkey_adpq.webm-1280x720-0067.i420
+9b724b808bc26f21aaa32653185b2cf3  vp90-2-15-segkey_adpq.webm-1280x720-0068.i420
+e18598cb7ac70cdb5dea29b35ae5accb  vp90-2-15-segkey_adpq.webm-1280x720-0069.i420
+afbcad9f7bad0b58a5bccdb8977a60fb  vp90-2-15-segkey_adpq.webm-1280x720-0070.i420
+6ec24c40cd8a0cf2e15339ce4f60c232  vp90-2-15-segkey_adpq.webm-1280x720-0071.i420
+76616dbe8207235f6890360566f9e8df  vp90-2-15-segkey_adpq.webm-1280x720-0072.i420
+49a5c751ed430e9bc41c3a3334295025  vp90-2-15-segkey_adpq.webm-1280x720-0073.i420
+f657e47dbbcc2a04e9e7b71ecd8451ff  vp90-2-15-segkey_adpq.webm-1280x720-0074.i420
+8e85f3d26b26f26ccd804061d2f37bbb  vp90-2-15-segkey_adpq.webm-1280x720-0075.i420
+5a9dd5c0390491cd21163da01dc21f4d  vp90-2-15-segkey_adpq.webm-1280x720-0076.i420
+3cf88ad2d2d7ecf1223afa5d1b849317  vp90-2-15-segkey_adpq.webm-1280x720-0077.i420
+27385b23461b5f1c137c2f29354595ed  vp90-2-15-segkey_adpq.webm-1280x720-0078.i420
+e6eacbe2890389c586f2936a75ab3509  vp90-2-15-segkey_adpq.webm-1280x720-0079.i420
+19a48ffafdcdb6fb1d6b9808daed2f86  vp90-2-15-segkey_adpq.webm-1280x720-0080.i420
+f8c9419d4944fb214e06a2c30a560d93  vp90-2-15-segkey_adpq.webm-1280x720-0081.i420
+3f3d3dd54e5aa6bd59af1be86ec9be3d  vp90-2-15-segkey_adpq.webm-1280x720-0082.i420
+28be5316ed79dc47b6a142cef0c16ab7  vp90-2-15-segkey_adpq.webm-1280x720-0083.i420
+6fbed684bfe8dfd354210293d7eb4d0b  vp90-2-15-segkey_adpq.webm-1280x720-0084.i420
+e60cd76f68c95f8b484d0b6424eea4cc  vp90-2-15-segkey_adpq.webm-1280x720-0085.i420
+e05a0cf382f49039faddaffeff2cec16  vp90-2-15-segkey_adpq.webm-1280x720-0086.i420
+42ea736ebbfe50f1ebd460d71781e5d6  vp90-2-15-segkey_adpq.webm-1280x720-0087.i420
+80f78066700b6752bbc1a41390ddb482  vp90-2-15-segkey_adpq.webm-1280x720-0088.i420
+14671354929fcf10677b2ed2db3c8cb4  vp90-2-15-segkey_adpq.webm-1280x720-0089.i420
+96a7d68407f1a2c96bd3cafe0c696bf5  vp90-2-15-segkey_adpq.webm-1280x720-0090.i420
+2f2adb990cfa42229db987a668b19d38  vp90-2-15-segkey_adpq.webm-1280x720-0091.i420
+a8233951004e1bb0d0937435a517fad2  vp90-2-15-segkey_adpq.webm-1280x720-0092.i420
+6163e872c38adfde7b0c8891cbb2c969  vp90-2-15-segkey_adpq.webm-1280x720-0093.i420
+990165e0905fb80ccc29d2de062d4f9b  vp90-2-15-segkey_adpq.webm-1280x720-0094.i420
+e6f3224c4c60098ee93fca870f8636b2  vp90-2-15-segkey_adpq.webm-1280x720-0095.i420
+8c561667345f932618f8b3aaa43ffde0  vp90-2-15-segkey_adpq.webm-1280x720-0096.i420
+1acb3999bacd483d1153beb43ee09772  vp90-2-15-segkey_adpq.webm-1280x720-0097.i420
+2a075c7bc49190df83b8285ee6e124d3  vp90-2-15-segkey_adpq.webm-1280x720-0098.i420
+890a134a3c77d9b64d83fe6d2def02de  vp90-2-15-segkey_adpq.webm-1280x720-0099.i420
+d0b41422b89f03ffcbde7c85889ad2c2  vp90-2-15-segkey_adpq.webm-1280x720-0100.i420
+fdc4f855d70ef16ec9baeb05c3a73f44  vp90-2-15-segkey_adpq.webm-1280x720-0101.i420
+ed9f847a3b4280cfe306018825c76508  vp90-2-15-segkey_adpq.webm-1280x720-0102.i420
+5deb2536bba158c722bc0d909f45e611  vp90-2-15-segkey_adpq.webm-1280x720-0103.i420
+fc7880ca8680e03fb1978adce8066027  vp90-2-15-segkey_adpq.webm-1280x720-0104.i420
+6e1c351c6b102e9185f688a02190b87f  vp90-2-15-segkey_adpq.webm-1280x720-0105.i420
+1f6169bf490ed1b4c391383f770fec02  vp90-2-15-segkey_adpq.webm-1280x720-0106.i420
+80ac3b673b1504fb1e88d883a91a539c  vp90-2-15-segkey_adpq.webm-1280x720-0107.i420
+d2e7654f961ff3767c1e9e8558c2f20d  vp90-2-15-segkey_adpq.webm-1280x720-0108.i420
+365368d813eb10c5adc53e47afeb414d  vp90-2-15-segkey_adpq.webm-1280x720-0109.i420
+5f74f55478377dd31da91cf195332480  vp90-2-15-segkey_adpq.webm-1280x720-0110.i420
+827b7b3853ea3b1855583b59ed7b09c2  vp90-2-15-segkey_adpq.webm-1280x720-0111.i420
+2017c1a57a271308172bd84d3887d063  vp90-2-15-segkey_adpq.webm-1280x720-0112.i420
+d65b95c71db9972dc051bec7df19f85f  vp90-2-15-segkey_adpq.webm-1280x720-0113.i420
+7243da9072729ffa75209a6699e77ac3  vp90-2-15-segkey_adpq.webm-1280x720-0114.i420
+112da8d27907ab6a66b030e9c8864e46  vp90-2-15-segkey_adpq.webm-1280x720-0115.i420
+e2837b6409de4bc6e71ff9eca8eab391  vp90-2-15-segkey_adpq.webm-1280x720-0116.i420
+567eba2ddb91a02665ac96fa10703f00  vp90-2-15-segkey_adpq.webm-1280x720-0117.i420
+474a99d56fce0e7e96ac3585b905956f  vp90-2-15-segkey_adpq.webm-1280x720-0118.i420
+3087edb09f1ef2e63130b7c03e696028  vp90-2-15-segkey_adpq.webm-1280x720-0119.i420
+574f7328da31760ecf237617aebd7784  vp90-2-15-segkey_adpq.webm-1280x720-0120.i420
+c3a7669bb496bec766a74a800275ff6c  vp90-2-15-segkey_adpq.webm-1280x720-0121.i420
+c0d87245a92e7140e6b729c26fe97a95  vp90-2-15-segkey_adpq.webm-1280x720-0122.i420
+467e33e84435fe64cb14653600ec5163  vp90-2-15-segkey_adpq.webm-1280x720-0123.i420
+1c7a5b2472c00e9dc63f679b51ead6a9  vp90-2-15-segkey_adpq.webm-1280x720-0124.i420
+8fb7197463cdae6c45437a73dcb4a3d8  vp90-2-15-segkey_adpq.webm-1280x720-0125.i420
+f352fee36f51536175b05b5ff5a3187a  vp90-2-15-segkey_adpq.webm-1280x720-0126.i420
+ac1ed4392a38268a2495508245032d74  vp90-2-15-segkey_adpq.webm-1280x720-0127.i420
+b8179a306c4fbc6f207d15acaae92dfb  vp90-2-15-segkey_adpq.webm-1280x720-0128.i420
+7f263b0fd68652d83b75d24cc11c89e8  vp90-2-15-segkey_adpq.webm-1280x720-0129.i420
+39e33d02a01247cefe19d8bf9fbdecae  vp90-2-15-segkey_adpq.webm-1280x720-0130.i420
+49a4e89c9fcc66f7e6e679aee4af0852  vp90-2-15-segkey_adpq.webm-1280x720-0131.i420
+0af52a32e6d74694a0a1f12aa78293fe  vp90-2-15-segkey_adpq.webm-1280x720-0132.i420
+fedde75a5c093ea12f0ed328da7350c9  vp90-2-15-segkey_adpq.webm-1280x720-0133.i420
+2ab788cf689fdbe8fbc74dde165605ad  vp90-2-15-segkey_adpq.webm-1280x720-0134.i420
+682c2316cbd2e8a5e54edd1e9309a6c7  vp90-2-15-segkey_adpq.webm-1280x720-0135.i420
+f155e8fa47625f18dffea813a7070c71  vp90-2-15-segkey_adpq.webm-1280x720-0136.i420
+2611eb2b2da8f6995ac2159012ec540a  vp90-2-15-segkey_adpq.webm-1280x720-0137.i420
+a1130a4ddf7dbd592e23001c4b98b3fc  vp90-2-15-segkey_adpq.webm-1280x720-0138.i420
+84eef6f47bff223c6a0916c0688d2f7c  vp90-2-15-segkey_adpq.webm-1280x720-0139.i420
+ccfab0b84c7fc59d850ac5cb8d36da41  vp90-2-15-segkey_adpq.webm-1280x720-0140.i420
+6866845dfb320ecd9c22444ca7e52c8b  vp90-2-15-segkey_adpq.webm-1280x720-0141.i420
+3068ceb83ee4d047df3880c64754efd7  vp90-2-15-segkey_adpq.webm-1280x720-0142.i420
+7f9a74e20cfe10972961e7f21529f7f4  vp90-2-15-segkey_adpq.webm-1280x720-0143.i420
+29156833963ec7f218d38fca7df132bf  vp90-2-15-segkey_adpq.webm-1280x720-0144.i420
+f8feb4c2ae1ce371fc8b4a83d7dc34e0  vp90-2-15-segkey_adpq.webm-1280x720-0145.i420
+0e5fe8965da239c17b02f0c902feeaec  vp90-2-15-segkey_adpq.webm-1280x720-0146.i420
+e8d37eb1b8c2576658ebc58a7cc6c0d4  vp90-2-15-segkey_adpq.webm-1280x720-0147.i420
+0a89fd2784112bbd54eb559a8272ab1e  vp90-2-15-segkey_adpq.webm-1280x720-0148.i420
+342bc99cdd618272d12d045698b9cb20  vp90-2-15-segkey_adpq.webm-1280x720-0149.i420
+a489a32bb43559b8a1989b13660e3cf6  vp90-2-15-segkey_adpq.webm-1280x720-0150.i420
diff --git a/tests/tests/media/res/raw/vp90_2_15_segkey_vp9_md5 b/tests/tests/media/res/raw/vp90_2_15_segkey_vp9_md5
new file mode 100644
index 0000000..809e25e
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_15_segkey_vp9_md5
@@ -0,0 +1 @@
+d3805a0d832b9bdd69ad99d68490be7b  vp90-2-15-segkey.webm-1280x720-0001.i420
diff --git a/tests/tests/media/res/raw/vp90_2_16_intra_only.vp9 b/tests/tests/media/res/raw/vp90_2_16_intra_only.vp9
new file mode 100644
index 0000000..a88750f
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_16_intra_only.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_16_intra_only_vp9_md5 b/tests/tests/media/res/raw/vp90_2_16_intra_only_vp9_md5
new file mode 100644
index 0000000..112a52a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_16_intra_only_vp9_md5
@@ -0,0 +1,7 @@
+d57529601178948afa4818c3c8938884  vp90-2-16-intra-only-352x288-0001.i420
+d47e00250c45733d64af067a417bcd06  vp90-2-16-intra-only-352x288-0002.i420
+984e41cd8350808ac6129746b2377818  vp90-2-16-intra-only-352x288-0003.i420
+a5fa62996b4bb52e72e335722cf55bef  vp90-2-16-intra-only-352x288-0004.i420
+b71ca5ad650170ac921a71a6440fb508  vp90-2-16-intra-only-352x288-0005.i420
+76ba63001170b8992fc72be5c4ace731  vp90-2-16-intra-only-352x288-0006.i420
+c4e7f96a8fd58d901b1d881926ddae09  vp90-2-16-intra-only-352x288-0007.i420
diff --git a/tests/tests/media/res/raw/vp90_2_17_show_existing_frame.vp9 b/tests/tests/media/res/raw/vp90_2_17_show_existing_frame.vp9
new file mode 100644
index 0000000..4748eeb
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_17_show_existing_frame.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_17_show_existing_frame_vp9_md5 b/tests/tests/media/res/raw/vp90_2_17_show_existing_frame_vp9_md5
new file mode 100644
index 0000000..50394da
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_17_show_existing_frame_vp9_md5
@@ -0,0 +1,30 @@
+b71ca5ad650170ac921a71a6440fb508  vp90-2-17-show-existing-frame.webm-352x288-0001.i420
+edc30ba14b73198ca827c1b216957dec  vp90-2-17-show-existing-frame.webm-352x288-0002.i420
+1902c5b3a82f6bdeb80a5b053909df04  vp90-2-17-show-existing-frame.webm-352x288-0003.i420
+9a96e33ed546d7961c6e5bc48244a5c7  vp90-2-17-show-existing-frame.webm-352x288-0004.i420
+b02a48630b0f3c08c61dd2518b55ea39  vp90-2-17-show-existing-frame.webm-352x288-0005.i420
+8ac9cec1101a46bf4ba20191b7ba3f07  vp90-2-17-show-existing-frame.webm-352x288-0006.i420
+88ea8c3cb9eca47152b5d22435a06675  vp90-2-17-show-existing-frame.webm-352x288-0007.i420
+bff3406209ec0d592a891dff2b58d6cd  vp90-2-17-show-existing-frame.webm-352x288-0008.i420
+b71ca5ad650170ac921a71a6440fb508  vp90-2-17-show-existing-frame.webm-352x288-0009.i420
+edc30ba14b73198ca827c1b216957dec  vp90-2-17-show-existing-frame.webm-352x288-0010.i420
+1902c5b3a82f6bdeb80a5b053909df04  vp90-2-17-show-existing-frame.webm-352x288-0011.i420
+9a96e33ed546d7961c6e5bc48244a5c7  vp90-2-17-show-existing-frame.webm-352x288-0012.i420
+b02a48630b0f3c08c61dd2518b55ea39  vp90-2-17-show-existing-frame.webm-352x288-0013.i420
+8ac9cec1101a46bf4ba20191b7ba3f07  vp90-2-17-show-existing-frame.webm-352x288-0014.i420
+88ea8c3cb9eca47152b5d22435a06675  vp90-2-17-show-existing-frame.webm-352x288-0015.i420
+bff3406209ec0d592a891dff2b58d6cd  vp90-2-17-show-existing-frame.webm-352x288-0016.i420
+b71ca5ad650170ac921a71a6440fb508  vp90-2-17-show-existing-frame.webm-352x288-0017.i420
+edc30ba14b73198ca827c1b216957dec  vp90-2-17-show-existing-frame.webm-352x288-0018.i420
+1902c5b3a82f6bdeb80a5b053909df04  vp90-2-17-show-existing-frame.webm-352x288-0019.i420
+9a96e33ed546d7961c6e5bc48244a5c7  vp90-2-17-show-existing-frame.webm-352x288-0020.i420
+b02a48630b0f3c08c61dd2518b55ea39  vp90-2-17-show-existing-frame.webm-352x288-0021.i420
+8ac9cec1101a46bf4ba20191b7ba3f07  vp90-2-17-show-existing-frame.webm-352x288-0022.i420
+88ea8c3cb9eca47152b5d22435a06675  vp90-2-17-show-existing-frame.webm-352x288-0023.i420
+bff3406209ec0d592a891dff2b58d6cd  vp90-2-17-show-existing-frame.webm-352x288-0024.i420
+a36428fd889ddf9983638c581c1d9146  vp90-2-17-show-existing-frame.webm-352x288-0025.i420
+689bd5fba1b7dff9abb1332e56f224fa  vp90-2-17-show-existing-frame.webm-352x288-0026.i420
+e883aa425fa13c6d4eda2707d114d61d  vp90-2-17-show-existing-frame.webm-352x288-0027.i420
+94d0bce08beb8a19c4ae12194a646935  vp90-2-17-show-existing-frame.webm-352x288-0028.i420
+cd317e97f5fd4be166308911c874f4e1  vp90-2-17-show-existing-frame.webm-352x288-0029.i420
+2fa245acd72d377cbb79c08faa02b330  vp90-2-17-show-existing-frame.webm-352x288-0030.i420
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip.vp9 b/tests/tests/media/res/raw/vp90_2_19_skip.vp9
new file mode 100644
index 0000000..51c1173
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip_01.vp9 b/tests/tests/media/res/raw/vp90_2_19_skip_01.vp9
new file mode 100644
index 0000000..b108df8
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip_01.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip_01_vp9_md5 b/tests/tests/media/res/raw/vp90_2_19_skip_01_vp9_md5
new file mode 100644
index 0000000..98fdce2
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip_01_vp9_md5
@@ -0,0 +1,60 @@
+6e350ec33af4ce08c18e884d7fd795aa  01.yuv
+abfb6e52a5a9d896b65e2c54e1f35f20  02.yuv
+e40e57536810c196f277f2d86fd7ef4d  03.yuv
+0b25dbe7b8218fcc67e700d332ef7ad7  04.yuv
+20f7737828b9a686a02a1b01cebb637f  05.yuv
+06d41fe61fbd8d96750882baac56954f  06.yuv
+9e6661eb3424978e105dfa393407c293  07.yuv
+2d9dd8d9625dc67cb342b9db51a9bf85  08.yuv
+d8d8671e8e921484acd0fd67c7046382  09.yuv
+f6513fee6d2de65d51239a689f45f1d6  10.yuv
+5a8c26cbe9cefc79481a1e24c36d1b07  11.yuv
+918c1080ca4f2d61049caaa963d58069  12.yuv
+9d028868e407a2a596ede1c7ec71997c  13.yuv
+0bf06f2b16acc2c9691953d0ba134e7b  14.yuv
+f340480004fd45b579bfa04487c94136  15.yuv
+a6ab04e5c72ab3612842e891644ef2f2  16.yuv
+cf5da560e869a73ac6dc37ff1812b14e  17.yuv
+4b9e24121a05b7f95e4c2ed5dc25aac9  18.yuv
+5e7c43edbf51d19cae31e348920e5848  19.yuv
+96e421b17ce7fea2428ea1fe8f7b500a  20.yuv
+0e2b1ef0e3d1cf4a2af7dd7cbb160f04  21.yuv
+bdcc399223320df2fab20bf365e4f3df  22.yuv
+26cf7f3d9c3e36c6d2f8af6e1c9f9b15  23.yuv
+d2ef6d0dfd7eca3d77b60f9c82191bf3  24.yuv
+76c07306ce9a627f37a6a5c8d66820a2  25.yuv
+7ee2428a7fbc3c88418167a8e52d438d  26.yuv
+68b267345e01d2fc72576f984f757a3c  27.yuv
+541bfb03ae1db20d693a0a92550e8df6  28.yuv
+e87cf619aefdb81e26a8ec70d6a12c2c  29.yuv
+621f1ed3976088b247d79504bdf03ca3  30.yuv
+2c6023819babc72f8ad936ec0f0ca85e  31.yuv
+9f5eae1311cfdd2c02ee63a978b8d6d2  32.yuv
+902112ada88fbd3fe006b713cf08f5aa  33.yuv
+ab5b451f7174520c57b096268272759c  34.yuv
+b686cba2b4c454de4e8e16f088db8354  35.yuv
+a68e934aa397819bb80bf4bd29134103  36.yuv
+6982347a3aa730c2f8a15c94bfb42b3d  37.yuv
+57c3f83402184dd80beb9f78f0c5cfc8  38.yuv
+adf66470bfdb88a860a17b74d0f5e99b  39.yuv
+e98d09d8d34d3c8d1cb6619794b1ed5b  40.yuv
+f839dce9aabf7db8b007d83766e05fa7  41.yuv
+3bad23fa7f6052582e319b9774e26030  42.yuv
+4220ba420816a3bc7030e1582942e74d  43.yuv
+f404671eaf5310565d0831684ff0f3ba  44.yuv
+8ba48a53a0178bcd596b880c8a96a61f  45.yuv
+7a8fbb7356e494a6cefe52c2b07e6dce  46.yuv
+fb7974be2a11fcfc71cc450727bf71ad  47.yuv
+5c9be4d4acac0b375be851cd3774a918  48.yuv
+83c84c97c9c5efd6dd56668cdbf18428  49.yuv
+626c9ab1e52f7d9c711e142b46e82a42  50.yuv
+8012dbe193dfa5d787445eaeecd9091b  51.yuv
+bc36350c60b92f77473158a9249d5383  52.yuv
+4e81e00620020b4c55f273796f023145  53.yuv
+f6161f425f0476821f8caa46360d87af  54.yuv
+509f724002e54baac7dd37b514c345da  55.yuv
+4ab2368ffa3854f433fd568883db0e55  56.yuv
+9934a8d1ae0bdd65aab070efa91ac778  57.yuv
+2f2c1b110107c1141053513f2596a599  58.yuv
+9da6ca6ef375a095f0c86cb8cb41db74  59.yuv
+125c735dc1fb523c8088e0815cd4cde1  60.yuv
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip_02.vp9 b/tests/tests/media/res/raw/vp90_2_19_skip_02.vp9
new file mode 100644
index 0000000..770e311
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip_02.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip_02_vp9_md5 b/tests/tests/media/res/raw/vp90_2_19_skip_02_vp9_md5
new file mode 100644
index 0000000..80b3d65
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip_02_vp9_md5
@@ -0,0 +1,12 @@
+1ee94a4b059cd7380dabf71553aedf32  vp90-2-19-skip-02.webm-208x144-0001.i420
+d86167bfd6bca76c476c79361894a3f0  vp90-2-19-skip-02.webm-208x144-0002.i420
+421c9cd3b3474af8893fa44832b6fca7  vp90-2-19-skip-02.webm-208x144-0003.i420
+db0585dc48220105b8a3326222a66292  vp90-2-19-skip-02.webm-208x144-0004.i420
+15e5a53f39d7e350d356b0c4b2be4c82  vp90-2-19-skip-02.webm-208x144-0005.i420
+4d35f23245c90b5c0f013b4b2a085b2a  vp90-2-19-skip-02.webm-208x144-0006.i420
+1e46a9945accfec93e345f50ebb520a0  vp90-2-19-skip-02.webm-208x144-0007.i420
+ea53419be2de85e9505aaed3a03a10e0  vp90-2-19-skip-02.webm-208x144-0008.i420
+14c17560d0690e929a40b6f2e46a458a  vp90-2-19-skip-02.webm-208x144-0009.i420
+7c5eb58b81b57530391717a076114728  vp90-2-19-skip-02.webm-208x144-0010.i420
+57d4952e50ba519388ce7efca7ee505b  vp90-2-19-skip-02.webm-208x144-0011.i420
+7bb3d99c86e135354ad437e5d80bf089  vp90-2-19-skip-02.webm-208x144-0012.i420
diff --git a/tests/tests/media/res/raw/vp90_2_19_skip_vp9_md5 b/tests/tests/media/res/raw/vp90_2_19_skip_vp9_md5
new file mode 100644
index 0000000..472b59a
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_19_skip_vp9_md5
@@ -0,0 +1,60 @@
+6e350ec33af4ce08c18e884d7fd795aa  01.yuv
+3f77603d7a5727db4017202310da1724  02.yuv
+983aae5424ab39af07adcf78d43a23ba  03.yuv
+a0cdeaa0eb6eda3750d268434391a7ab  04.yuv
+64325c99444e566989c6eeaa8ffeee32  05.yuv
+8320f52b7fcd0565465941c50a01b801  06.yuv
+d6bb76bf65b70b86bda891fe807fcd26  07.yuv
+c44b46422d2be0b831d27fab61a0d374  08.yuv
+414ce4220e0aef53cb5966990ae00bb6  09.yuv
+2bf82867941dc68b0d60cede97f2d4d7  10.yuv
+593c676743ffaf1a5be85d74529dbb3f  11.yuv
+ccac5f0992545c35d227a021cb91b6f6  12.yuv
+bbb637aaed37f7cc6068802531152b77  13.yuv
+41e2d71a3ff3ed9d225348eb6be72853  14.yuv
+7ed3f76508059c281f75e2043d7d6677  15.yuv
+ed330eefed85685bed2bc1c5dc409d24  16.yuv
+61c4c435237e06623b6994f43b469833  17.yuv
+1e27f96fe683a654b228360f7a1beee1  18.yuv
+090e025ec148ec53f802cdb8ed0bfd77  19.yuv
+20d0caa6d4ab9db05869fd0532a2265f  20.yuv
+e11d108db8822b07a6fe8216b34fa259  21.yuv
+bdb3421bffee6eeafa00255ffcdcf1fe  22.yuv
+cb090c2f2d28679d1e2eb2c04150d751  23.yuv
+7f8eec67552bbac654f9a374d7a985ca  24.yuv
+5c039c621c9c20947f75b98b7e579ce8  25.yuv
+464be7de183b98138d8e9fb61ef613ec  26.yuv
+b887a102c6399d33307ac434d0ab3fd4  27.yuv
+e8fa163067c77e27b9089b4a48b444c0  28.yuv
+d92e13465475df261f9469171ac962cc  29.yuv
+8e6a8ba99387bc4cf7aee0aab6d132f4  30.yuv
+4625d7b6b23ddc840941a4f4d7739daa  31.yuv
+3b8533887142da49fdb24569dd34c2ac  32.yuv
+9ff94cefac26936cbf284e7482b2433d  33.yuv
+68b2fec46494c24501e48927fe9636e5  34.yuv
+7d76bfa0ebb09f27482288a0d61cd0e8  35.yuv
+27b630a10fc1790884e16bbb0fef37ee  36.yuv
+322de7f87166725fdd48373b28156593  37.yuv
+d73c7bd37eccd47df4a5b27cecbb8cea  38.yuv
+c3679a0317d1efc2b76e3dd97baa4070  39.yuv
+e3f9523bd41a280b922cdcf188911de2  40.yuv
+b57f28d944f4f39ab9c97a5ae8e3beda  41.yuv
+520a2b794f4384cf4c38f8d4c5b9c7bb  42.yuv
+bc215f65a73183da31b4bd896db178b4  43.yuv
+ab3c86d15728db474a45c544c2103745  44.yuv
+1287678d28e400a47a4f21b8854339d7  45.yuv
+be3f1eb3f48706e4e37aff83f0434fab  46.yuv
+dbc71f50dd620e058da88c414041ca57  47.yuv
+3d68bf9ae1e6065bf70eee87fbb9a2ce  48.yuv
+c901fac66677a4be1b624d6995af1ea3  49.yuv
+0756c5dd31c691df91a535910d8756e0  50.yuv
+b9c30e56f000a71148ababdf7c7bbae3  51.yuv
+2dc2917b1c0e498dd8e83abcdc48e3ca  52.yuv
+057ce1fe6eb8800ec8ec47720e70ed74  53.yuv
+1c25a6c9e182fa7fbef473ad9be476ea  54.yuv
+3ae770d42403b5069d0fa97e11cec3b0  55.yuv
+e5c19d46df1c711a650229867073246c  56.yuv
+cfc5f6cbb0a319d8bfb3feffddbb8f48  57.yuv
+86e42a5e03bc537505589f7fa39bff2b  58.yuv
+cdf32bda09d594763068d6fa0ff67b98  59.yuv
+0d6be7f95a7e3941950f14e20be11020  60.yuv
diff --git a/tests/tests/media/res/raw/vp90_2_20_big_superframe_01.vp9 b/tests/tests/media/res/raw/vp90_2_20_big_superframe_01.vp9
new file mode 100644
index 0000000..6a45085
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_20_big_superframe_01.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_20_big_superframe_01_vp9_md5 b/tests/tests/media/res/raw/vp90_2_20_big_superframe_01_vp9_md5
new file mode 100644
index 0000000..4fe4dcc
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_20_big_superframe_01_vp9_md5
@@ -0,0 +1,13 @@
+b5d461894f957709576d15f6dce3d69e  vp90-2-20-big_superframe-01.webm-352x288-0001.i420
+b14448e30621b5d2d0a18c2e12ef0d95  vp90-2-20-big_superframe-01.webm-352x288-0002.i420
+4584cf6ffe6ca91fa3926cb88b6dab2d  vp90-2-20-big_superframe-01.webm-352x288-0003.i420
+ff83dd3c0dfdd8740523f560a9d7abfe  vp90-2-20-big_superframe-01.webm-352x288-0004.i420
+a2a1dc9b91b0e4fd6ecc8fa53a156ed9  vp90-2-20-big_superframe-01.webm-352x288-0005.i420
+13f953ae1cfa25c5996d77fc88070452  vp90-2-20-big_superframe-01.webm-352x288-0006.i420
+81dd4bdf32f7998fdc221a4612e022ce  vp90-2-20-big_superframe-01.webm-352x288-0007.i420
+518bbee70ad6488ea3d69e0e34a133a4  vp90-2-20-big_superframe-01.webm-352x288-0008.i420
+acae8f0ab72c6daa3a280fa41fbbb22e  vp90-2-20-big_superframe-01.webm-352x288-0009.i420
+fbfb93207c09242ee49637e740f3f870  vp90-2-20-big_superframe-01.webm-352x288-0010.i420
+20b072932f592e67d92cb67b224620b1  vp90-2-20-big_superframe-01.webm-352x288-0011.i420
+ddab6752606406c5b25d4e3b3208e381  vp90-2-20-big_superframe-01.webm-352x288-0012.i420
+6525d6826964e8b54fa982a300088ce3  vp90-2-20-big_superframe-01.webm-352x288-0013.i420
diff --git a/tests/tests/media/res/raw/vp90_2_20_big_superframe_02.vp9 b/tests/tests/media/res/raw/vp90_2_20_big_superframe_02.vp9
new file mode 100644
index 0000000..73137af
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_20_big_superframe_02.vp9
Binary files differ
diff --git a/tests/tests/media/res/raw/vp90_2_20_big_superframe_02_vp9_md5 b/tests/tests/media/res/raw/vp90_2_20_big_superframe_02_vp9_md5
new file mode 100644
index 0000000..8ca8576
--- /dev/null
+++ b/tests/tests/media/res/raw/vp90_2_20_big_superframe_02_vp9_md5
@@ -0,0 +1,18 @@
+b5d461894f957709576d15f6dce3d69e  vp90-2-20-big_superframe-02.webm-352x288-0001.i420
+54e45dfe575d9843c198270f62154c09  vp90-2-20-big_superframe-02.webm-352x288-0002.i420
+87749847c291a46c0ae0ca5d5002cb5f  vp90-2-20-big_superframe-02.webm-352x288-0003.i420
+04d7f341b081b35fd14ddfd777607fb1  vp90-2-20-big_superframe-02.webm-352x288-0004.i420
+81c73e1129b94936d53d33f8c66588e9  vp90-2-20-big_superframe-02.webm-352x288-0005.i420
+678b99102426df6a69184acc142c0c6a  vp90-2-20-big_superframe-02.webm-352x288-0006.i420
+a91f8d509a3e853e71b78b7ebe162428  vp90-2-20-big_superframe-02.webm-352x288-0007.i420
+9981ac3b4b78627c4474222823a9b288  vp90-2-20-big_superframe-02.webm-352x288-0008.i420
+400adf7ab42c47954db9086b5fcb2ef8  vp90-2-20-big_superframe-02.webm-352x288-0009.i420
+fc917ebef7115a04f0bf4e06e1e1a2a9  vp90-2-20-big_superframe-02.webm-352x288-0010.i420
+72271e7946c9dd99a947df787caaadfe  vp90-2-20-big_superframe-02.webm-352x288-0011.i420
+acb81daaaa35d651a87a9f8e87f813b3  vp90-2-20-big_superframe-02.webm-352x288-0012.i420
+e6ffc22ab1a918e3f1af384f0dd22ff9  vp90-2-20-big_superframe-02.webm-352x288-0013.i420
+3ecbc78c737312948d8c172d1c2d2383  vp90-2-20-big_superframe-02.webm-352x288-0014.i420
+320edb7fddfe8c98e616702d11f8f456  vp90-2-20-big_superframe-02.webm-352x288-0015.i420
+cf8363cebf34bdefd2c8e2178de5ef23  vp90-2-20-big_superframe-02.webm-352x288-0016.i420
+d15c8f1bc21ad09ad881a59b5f2b8167  vp90-2-20-big_superframe-02.webm-352x288-0017.i420
+c5c9f8b1826fac50655ed1454ae78279  vp90-2-20-big_superframe-02.webm-352x288-0018.i420
diff --git a/tests/tests/media/res/raw/vp9_test_vectors b/tests/tests/media/res/raw/vp9_test_vectors
new file mode 100644
index 0000000..a9dc4f3
--- /dev/null
+++ b/tests/tests/media/res/raw/vp9_test_vectors
@@ -0,0 +1,235 @@
+vp90_2_00_quantizer_00
+vp90_2_00_quantizer_01
+vp90_2_00_quantizer_02
+vp90_2_00_quantizer_03
+vp90_2_00_quantizer_04
+vp90_2_00_quantizer_05
+vp90_2_00_quantizer_06
+vp90_2_00_quantizer_07
+vp90_2_00_quantizer_08
+vp90_2_00_quantizer_09
+vp90_2_00_quantizer_10
+vp90_2_00_quantizer_11
+vp90_2_00_quantizer_12
+vp90_2_00_quantizer_13
+vp90_2_00_quantizer_14
+vp90_2_00_quantizer_15
+vp90_2_00_quantizer_16
+vp90_2_00_quantizer_17
+vp90_2_00_quantizer_18
+vp90_2_00_quantizer_19
+vp90_2_00_quantizer_20
+vp90_2_00_quantizer_21
+vp90_2_00_quantizer_22
+vp90_2_00_quantizer_23
+vp90_2_00_quantizer_24
+vp90_2_00_quantizer_25
+vp90_2_00_quantizer_26
+vp90_2_00_quantizer_27
+vp90_2_00_quantizer_28
+vp90_2_00_quantizer_29
+vp90_2_00_quantizer_30
+vp90_2_00_quantizer_31
+vp90_2_00_quantizer_32
+vp90_2_00_quantizer_33
+vp90_2_00_quantizer_34
+vp90_2_00_quantizer_35
+vp90_2_00_quantizer_36
+vp90_2_00_quantizer_37
+vp90_2_00_quantizer_38
+vp90_2_00_quantizer_39
+vp90_2_00_quantizer_40
+vp90_2_00_quantizer_41
+vp90_2_00_quantizer_42
+vp90_2_00_quantizer_43
+vp90_2_00_quantizer_44
+vp90_2_00_quantizer_45
+vp90_2_00_quantizer_46
+vp90_2_00_quantizer_47
+vp90_2_00_quantizer_48
+vp90_2_00_quantizer_49
+vp90_2_00_quantizer_50
+vp90_2_00_quantizer_51
+vp90_2_00_quantizer_52
+vp90_2_00_quantizer_53
+vp90_2_00_quantizer_54
+vp90_2_00_quantizer_55
+vp90_2_00_quantizer_56
+vp90_2_00_quantizer_57
+vp90_2_00_quantizer_58
+vp90_2_00_quantizer_59
+vp90_2_00_quantizer_60
+vp90_2_00_quantizer_61
+vp90_2_00_quantizer_62
+vp90_2_00_quantizer_63
+vp90_2_01_sharpness_1
+vp90_2_01_sharpness_2
+vp90_2_01_sharpness_3
+vp90_2_01_sharpness_4
+vp90_2_01_sharpness_5
+vp90_2_01_sharpness_6
+vp90_2_01_sharpness_7
+vp90_2_02_size_08x08
+vp90_2_02_size_08x10
+vp90_2_02_size_08x16
+vp90_2_02_size_08x18
+vp90_2_02_size_08x32
+vp90_2_02_size_08x34
+vp90_2_02_size_08x64
+vp90_2_02_size_08x66
+vp90_2_02_size_10x08
+vp90_2_02_size_10x10
+vp90_2_02_size_10x16
+vp90_2_02_size_10x18
+vp90_2_02_size_10x32
+vp90_2_02_size_10x34
+vp90_2_02_size_10x64
+vp90_2_02_size_10x66
+vp90_2_02_size_16x08
+vp90_2_02_size_16x10
+vp90_2_02_size_16x16
+vp90_2_02_size_16x18
+vp90_2_02_size_16x32
+vp90_2_02_size_16x34
+vp90_2_02_size_16x64
+vp90_2_02_size_16x66
+vp90_2_02_size_18x08
+vp90_2_02_size_18x10
+vp90_2_02_size_18x16
+vp90_2_02_size_18x18
+vp90_2_02_size_18x32
+vp90_2_02_size_18x34
+vp90_2_02_size_18x64
+vp90_2_02_size_18x66
+vp90_2_02_size_32x08
+vp90_2_02_size_32x10
+vp90_2_02_size_32x16
+vp90_2_02_size_32x18
+vp90_2_02_size_32x32
+vp90_2_02_size_32x34
+vp90_2_02_size_32x64
+vp90_2_02_size_32x66
+vp90_2_02_size_34x08
+vp90_2_02_size_34x10
+vp90_2_02_size_34x16
+vp90_2_02_size_34x18
+vp90_2_02_size_34x32
+vp90_2_02_size_34x34
+vp90_2_02_size_34x64
+vp90_2_02_size_34x66
+vp90_2_02_size_64x08
+vp90_2_02_size_64x10
+vp90_2_02_size_64x16
+vp90_2_02_size_64x18
+vp90_2_02_size_64x32
+vp90_2_02_size_64x34
+vp90_2_02_size_64x64
+vp90_2_02_size_64x66
+vp90_2_02_size_66x08
+vp90_2_02_size_66x10
+vp90_2_02_size_66x16
+vp90_2_02_size_66x18
+vp90_2_02_size_66x32
+vp90_2_02_size_66x34
+vp90_2_02_size_66x64
+vp90_2_02_size_66x66
+vp90_2_02_size_130x132
+vp90_2_02_size_132x130
+vp90_2_02_size_132x132
+vp90_2_02_size_178x180
+vp90_2_02_size_180x178
+vp90_2_02_size_180x180
+vp90_2_03_size_196x196
+vp90_2_03_size_196x198
+vp90_2_03_size_196x200
+vp90_2_03_size_196x202
+vp90_2_03_size_196x208
+vp90_2_03_size_196x210
+vp90_2_03_size_196x224
+vp90_2_03_size_196x226
+vp90_2_03_size_198x196
+vp90_2_03_size_198x198
+vp90_2_03_size_198x200
+vp90_2_03_size_198x202
+vp90_2_03_size_198x208
+vp90_2_03_size_198x210
+vp90_2_03_size_198x224
+vp90_2_03_size_198x226
+vp90_2_03_size_200x196
+vp90_2_03_size_200x198
+vp90_2_03_size_200x200
+vp90_2_03_size_200x202
+vp90_2_03_size_200x208
+vp90_2_03_size_200x210
+vp90_2_03_size_200x224
+vp90_2_03_size_200x226
+vp90_2_03_size_202x196
+vp90_2_03_size_202x198
+vp90_2_03_size_202x200
+vp90_2_03_size_202x202
+vp90_2_03_size_202x208
+vp90_2_03_size_202x210
+vp90_2_03_size_202x224
+vp90_2_03_size_202x226
+vp90_2_03_size_208x196
+vp90_2_03_size_208x198
+vp90_2_03_size_208x200
+vp90_2_03_size_208x202
+vp90_2_03_size_208x208
+vp90_2_03_size_208x210
+vp90_2_03_size_208x224
+vp90_2_03_size_208x226
+vp90_2_03_size_210x196
+vp90_2_03_size_210x198
+vp90_2_03_size_210x200
+vp90_2_03_size_210x202
+vp90_2_03_size_210x208
+vp90_2_03_size_210x210
+vp90_2_03_size_210x224
+vp90_2_03_size_210x226
+vp90_2_03_size_224x196
+vp90_2_03_size_224x198
+vp90_2_03_size_224x200
+vp90_2_03_size_224x202
+vp90_2_03_size_224x208
+vp90_2_03_size_224x210
+vp90_2_03_size_224x224
+vp90_2_03_size_224x226
+vp90_2_03_size_226x196
+vp90_2_03_size_226x198
+vp90_2_03_size_226x200
+vp90_2_03_size_226x202
+vp90_2_03_size_226x208
+vp90_2_03_size_226x210
+vp90_2_03_size_226x224
+vp90_2_03_size_226x226
+vp90_2_02_size_lf_1920x1080
+vp90_2_03_deltaq
+vp90_2_06_bilinear
+vp90_2_07_frame_parallel_1
+vp90_2_07_frame_parallel
+vp90_2_08_tile_1x2_frame_parallel
+vp90_2_08_tile_1x2
+vp90_2_08_tile_1x4_frame_parallel
+vp90_2_08_tile_1x4
+vp90_2_08_tile_1x8_frame_parallel
+vp90_2_08_tile_1x8
+vp90_2_08_tile_4x1
+vp90_2_08_tile_4x4
+vp90_2_09_aq2
+vp90_2_09_lf_deltas
+vp90_2_09_subpixel_00
+vp90_2_10_show_existing_frame2
+vp90_2_10_show_existing_frame
+vp90_2_12_droppable_1
+vp90_2_12_droppable_2
+vp90_2_12_droppable_3
+vp90_2_15_segkey_adpq
+vp90_2_15_segkey
+vp90_2_16_intra_only
+vp90_2_17_show_existing_frame
+vp90_2_19_skip_01
+vp90_2_19_skip_02
+vp90_2_19_skip
+vp90_2_20_big_superframe_01
+vp90_2_20_big_superframe_02
diff --git a/tests/tests/media/src/android/media/cts/CodecUtils.java b/tests/tests/media/src/android/media/cts/CodecUtils.java
index b7ebb88..dd8efdb 100644
--- a/tests/tests/media/src/android/media/cts/CodecUtils.java
+++ b/tests/tests/media/src/android/media/cts/CodecUtils.java
@@ -16,12 +16,18 @@
 
 package android.media.cts;
 
+import android.graphics.ImageFormat;
 import android.graphics.Rect;
 import android.media.cts.CodecImage;
 import android.media.Image;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
 import android.util.Log;
 
 import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.util.ArrayList;
 
 public class CodecUtils  {
     private static final String TAG = "CodecUtils";
@@ -140,5 +146,100 @@
     }
 
     public native static float[] Raw2YUVStats(long[] rawStats);
+
+    public static String[] getDecoderNames(String mime, boolean isGoog) {
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        ArrayList<String> result = new ArrayList<String>();
+        for (MediaCodecInfo info : mcl.getCodecInfos()) {
+            CodecCapabilities caps = null;
+            try {
+                caps = info.getCapabilitiesForType(mime);
+            } catch (IllegalArgumentException e) {  // mime is not supported
+                continue;
+            }
+            result.add(info.getName());
+        }
+        return result.toArray(new String[result.size()]);
+    }
+
+    public static String getImageMD5Checksum(Image image) throws Exception {
+        int format = image.getFormat();
+        if (ImageFormat.YUV_420_888 != format) {
+            Log.w(TAG, "unsupported image format");
+            return "";
+        }
+
+        MessageDigest md = MessageDigest.getInstance("MD5");
+
+        int imageWidth = image.getWidth();
+        int imageHeight = image.getHeight();
+
+        Image.Plane[] planes = image.getPlanes();
+        for (int i = 0; i < planes.length; ++i) {
+            ByteBuffer buf = planes[i].getBuffer();
+
+            int width, height, rowStride, pixelStride, x, y;
+            rowStride = planes[i].getRowStride();
+            pixelStride = planes[i].getPixelStride();
+            if (i == 0) {
+                width = imageWidth;
+                height = imageHeight;
+            } else {
+                width = imageWidth / 2;
+                height = imageHeight /2;
+            }
+            // local contiguous pixel buffer
+            byte[] bb = new byte[width * height];
+            if (buf.hasArray()) {
+                byte b[] = buf.array();
+                int offs = buf.arrayOffset();
+                if (pixelStride == 1) {
+                    for (y = 0; y < height; ++y) {
+                        System.arraycopy(bb, y * width, b, y * rowStride + offs, width);
+                    }
+                } else {
+                    // do it pixel-by-pixel
+                    for (y = 0; y < height; ++y) {
+                        int lineOffset = offs + y * rowStride;
+                        for (x = 0; x < width; ++x) {
+                            bb[y * width + x] = b[lineOffset + x * pixelStride];
+                        }
+                    }
+                }
+            } else { // almost always ends up here due to direct buffers
+                int pos = buf.position();
+                if (pixelStride == 1) {
+                    for (y = 0; y < height; ++y) {
+                        buf.position(pos + y * rowStride);
+                        buf.get(bb, y * width, width);
+                    }
+                } else {
+                    // local line buffer
+                    byte[] lb = new byte[rowStride];
+                    // do it pixel-by-pixel
+                    for (y = 0; y < height; ++y) {
+                        buf.position(pos + y * rowStride);
+                        // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
+                        buf.get(lb, 0, pixelStride * (width - 1) + 1);
+                        for (x = 0; x < width; ++x) {
+                            bb[y * width + x] = lb[x * pixelStride];
+                        }
+                    }
+                }
+                buf.position(pos);
+            }
+            md.update(bb, 0, width * height);
+        }
+
+        return convertByteArrayToHEXString(md.digest());
+    }
+
+    private static String convertByteArrayToHEXString(byte[] ba) throws Exception {
+        StringBuilder result = new StringBuilder();
+        for (int i = 0; i < ba.length; i++) {
+            result.append(Integer.toString((ba[i] & 0xff) + 0x100, 16).substring(1));
+        }
+        return result.toString();
+    }
 }
 
diff --git a/tests/tests/media/src/android/media/cts/DecoderConformanceTest.java b/tests/tests/media/src/android/media/cts/DecoderConformanceTest.java
new file mode 100644
index 0000000..7a49fd0
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/DecoderConformanceTest.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.cts.R;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.cts.util.DeviceReportLog;
+import android.cts.util.MediaUtils;
+import android.media.cts.CodecUtils;
+import android.media.Image;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+import android.util.Range;
+
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+import com.android.compatibility.common.util.Stat;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Conformance test for decoders on the device.
+ *
+ * This test will decode test vectors and calculate every decoded frame's md5
+ * checksum to see if it matches with the correct md5 value read from a
+ * reference file associated with the test vector. Test vector md5 sums are
+ * based on the YUV 420 plannar format.
+ */
+public class DecoderConformanceTest extends MediaPlayerTestBase {
+    private static enum Status {
+        FAIL,
+        PASS,
+        SKIP;
+    }
+
+    private static final String TAG = "DecoderConformanceTest";
+    private Resources mResources;
+    private DeviceReportLog mReportLog;
+    private MediaCodec mDecoder;
+    private MediaExtractor mExtractor;
+
+    private static final Map<String, String> MIMETYPE_TO_TAG = new HashMap <String, String>() {{
+        put(MediaFormat.MIMETYPE_VIDEO_VP9, "vp9");
+    }};
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+        mReportLog = new DeviceReportLog();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mReportLog.deliverReportToHost(getInstrumentation());
+        super.tearDown();
+    }
+
+
+    private List<String> readResourceLines(String fileName) throws Exception {
+        int resId = mResources.getIdentifier(fileName, "raw", mContext.getPackageName());
+        InputStream is = mContext.getResources().openRawResource(resId);
+        BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+
+        // Read the file line by line.
+        List<String> lines = new ArrayList<String>();
+        String str;
+        while ((str = in.readLine()) != null) {
+            int k = str.indexOf(' ');
+            String line = k >= 0 ? str.substring(0, k) : str;
+            lines.add(line);
+        }
+
+        is.close();
+        return lines;
+    }
+
+    private List<String> readCodecTestVectors(String mime) throws Exception {
+        String tag = MIMETYPE_TO_TAG.get(mime);
+        String testVectorFileName = tag + "_test_vectors";
+        return readResourceLines(testVectorFileName);
+    }
+
+    private List<String> readVectorMD5Sums(String mime, String vectorName) throws Exception {
+        String tag = MIMETYPE_TO_TAG.get(mime);
+        String md5FileName = vectorName + "_" + tag + "_md5";
+        return readResourceLines(md5FileName);
+    }
+
+    private void releaseMediacodec() {
+        try {
+            mDecoder.stop();
+        } catch (Exception e) {
+            Log.e(TAG, "Mediacodec stop exception");
+        }
+
+        try {
+            mDecoder.release();
+            mExtractor.release();
+        } catch (Exception e) {
+            Log.e(TAG, "Mediacodec release exception");
+        }
+
+        mDecoder = null;
+        mExtractor = null;
+    }
+
+    private Status decodeTestVector(String mime, String decoderName, String vectorName) throws Exception {
+        int resId = mResources.getIdentifier(vectorName, "raw", mContext.getPackageName());
+        AssetFileDescriptor testFd = mResources.openRawResourceFd(resId);
+        mExtractor = new MediaExtractor();
+        mExtractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                                 testFd.getLength());
+        mExtractor.selectTrack(0);
+        int trackIndex = mExtractor.getSampleTrackIndex();
+        MediaFormat format = mExtractor.getTrackFormat(trackIndex);
+        mDecoder = MediaCodec.createByCodecName(decoderName);
+
+        MediaCodecInfo codecInfo = mDecoder.getCodecInfo();
+        MediaCodecInfo.CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime);
+        if (!caps.isFormatSupported(format)) {
+            return Status.SKIP;
+        }
+
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        int decodeFrameCount = 0;
+        boolean sawInputEOS = false;
+        boolean sawOutputEOS = false;
+        final long kTimeOutUs = 5000; // 5ms timeout
+        List<String> frameMD5Sums;
+
+        try {
+            frameMD5Sums = readVectorMD5Sums(mime, vectorName);
+        } catch(Exception e) {
+            Log.e(TAG, "Fail to read " + vectorName + "md5sum file");
+            return Status.FAIL;
+        }
+
+        int expectFrameCount = frameMD5Sums.size();
+        mDecoder.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+        mDecoder.start();
+
+        while (!sawOutputEOS) {
+            // handle input
+            if (!sawInputEOS) {
+                int inputIndex = mDecoder.dequeueInputBuffer(kTimeOutUs);
+                if (inputIndex >= 0) {
+                    ByteBuffer buffer = mDecoder.getInputBuffer(inputIndex);
+                    int sampleSize = mExtractor.readSampleData(buffer, 0);
+                    if (sampleSize < 0) {
+                        mDecoder.queueInputBuffer(inputIndex, 0, 0, 0,
+                                                  MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+                        sawInputEOS = true;
+                    } else {
+                        mDecoder.queueInputBuffer(inputIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
+                        mExtractor.advance();
+                    }
+                }
+            }
+
+            // handle output
+            int outputBufIndex = mDecoder.dequeueOutputBuffer(info, kTimeOutUs);
+            if (outputBufIndex >= 0) {
+                if (info.size > 0) { // Disregard 0-sized buffers at the end.
+                    MediaFormat bufferFormat = mDecoder.getOutputFormat(outputBufIndex);
+                    int width = bufferFormat.getInteger(MediaFormat.KEY_WIDTH);
+                    int height = bufferFormat.getInteger(MediaFormat.KEY_HEIGHT);
+                    int colorFmt = bufferFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+
+                    String md5CheckSum = "";
+                    try  {
+                        Image image = mDecoder.getOutputImage(outputBufIndex);
+                        md5CheckSum = CodecUtils.getImageMD5Checksum(image);
+                    } catch (Exception e) {
+                        Log.e(TAG, "getOutputImage md5CheckSum failed", e);
+                        return Status.FAIL;
+                    }
+
+                    if (!md5CheckSum.equals(frameMD5Sums.get(decodeFrameCount))) {
+                        Log.d(TAG, "Frame " + decodeFrameCount + " md5sum mismatch");
+                        return Status.FAIL;
+                    }
+
+                    decodeFrameCount++;
+                }
+                mDecoder.releaseOutputBuffer(outputBufIndex, false /* render */);
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    sawOutputEOS = true;
+                }
+            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                MediaFormat decOutputFormat = mDecoder.getOutputFormat();
+                int width = decOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
+                int height = decOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
+                Log.d(TAG, "output format " + decOutputFormat);
+            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                Log.i(TAG, "Skip handling MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED");
+            } else {
+                assertEquals(
+                        "decoder.dequeueOutputBuffer() unrecognized return index: " + outputBufIndex,
+                        MediaCodec.INFO_TRY_AGAIN_LATER, outputBufIndex);
+            }
+        }
+
+        if (decodeFrameCount != expectFrameCount) {
+            Log.d(TAG, vectorName + " decode frame count not match");
+            return Status.FAIL;
+        }
+
+        mDecoder.stop();
+        mDecoder.release();
+        mExtractor.release();
+        return Status.PASS;
+    }
+
+    void decodeTestVectors(String mime, boolean isGoog) throws Exception {
+        String[] decoderNames = CodecUtils.getDecoderNames(mime, isGoog);
+        for (String decoderName: decoderNames) {
+            List<String> testVectors = readCodecTestVectors(mime);
+            for (String vectorName: testVectors) {
+                boolean pass = false;
+                Log.d(TAG, "Decode vector " + vectorName + " with " + decoderName);
+                try {
+                    Status stat = decodeTestVector(mime, decoderName, vectorName);
+                    if (stat == Status.PASS) {
+                        pass = true;
+                    } else if (stat == Status.SKIP) {
+                        continue;
+                    }
+                } catch (Exception e) {
+                    Log.e(TAG, "Decode " + vectorName + " fail");
+                }
+
+                if (pass) {
+                    mReportLog.printValue(vectorName, 1, ResultType.NEUTRAL, ResultUnit.NONE);
+                } else {
+                    mReportLog.printValue(vectorName, 0, ResultType.NEUTRAL, ResultUnit.NONE);
+                    // Release mediacodec in failure or exception casees.
+                    releaseMediacodec();
+                }
+            }
+            mReportLog.printSummary(decoderName, 0, ResultType.NEUTRAL, ResultUnit.NONE);
+        }
+    }
+
+    /**
+     * Test VP9 decoders from vendor.
+     */
+    public void testVP9Other() throws Exception {
+        decodeTestVectors(MediaFormat.MIMETYPE_VIDEO_VP9, false /* isGoog */);
+    }
+
+    /**
+     * Test Google's VP9 decoder from libvpx.
+     */
+    public void testVP9Goog() throws Exception {
+        decodeTestVectors(MediaFormat.MIMETYPE_VIDEO_VP9, true /* isGoog */);
+    }
+
+}
diff --git a/tests/tests/media/src/android/media/cts/IvfWriter.java b/tests/tests/media/src/android/media/cts/IvfWriter.java
index 075f73c..36fb679 100644
--- a/tests/tests/media/src/android/media/cts/IvfWriter.java
+++ b/tests/tests/media/src/android/media/cts/IvfWriter.java
@@ -16,6 +16,8 @@
 
 package android.media.cts;
 
+import android.media.MediaFormat;
+
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
@@ -34,6 +36,7 @@
     private int mScale;
     private int mRate;
     private int mFrameCount;
+    private String mMimeType;
 
     /**
      * Initializes the IVF file writer.
@@ -43,15 +46,17 @@
      * with this timebase value.
      *
      * @param filename   name of the IVF file
+     * @param mimeType   mime type of the codec
      * @param width      frame width
      * @param height     frame height
      * @param scale      timebase scale (or numerator of the timebase fraction)
      * @param rate       timebase rate (or denominator of the timebase fraction)
      */
-    public IvfWriter(String filename,
-                     int width, int height,
-                     int scale, int rate) throws IOException {
+    public IvfWriter(
+            String filename, String mimeType, int width, int height, int scale,
+            int rate) throws IOException {
         mOutputFile = new RandomAccessFile(filename, "rw");
+        mMimeType = mimeType;
         mWidth = width;
         mHeight = height;
         mScale = scale;
@@ -67,11 +72,12 @@
      * Microsecond timebase is default for OMX thus stagefright.
      *
      * @param filename   name of the IVF file
+     * @param mimeType   mime type of the codec
      * @param width      frame width
      * @param height     frame height
      */
-    public IvfWriter(String filename, int width, int height) throws IOException {
-        this(filename, width, height, 1, 1000000);
+    public IvfWriter(String filename, String mimeType, int width, int height) throws IOException {
+        this(filename, mimeType, width, height, 1, 1000000);
     }
 
     /**
@@ -80,7 +86,7 @@
     public void close() throws IOException{
         // Write header now
         mOutputFile.seek(0);
-        mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate));
+        mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate, mMimeType));
         mOutputFile.close();
     }
 
@@ -107,7 +113,8 @@
      * @param scale      timebase scale (or numerator of the timebase fraction)
      * @param rate       timebase rate (or denominator of the timebase fraction)
      */
-    private static byte[] makeIvfHeader(int frameCount, int width, int height, int scale, int rate){
+    private static byte[] makeIvfHeader(
+            int frameCount, int width, int height, int scale, int rate, String mimeType) {
         byte[] ivfHeader = new byte[32];
         ivfHeader[0] = 'D';
         ivfHeader[1] = 'K';
@@ -117,7 +124,7 @@
         lay16Bits(ivfHeader, 6, 32);  // header size
         ivfHeader[8] = 'V';  // fourcc
         ivfHeader[9] = 'P';
-        ivfHeader[10] = '8';
+        ivfHeader[10] = (byte) (MediaFormat.MIMETYPE_VIDEO_VP8.equals(mimeType) ? '8' : '9');
         ivfHeader[11] = '0';
         lay16Bits(ivfHeader, 12, width);
         lay16Bits(ivfHeader, 14, height);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 5b2936b..b579c6d 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -52,12 +52,8 @@
     private static final int TIMEOUT_US = 1000000;  // 1 sec
     private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
 
-    private final MediaCodecList mRegularCodecs =
-            new MediaCodecList(MediaCodecList.REGULAR_CODECS);
     private final MediaCodecList mAllCodecs =
             new MediaCodecList(MediaCodecList.ALL_CODECS);
-    private final MediaCodecInfo[] mRegularInfos =
-            mRegularCodecs.getCodecInfos();
     private final MediaCodecInfo[] mAllInfos =
             mAllCodecs.getCodecInfos();
 
@@ -391,7 +387,7 @@
         // check if there is an adaptive decoder for each
         for (String mime : supportedFormats) {
             skipped = false;
-            // implicit assumption that QVGA video is always valid.
+            // implicit assumption that QCIF video is always valid.
             MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
             format.setFeatureEnabled(CodecCapabilities.FEATURE_AdaptivePlayback, true);
             String codec = mAllCodecs.findDecoderForFormat(format);
@@ -501,7 +497,7 @@
                 MediaFormat format = null;
                 try {
                     codec = MediaCodec.createByCodecName(info.getName());
-                    // implicit assumption that QVGA video is always valid.
+                    // implicit assumption that QCIF video is always valid.
                     format = createReasonableVideoFormat(caps, mime, isEncoder, 176, 144);
                     format.setInteger(
                             MediaFormat.KEY_COLOR_FORMAT,
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
deleted file mode 100644
index 0395ec7..0000000
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ /dev/null
@@ -1,2000 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.cts;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.media.MediaCodec;
-import android.media.MediaCodec.CodecException;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecList;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Looper;
-import android.os.Handler;
-import android.test.AndroidTestCase;
-import android.util.Log;
-import android.media.cts.R;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.Locale;
-import java.util.ArrayList;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Verification test for vp8 encoder and decoder.
- *
- * A raw yv12 stream is encoded at various settings and written to an IVF
- * file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
- * calculate PSNR values for various bitrates.
- */
-public class Vp8CodecTestBase extends AndroidTestCase {
-
-    protected static final String TAG = "VP8CodecTestBase";
-    protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
-    private static final String GOOGLE_CODEC_PREFIX = "omx.google.";
-    protected static final String SDCARD_DIR =
-            Environment.getExternalStorageDirectory().getAbsolutePath();
-
-    // Default timeout for MediaCodec buffer dequeue - 200 ms.
-    protected static final long DEFAULT_DEQUEUE_TIMEOUT_US = 200000;
-    // Default timeout for MediaEncoderAsync - 30 sec.
-    protected static final long DEFAULT_ENCODE_TIMEOUT_MS = 30000;
-    // Default sync frame interval in frames (zero means allow the encoder to auto-select
-    // key frame interval).
-    private static final int SYNC_FRAME_INTERVAL = 0;
-    // Video bitrate type - should be set to OMX_Video_ControlRateConstant from OMX_Video.h
-    protected static final int VIDEO_ControlRateVariable = 1;
-    protected static final int VIDEO_ControlRateConstant = 2;
-    // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
-    // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
-    private static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04;
-    // Allowable color formats supported by codec - in order of preference.
-    private static final int[] mSupportedColorList = {
-            CodecCapabilities.COLOR_FormatYUV420Planar,
-            CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
-            CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
-            COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m
-    };
-    // Scaled image cache list - contains scale factors, for which up-scaled frames
-    // were calculated and were written to yuv file.
-    ArrayList<Integer> mScaledImages = new ArrayList<Integer>();
-
-    private Resources mResources;
-
-    @Override
-    public void setContext(Context context) {
-        super.setContext(context);
-        mResources = mContext.getResources();
-    }
-
-    /**
-     *  VP8 codec properties generated by getVp8CodecProperties() function.
-     */
-    private class CodecProperties {
-        CodecProperties(String codecName, int colorFormat) {
-            this.codecName = codecName;
-            this.colorFormat = colorFormat;
-        }
-        public boolean  isGoogleCodec() {
-            return codecName.toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
-        }
-
-        public final String codecName; // OpenMax component name for VP8 codec.
-        public final int colorFormat;  // Color format supported by codec.
-    }
-
-    /**
-     * Function to find VP8 codec.
-     *
-     * Iterates through the list of available codecs and tries to find
-     * VPX codec, which can support either YUV420 planar or NV12 color formats.
-     * If forceGoogleCodec parameter set to true the function always returns
-     * Google VPX codec.
-     * If forceGoogleCodec parameter set to false the functions looks for platform
-     * specific VPX codec first. If no platform specific codec exist, falls back to
-     * Google VPX codec.
-     *
-     * @param isEncoder     Flag if encoder is requested.
-     * @param forceGoogleCodec  Forces to use Google codec.
-     */
-    private CodecProperties getVpxCodecProperties(
-            boolean isEncoder,
-            MediaFormat format,
-            boolean forceGoogleCodec) throws Exception {
-        CodecProperties codecProperties = null;
-        String mime = format.getString(MediaFormat.KEY_MIME);
-
-        // Loop through the list of omx components in case platform specific codec
-        // is requested.
-        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-        for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
-            if (isEncoder != codecInfo.isEncoder()) {
-                continue;
-            }
-            Log.v(TAG, codecInfo.getName());
-            // TODO: remove dependence of Google from the test
-            // Check if this is Google codec - we should ignore it.
-            boolean isGoogleCodec =
-                codecInfo.getName().toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
-            if (!isGoogleCodec && forceGoogleCodec) {
-                continue;
-            }
-
-            for (String type : codecInfo.getSupportedTypes()) {
-                if (!type.equalsIgnoreCase(mime)) {
-                    continue;
-                }
-                CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(type);
-                if (!capabilities.isFormatSupported(format)) {
-                    continue;
-                }
-
-                // Get candidate codec properties.
-                Log.v(TAG, "Found candidate codec " + codecInfo.getName());
-                for (int colorFormat: capabilities.colorFormats) {
-                    Log.v(TAG, "   Color: 0x" + Integer.toHexString(colorFormat));
-                }
-
-                // Check supported color formats.
-                for (int supportedColorFormat : mSupportedColorList) {
-                    for (int codecColorFormat : capabilities.colorFormats) {
-                        if (codecColorFormat == supportedColorFormat) {
-                            codecProperties = new CodecProperties(codecInfo.getName(),
-                                    codecColorFormat);
-                            Log.v(TAG, "Found target codec " + codecProperties.codecName +
-                                    ". Color: 0x" + Integer.toHexString(codecColorFormat));
-                            // return first HW codec found
-                            if (!isGoogleCodec) {
-                                return codecProperties;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (codecProperties == null) {
-            Log.i(TAG, "no suitable " + (forceGoogleCodec ? "google " : "")
-                    + (isEncoder ? "encoder " : "decoder ") + "found for " + format);
-        }
-        return codecProperties;
-    }
-
-    /**
-     * Parameters for encoded video stream.
-     */
-    protected class EncoderOutputStreamParameters {
-        // Name of raw YUV420 input file. When the value of this parameter
-        // is set to null input file descriptor from inputResourceId parameter
-        // is used instead.
-        public String inputYuvFilename;
-        // Name of scaled YUV420 input file.
-        public String scaledYuvFilename;
-        // File descriptor for the raw input file (YUV420). Used only if
-        // inputYuvFilename parameter is null.
-        int inputResourceId;
-        // Name of the IVF file to write encoded bitsream
-        public String outputIvfFilename;
-        // Force to use Google VP8 encoder.
-        boolean forceGoogleEncoder;
-        // Number of frames to encode.
-        int frameCount;
-        // Frame rate of input file in frames per second.
-        int frameRate;
-        // Encoded frame width.
-        public int frameWidth;
-        // Encoded frame height.
-        public int frameHeight;
-        // Encoding bitrate array in bits/second for every frame. If array length
-        // is shorter than the total number of frames, the last value is re-used for
-        // all remaining frames. For constant bitrate encoding single element
-        // array can be used with first element set to target bitrate value.
-        public int[] bitrateSet;
-        // Encoding bitrate type - VBR or CBR
-        public int bitrateType;
-        // Number of temporal layers
-        public int temporalLayers;
-        // Desired key frame interval - codec is asked to generate key frames
-        // at a period defined by this parameter.
-        public int syncFrameInterval;
-        // Optional parameter - forced key frame interval. Used to
-        // explicitly request the codec to generate key frames using
-        // MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME parameter.
-        public int syncForceFrameInterval;
-        // Buffer timeout
-        long timeoutDequeue;
-        // Flag if encoder should run in Looper thread.
-        boolean runInLooperThread;
-    }
-
-    /**
-     * Generates an array of default parameters for encoder output stream based on
-     * upscaling value.
-     */
-    protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
-            String inputYuvName,
-            String outputIvfBaseName,
-            int encodeSeconds,
-            int[] resolutionScales,
-            int frameWidth,
-            int frameHeight,
-            int frameRate,
-            int bitrateMode,
-            int[] bitrates,
-            boolean syncEncoding) {
-        assertTrue(resolutionScales.length == bitrates.length);
-        int numCodecs = resolutionScales.length;
-        ArrayList<EncoderOutputStreamParameters> outputParameters =
-                new ArrayList<EncoderOutputStreamParameters>(numCodecs);
-        for (int i = 0; i < numCodecs; i++) {
-            EncoderOutputStreamParameters params = new EncoderOutputStreamParameters();
-            if (inputYuvName != null) {
-                params.inputYuvFilename = SDCARD_DIR + File.separator + inputYuvName;
-            } else {
-                params.inputYuvFilename = null;
-            }
-            params.scaledYuvFilename = SDCARD_DIR + File.separator +
-                    outputIvfBaseName + resolutionScales[i]+ ".yuv";
-            params.inputResourceId = R.raw.football_qvga;
-            params.outputIvfFilename = SDCARD_DIR + File.separator +
-                    outputIvfBaseName + resolutionScales[i] + ".ivf";
-            params.forceGoogleEncoder = false;
-            params.frameCount = encodeSeconds * frameRate;
-            params.frameRate = frameRate;
-            params.frameWidth = Math.min(frameWidth * resolutionScales[i], 1280);
-            params.frameHeight = Math.min(frameHeight * resolutionScales[i], 720);
-            params.bitrateSet = new int[1];
-            params.bitrateSet[0] = bitrates[i];
-            params.bitrateType = bitrateMode;
-            params.temporalLayers = 0;
-            params.syncFrameInterval = SYNC_FRAME_INTERVAL;
-            params.syncForceFrameInterval = 0;
-            if (syncEncoding) {
-                params.timeoutDequeue = DEFAULT_DEQUEUE_TIMEOUT_US;
-                params.runInLooperThread = false;
-            } else {
-                params.timeoutDequeue = 0;
-                params.runInLooperThread = true;
-            }
-            outputParameters.add(params);
-        }
-        return outputParameters;
-    }
-
-    protected EncoderOutputStreamParameters getDefaultEncodingParameters(
-            String inputYuvName,
-            String outputIvfBaseName,
-            int encodeSeconds,
-            int frameWidth,
-            int frameHeight,
-            int frameRate,
-            int bitrateMode,
-            int bitrate,
-            boolean syncEncoding) {
-        int[] scaleValues = { 1 };
-        int[] bitrates = { bitrate };
-        return getDefaultEncodingParameterList(
-                inputYuvName,
-                outputIvfBaseName,
-                encodeSeconds,
-                scaleValues,
-                frameWidth,
-                frameHeight,
-                frameRate,
-                bitrateMode,
-                bitrates,
-                syncEncoding).get(0);
-    }
-
-    /**
-     * Converts (interleaves) YUV420 planar to NV12.
-     * Assumes packed, macroblock-aligned frame with no cropping
-     * (visible/coded row length == stride).
-     */
-    private static byte[] YUV420ToNV(int width, int height, byte[] yuv) {
-        byte[] nv = new byte[yuv.length];
-        // Y plane we just copy.
-        System.arraycopy(yuv, 0, nv, 0, width * height);
-
-        // U & V plane we interleave.
-        int u_offset = width * height;
-        int v_offset = u_offset + u_offset / 4;
-        int nv_offset = width * height;
-        for (int i = 0; i < width * height / 4; i++) {
-            nv[nv_offset++] = yuv[u_offset++];
-            nv[nv_offset++] = yuv[v_offset++];
-        }
-        return nv;
-    }
-
-    /**
-     * Converts (de-interleaves) NV12 to YUV420 planar.
-     * Stride may be greater than width, slice height may be greater than height.
-     */
-    private static byte[] NV12ToYUV420(int width, int height,
-            int stride, int sliceHeight, byte[] nv12) {
-        byte[] yuv = new byte[width * height * 3 / 2];
-
-        // Y plane we just copy.
-        for (int i = 0; i < height; i++) {
-            System.arraycopy(nv12, i * stride, yuv, i * width, width);
-        }
-
-        // U & V plane - de-interleave.
-        int u_offset = width * height;
-        int v_offset = u_offset + u_offset / 4;
-        int nv_offset;
-        for (int i = 0; i < height / 2; i++) {
-            nv_offset = stride * (sliceHeight + i);
-            for (int j = 0; j < width / 2; j++) {
-                yuv[u_offset++] = nv12[nv_offset++];
-                yuv[v_offset++] = nv12[nv_offset++];
-            }
-        }
-        return yuv;
-    }
-
-    /**
-     * Packs YUV420 frame by moving it to a smaller size buffer with stride and slice
-     * height equal to the original frame width and height.
-     */
-    private static byte[] PackYUV420(int width, int height,
-            int stride, int sliceHeight, byte[] src) {
-        byte[] dst = new byte[width * height * 3 / 2];
-        // Y copy.
-        for (int i = 0; i < height; i++) {
-            System.arraycopy(src, i * stride, dst, i * width, width);
-        }
-        // U and V copy.
-        int u_src_offset = stride * sliceHeight;
-        int v_src_offset = u_src_offset + u_src_offset / 4;
-        int u_dst_offset = width * height;
-        int v_dst_offset = u_dst_offset + u_dst_offset / 4;
-        for (int i = 0; i < height / 2; i++) {
-            System.arraycopy(src, u_src_offset + i * (stride / 2),
-                    dst, u_dst_offset + i * (width / 2), width / 2);
-            System.arraycopy(src, v_src_offset + i * (stride / 2),
-                    dst, v_dst_offset + i * (width / 2), width / 2);
-        }
-        return dst;
-    }
-
-
-    private static void imageUpscale1To2(byte[] src, int srcByteOffset, int srcStride,
-            byte[] dst, int dstByteOffset, int dstWidth, int dstHeight) {
-        for (int i = 0; i < dstHeight/2 - 1; i++) {
-            int dstOffset0 = 2 * i * dstWidth + dstByteOffset;
-            int dstOffset1 = dstOffset0 + dstWidth;
-            int srcOffset0 = i * srcStride + srcByteOffset;
-            int srcOffset1 = srcOffset0 + srcStride;
-            int pixel00 = (int)src[srcOffset0++] & 0xff;
-            int pixel10 = (int)src[srcOffset1++] & 0xff;
-            for (int j = 0; j < dstWidth/2 - 1; j++) {
-                int pixel01 = (int)src[srcOffset0++] & 0xff;
-                int pixel11 = (int)src[srcOffset1++] & 0xff;
-                dst[dstOffset0++] = (byte)pixel00;
-                dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
-                dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
-                dst[dstOffset1++] = (byte)((pixel00 + pixel01 + pixel10 + pixel11 + 2) / 4);
-                pixel00 = pixel01;
-                pixel10 = pixel11;
-            }
-            // last column
-            dst[dstOffset0++] = (byte)pixel00;
-            dst[dstOffset0++] = (byte)pixel00;
-            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
-            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
-        }
-
-        // last row
-        int dstOffset0 = (dstHeight - 2) * dstWidth + dstByteOffset;
-        int dstOffset1 = dstOffset0 + dstWidth;
-        int srcOffset0 = (dstHeight/2 - 1) * srcStride + srcByteOffset;
-        int pixel00 = (int)src[srcOffset0++] & 0xff;
-        for (int j = 0; j < dstWidth/2 - 1; j++) {
-            int pixel01 = (int)src[srcOffset0++] & 0xff;
-            dst[dstOffset0++] = (byte)pixel00;
-            dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
-            dst[dstOffset1++] = (byte)pixel00;
-            dst[dstOffset1++] = (byte)((pixel00 + pixel01 + 1) / 2);
-            pixel00 = pixel01;
-        }
-        // the very last pixel - bottom right
-        dst[dstOffset0++] = (byte)pixel00;
-        dst[dstOffset0++] = (byte)pixel00;
-        dst[dstOffset1++] = (byte)pixel00;
-        dst[dstOffset1++] = (byte)pixel00;
-    }
-
-    /**
-    * Up-scale image.
-    * Scale factor is defined by source and destination width ratio.
-    * Only 1:2 and 1:4 up-scaling is supported for now.
-    * For 640x480 -> 1280x720 conversion only top 640x360 part of the original
-    * image is scaled.
-    */
-    private static byte[] imageScale(byte[] src, int srcWidth, int srcHeight,
-            int dstWidth, int dstHeight) throws Exception {
-        int srcYSize = srcWidth * srcHeight;
-        int dstYSize = dstWidth * dstHeight;
-        byte[] dst = null;
-        if (dstWidth == 2 * srcWidth && dstHeight <= 2 * srcHeight) {
-            // 1:2 upscale
-            dst = new byte[dstWidth * dstHeight * 3 / 2];
-            imageUpscale1To2(src, 0, srcWidth,
-                    dst, 0, dstWidth, dstHeight);                                 // Y
-            imageUpscale1To2(src, srcYSize, srcWidth / 2,
-                    dst, dstYSize, dstWidth / 2, dstHeight / 2);                  // U
-            imageUpscale1To2(src, srcYSize * 5 / 4, srcWidth / 2,
-                    dst, dstYSize * 5 / 4, dstWidth / 2, dstHeight / 2);          // V
-        } else if (dstWidth == 4 * srcWidth && dstHeight <= 4 * srcHeight) {
-            // 1:4 upscale - in two steps
-            int midWidth = 2 * srcWidth;
-            int midHeight = 2 * srcHeight;
-            byte[] midBuffer = imageScale(src, srcWidth, srcHeight, midWidth, midHeight);
-            dst = imageScale(midBuffer, midWidth, midHeight, dstWidth, dstHeight);
-
-        } else {
-            throw new RuntimeException("Can not find proper scaling function");
-        }
-
-        return dst;
-    }
-
-    private void cacheScaledImage(
-            String srcYuvFilename, int srcResourceId, int srcFrameWidth, int srcFrameHeight,
-            String dstYuvFilename, int dstFrameWidth, int dstFrameHeight) throws Exception {
-        InputStream srcStream = OpenFileOrResourceId(srcYuvFilename, srcResourceId);
-        FileOutputStream dstFile = new FileOutputStream(dstYuvFilename, false);
-        int srcFrameSize = srcFrameWidth * srcFrameHeight * 3 / 2;
-        byte[] srcFrame = new byte[srcFrameSize];
-        byte[] dstFrame = null;
-        Log.d(TAG, "Scale to " + dstFrameWidth + " x " + dstFrameHeight + ". -> " + dstYuvFilename);
-        while (true) {
-            int bytesRead = srcStream.read(srcFrame);
-            if (bytesRead != srcFrame.length) {
-                break;
-            }
-            if (dstFrameWidth == srcFrameWidth && dstFrameHeight == srcFrameHeight) {
-                dstFrame = srcFrame;
-            } else {
-                dstFrame = imageScale(srcFrame, srcFrameWidth, srcFrameHeight,
-                        dstFrameWidth, dstFrameHeight);
-            }
-            dstFile.write(dstFrame);
-        }
-        srcStream.close();
-        dstFile.close();
-    }
-
-
-    /**
-     * A basic check if an encoded stream is decodable.
-     *
-     * The most basic confirmation we can get about a frame
-     * being properly encoded is trying to decode it.
-     * (Especially in realtime mode encode output is non-
-     * deterministic, therefore a more thorough check like
-     * md5 sum comparison wouldn't work.)
-     *
-     * Indeed, MediaCodec will raise an IllegalStateException
-     * whenever vp8 decoder fails to decode a frame, and
-     * this test uses that fact to verify the bitstream.
-     *
-     * @param inputIvfFilename  The name of the IVF file containing encoded bitsream.
-     * @param outputYuvFilename The name of the output YUV file (optional).
-     * @param frameRate         Frame rate of input file in frames per second
-     * @param forceGoogleDecoder    Force to use Google VP8 decoder.
-     */
-    protected ArrayList<MediaCodec.BufferInfo> decode(
-            String inputIvfFilename,
-            String outputYuvFilename,
-            int frameRate,
-            boolean forceGoogleDecoder) throws Exception {
-        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
-
-        // Open input/output.
-        IvfReader ivf = new IvfReader(inputIvfFilename);
-        int frameWidth = ivf.getWidth();
-        int frameHeight = ivf.getHeight();
-        int frameCount = ivf.getFrameCount();
-        int frameStride = frameWidth;
-        int frameSliceHeight = frameHeight;
-        assertTrue(frameWidth > 0);
-        assertTrue(frameHeight > 0);
-        assertTrue(frameCount > 0);
-
-        // Create decoder.
-        MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, ivf.getWidth(), ivf.getHeight());
-        CodecProperties properties = getVpxCodecProperties(
-                false /* encoder */, format, forceGoogleDecoder);
-        if (properties == null) {
-            ivf.close();
-            return null;
-        }
-        int frameColorFormat = properties.colorFormat;
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
-
-        FileOutputStream yuv = null;
-        if (outputYuvFilename != null) {
-            yuv = new FileOutputStream(outputYuvFilename, false);
-        }
-
-        Log.d(TAG, "Creating decoder " + properties.codecName +
-                ". Color format: 0x" + Integer.toHexString(frameColorFormat) +
-                ". " + frameWidth + " x " + frameHeight);
-        Log.d(TAG, "  Format: " + format);
-        Log.d(TAG, "  In: " + inputIvfFilename + ". Out:" + outputYuvFilename);
-        MediaCodec decoder = MediaCodec.createByCodecName(properties.codecName);
-        decoder.configure(format,
-                          null,  // surface
-                          null,  // crypto
-                          0);    // flags
-        decoder.start();
-
-        ByteBuffer[] inputBuffers = decoder.getInputBuffers();
-        ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
-        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
-
-        // decode loop
-        int inputFrameIndex = 0;
-        int outputFrameIndex = 0;
-        long inPresentationTimeUs = 0;
-        long outPresentationTimeUs = 0;
-        boolean sawOutputEOS = false;
-        boolean sawInputEOS = false;
-
-        while (!sawOutputEOS) {
-            if (!sawInputEOS) {
-                int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_DEQUEUE_TIMEOUT_US);
-                if (inputBufIndex >= 0) {
-                    byte[] frame = ivf.readFrame(inputFrameIndex);
-
-                    if (inputFrameIndex == frameCount - 1) {
-                        Log.d(TAG, "  Input EOS for frame # " + inputFrameIndex);
-                        sawInputEOS = true;
-                    }
-
-                    inputBuffers[inputBufIndex].clear();
-                    inputBuffers[inputBufIndex].put(frame);
-                    inputBuffers[inputBufIndex].rewind();
-                    inPresentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
-
-                    decoder.queueInputBuffer(
-                            inputBufIndex,
-                            0,  // offset
-                            frame.length,
-                            inPresentationTimeUs,
-                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                    inputFrameIndex++;
-                }
-            }
-
-            int result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
-            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
-                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    outputBuffers = decoder.getOutputBuffers();
-                } else  if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    // Process format change
-                    format = decoder.getOutputFormat();
-                    frameWidth = format.getInteger(MediaFormat.KEY_WIDTH);
-                    frameHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
-                    frameColorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
-                    Log.d(TAG, "Decoder output format change. Color: 0x" +
-                            Integer.toHexString(frameColorFormat));
-                    Log.d(TAG, "Format: " + format.toString());
-
-                    // Parse frame and slice height from undocumented values
-                    if (format.containsKey("stride")) {
-                        frameStride = format.getInteger("stride");
-                    } else {
-                        frameStride = frameWidth;
-                    }
-                    if (format.containsKey("slice-height")) {
-                        frameSliceHeight = format.getInteger("slice-height");
-                    } else {
-                        frameSliceHeight = frameHeight;
-                    }
-                    Log.d(TAG, "Frame stride and slice height: " + frameStride +
-                            " x " + frameSliceHeight);
-                    frameStride = Math.max(frameWidth, frameStride);
-                    frameSliceHeight = Math.max(frameHeight, frameSliceHeight);
-                }
-                result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
-            }
-            if (result >= 0) {
-                int outputBufIndex = result;
-                outPresentationTimeUs = bufferInfo.presentationTimeUs;
-                Log.v(TAG, "Writing buffer # " + outputFrameIndex +
-                        ". Size: " + bufferInfo.size +
-                        ". InTime: " + (inPresentationTimeUs + 500)/1000 +
-                        ". OutTime: " + (outPresentationTimeUs + 500)/1000);
-                if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    sawOutputEOS = true;
-                    Log.d(TAG, "   Output EOS for frame # " + outputFrameIndex);
-                }
-
-                if (bufferInfo.size > 0) {
-                    // Save decoder output to yuv file.
-                    if (yuv != null) {
-                        byte[] frame = new byte[bufferInfo.size];
-                        outputBuffers[outputBufIndex].position(bufferInfo.offset);
-                        outputBuffers[outputBufIndex].get(frame, 0, bufferInfo.size);
-                        // Convert NV12 to YUV420 if necessary.
-                        if (frameColorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
-                            frame = NV12ToYUV420(frameWidth, frameHeight,
-                                    frameStride, frameSliceHeight, frame);
-                        }
-                        int writeLength = Math.min(frameWidth * frameHeight * 3 / 2, frame.length);
-                        // Pack frame if necessary.
-                        if (writeLength < frame.length &&
-                                (frameStride > frameWidth || frameSliceHeight > frameHeight)) {
-                            frame = PackYUV420(frameWidth, frameHeight,
-                                    frameStride, frameSliceHeight, frame);
-                        }
-                        yuv.write(frame, 0, writeLength);
-                    }
-                    outputFrameIndex++;
-
-                    // Update statistics - store presentation time delay in offset
-                    long presentationTimeUsDelta = inPresentationTimeUs - outPresentationTimeUs;
-                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
-                    bufferInfoCopy.set((int)presentationTimeUsDelta, bufferInfo.size,
-                            outPresentationTimeUs, bufferInfo.flags);
-                    bufferInfos.add(bufferInfoCopy);
-                }
-                decoder.releaseOutputBuffer(outputBufIndex, false);
-            }
-        }
-        decoder.stop();
-        decoder.release();
-        ivf.close();
-        if (yuv != null) {
-            yuv.close();
-        }
-
-        return bufferInfos;
-    }
-
-
-    /**
-     * Helper function to return InputStream from either filename (if set)
-     * or resource id (if filename is not set).
-     */
-    private InputStream OpenFileOrResourceId(String filename, int resourceId) throws Exception {
-        if (filename != null) {
-            return new FileInputStream(filename);
-        }
-        return mResources.openRawResource(resourceId);
-    }
-
-    /**
-     * Results of frame encoding.
-     */
-    protected class MediaEncoderOutput {
-        public long inPresentationTimeUs;
-        public long outPresentationTimeUs;
-        public boolean outputGenerated;
-        public int flags;
-        public byte[] buffer;
-    }
-
-    protected class MediaEncoderAsyncHelper {
-        private final EncoderOutputStreamParameters mStreamParams;
-        private final CodecProperties mProperties;
-        private final ArrayList<MediaCodec.BufferInfo> mBufferInfos;
-        private final IvfWriter mIvf;
-        private final byte[] mSrcFrame;
-
-        private InputStream mYuvStream;
-        private int mInputFrameIndex;
-
-        MediaEncoderAsyncHelper(
-                EncoderOutputStreamParameters streamParams,
-                CodecProperties properties,
-                ArrayList<MediaCodec.BufferInfo> bufferInfos,
-                IvfWriter ivf)
-                throws Exception {
-            mStreamParams = streamParams;
-            mProperties = properties;
-            mBufferInfos = bufferInfos;
-            mIvf = ivf;
-
-            int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
-            mSrcFrame = new byte[srcFrameSize];
-
-            mYuvStream = OpenFileOrResourceId(
-                    streamParams.inputYuvFilename, streamParams.inputResourceId);
-        }
-
-        public byte[] getInputFrame() {
-            // Check EOS
-            if (mStreamParams.frameCount == 0
-                    || (mStreamParams.frameCount > 0
-                            && mInputFrameIndex >= mStreamParams.frameCount)) {
-                Log.d(TAG, "---Sending EOS empty frame for frame # " + mInputFrameIndex);
-                return null;
-            }
-
-            try {
-                int bytesRead = mYuvStream.read(mSrcFrame);
-
-                if (bytesRead == -1) {
-                    // rewind to beginning of file
-                    mYuvStream.close();
-                    mYuvStream = OpenFileOrResourceId(
-                            mStreamParams.inputYuvFilename, mStreamParams.inputResourceId);
-                    bytesRead = mYuvStream.read(mSrcFrame);
-                }
-            } catch (Exception e) {
-                Log.e(TAG, "Failed to read YUV file.");
-                return null;
-            }
-            mInputFrameIndex++;
-
-            // Convert YUV420 to NV12 if necessary
-            if (mProperties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
-                return YUV420ToNV(mStreamParams.frameWidth, mStreamParams.frameHeight,
-                        mSrcFrame);
-            } else {
-                return mSrcFrame;
-            }
-        }
-
-        public boolean saveOutputFrame(MediaEncoderOutput out) {
-            if (out.outputGenerated) {
-                if (out.buffer.length > 0) {
-                    // Save frame
-                    try {
-                        mIvf.writeFrame(out.buffer, out.outPresentationTimeUs);
-                    } catch (Exception e) {
-                        Log.d(TAG, "Failed to write frame");
-                        return true;
-                    }
-
-                    // Update statistics - store presentation time delay in offset
-                    long presentationTimeUsDelta = out.inPresentationTimeUs -
-                            out.outPresentationTimeUs;
-                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
-                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
-                            out.outPresentationTimeUs, out.flags);
-                    mBufferInfos.add(bufferInfoCopy);
-                }
-                // Detect output EOS
-                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    Log.d(TAG, "----Output EOS ");
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Video encoder wrapper class.
-     * Allows to run the encoder either in a callee's thread or in a looper thread
-     * using buffer dequeue ready notification callbacks.
-     *
-     * Function feedInput() is used to send raw video frame to the encoder input. When encoder
-     * is configured to run in async mode the function will run in a looper thread.
-     * Encoded frame can be retrieved by calling getOutput() function.
-     */
-    protected class MediaEncoderAsync extends Thread {
-        private int mId;
-        private MediaCodec mCodec;
-        private MediaFormat mFormat;
-        private ByteBuffer[] mInputBuffers;
-        private ByteBuffer[] mOutputBuffers;
-        private int mInputFrameIndex;
-        private int mOutputFrameIndex;
-        private int mInputBufIndex;
-        private int mFrameRate;
-        private long mTimeout;
-        private MediaCodec.BufferInfo mBufferInfo;
-        private long mInPresentationTimeUs;
-        private long mOutPresentationTimeUs;
-        private boolean mAsync;
-        // Flag indicating if input frame was consumed by the encoder in feedInput() call.
-        private boolean mConsumedInput;
-        // Result of frame encoding returned by getOutput() call.
-        private MediaEncoderOutput mOutput;
-        // Object used to signal that looper thread has started and Handler instance associated
-        // with looper thread has been allocated.
-        private final Object mThreadEvent = new Object();
-        // Object used to signal that MediaCodec buffer dequeue notification callback
-        // was received.
-        private final Object mCallbackEvent = new Object();
-        private Handler mHandler;
-        private boolean mCallbackReceived;
-        private MediaEncoderAsyncHelper mHelper;
-        private final Object mCompletionEvent = new Object();
-        private boolean mCompleted;
-
-        private MediaCodec.Callback mCallback = new MediaCodec.Callback() {
-            @Override
-            public void onInputBufferAvailable(MediaCodec codec, int index) {
-                if (mHelper == null) {
-                    Log.e(TAG, "async helper not available");
-                    return;
-                }
-
-                byte[] encFrame = mHelper.getInputFrame();
-                boolean inputEOS = (encFrame == null);
-
-                int encFrameLength = 0;
-                int flags = 0;
-                if (inputEOS) {
-                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
-                } else {
-                    encFrameLength = encFrame.length;
-
-                    ByteBuffer byteBuffer = mCodec.getInputBuffer(index);
-                    byteBuffer.put(encFrame);
-                    byteBuffer.rewind();
-
-                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
-
-                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
-                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
-
-                    mInputFrameIndex++;
-                }
-
-                mCodec.queueInputBuffer(
-                        index,
-                        0,  // offset
-                        encFrameLength,  // size
-                        mInPresentationTimeUs,
-                        flags);
-            }
-
-            @Override
-            public void onOutputBufferAvailable(MediaCodec codec,
-                    int index, MediaCodec.BufferInfo info) {
-                if (mHelper == null) {
-                    Log.e(TAG, "async helper not available");
-                    return;
-                }
-
-                MediaEncoderOutput out = new MediaEncoderOutput();
-
-                out.buffer = new byte[info.size];
-                ByteBuffer outputBuffer = mCodec.getOutputBuffer(index);
-                outputBuffer.get(out.buffer, 0, info.size);
-                mOutPresentationTimeUs = info.presentationTimeUs;
-
-                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
-                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
-                    logStr += " CONFIG. ";
-                }
-                if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
-                    logStr += " KEY. ";
-                }
-                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    logStr += " EOS. ";
-                }
-                logStr += " Size: " + info.size;
-                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
-                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
-                Log.v(TAG, logStr);
-
-                if (mOutputFrameIndex == 0 &&
-                        ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
-                    throw new RuntimeException("First frame is not a sync frame.");
-                }
-
-                if (info.size > 0) {
-                    mOutputFrameIndex++;
-                    out.inPresentationTimeUs = mInPresentationTimeUs;
-                    out.outPresentationTimeUs = mOutPresentationTimeUs;
-                }
-                mCodec.releaseOutputBuffer(index, false);
-
-                out.flags = info.flags;
-                out.outputGenerated = true;
-
-                if (mHelper.saveOutputFrame(out)) {
-                    // output EOS
-                    signalCompletion();
-                }
-            }
-
-            @Override
-            public void onError(MediaCodec codec, CodecException e) {
-                Log.e(TAG, "onError: " + e
-                        + ", transient " + e.isTransient()
-                        + ", recoverable " + e.isRecoverable()
-                        + ", error " + e.getErrorCode());
-            }
-
-            @Override
-            public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
-                Log.i(TAG, "onOutputFormatChanged: " + format.toString());
-            }
-        };
-
-        private synchronized void requestStart() throws Exception {
-            mHandler = null;
-            start();
-            // Wait for Hander allocation
-            synchronized (mThreadEvent) {
-                while (mHandler == null) {
-                    mThreadEvent.wait();
-                }
-            }
-        }
-
-        public void setAsyncHelper(MediaEncoderAsyncHelper helper) {
-            mHelper = helper;
-        }
-
-        @Override
-        public void run() {
-            Looper.prepare();
-            synchronized (mThreadEvent) {
-                mHandler = new Handler();
-                mThreadEvent.notify();
-            }
-            Looper.loop();
-        }
-
-        private void runCallable(final Callable<?> callable) throws Exception {
-            if (mAsync) {
-                final Exception[] exception = new Exception[1];
-                final CountDownLatch countDownLatch = new CountDownLatch(1);
-                mHandler.post( new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            callable.call();
-                        } catch (Exception e) {
-                            exception[0] = e;
-                        } finally {
-                            countDownLatch.countDown();
-                        }
-                    }
-                } );
-
-                // Wait for task completion
-                countDownLatch.await();
-                if (exception[0] != null) {
-                    throw exception[0];
-                }
-            } else {
-                callable.call();
-            }
-        }
-
-        private synchronized void requestStop() throws Exception {
-            mHandler.post( new Runnable() {
-                @Override
-                public void run() {
-                    // This will run on the Looper thread
-                    Log.v(TAG, "MediaEncoder looper quitting");
-                    Looper.myLooper().quitSafely();
-                }
-            } );
-            // Wait for completion
-            join();
-            mHandler = null;
-        }
-
-        private void createCodecInternal(final String name,
-                final MediaFormat format, final long timeout) throws Exception {
-            mBufferInfo = new MediaCodec.BufferInfo();
-            mFormat = format;
-            mFrameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
-            mTimeout = timeout;
-            mInputFrameIndex = 0;
-            mOutputFrameIndex = 0;
-            mInPresentationTimeUs = 0;
-            mOutPresentationTimeUs = 0;
-
-            mCodec = MediaCodec.createByCodecName(name);
-            if (mAsync) {
-                mCodec.setCallback(mCallback);
-            }
-            mCodec.configure(mFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
-            mCodec.start();
-
-            // get the cached input/output only in sync mode
-            if (!mAsync) {
-                mInputBuffers = mCodec.getInputBuffers();
-                mOutputBuffers = mCodec.getOutputBuffers();
-            }
-        }
-
-        public void createCodec(int id, final String name, final MediaFormat format,
-                final long timeout, boolean async)  throws Exception {
-            mId = id;
-            mAsync = async;
-            if (mAsync) {
-                requestStart(); // start looper thread
-            }
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    createCodecInternal(name, format, timeout);
-                    return null;
-                }
-            } );
-        }
-
-        private void feedInputInternal(final byte[] encFrame, final boolean inputEOS) {
-            mConsumedInput = false;
-            // Feed input
-            mInputBufIndex = mCodec.dequeueInputBuffer(mTimeout);
-
-            if (mInputBufIndex >= 0) {
-                mInputBuffers[mInputBufIndex].clear();
-                mInputBuffers[mInputBufIndex].put(encFrame);
-                mInputBuffers[mInputBufIndex].rewind();
-                int encFrameLength = encFrame.length;
-                int flags = 0;
-                if (inputEOS) {
-                    encFrameLength = 0;
-                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
-                }
-                if (!inputEOS) {
-                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
-                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
-                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
-                    mInputFrameIndex++;
-                }
-
-                mCodec.queueInputBuffer(
-                        mInputBufIndex,
-                        0,  // offset
-                        encFrameLength,  // size
-                        mInPresentationTimeUs,
-                        flags);
-
-                mConsumedInput = true;
-            } else {
-                Log.v(TAG, "In " + mId + " - TRY_AGAIN_LATER");
-            }
-            mCallbackReceived = false;
-        }
-
-        public boolean feedInput(final byte[] encFrame, final boolean inputEOS) throws Exception {
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    feedInputInternal(encFrame, inputEOS);
-                    return null;
-                }
-            } );
-            return mConsumedInput;
-        }
-
-        private void getOutputInternal() {
-            mOutput = new MediaEncoderOutput();
-            mOutput.inPresentationTimeUs = mInPresentationTimeUs;
-            mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
-            mOutput.outputGenerated = false;
-
-            // Get output from the encoder
-            int result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
-            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
-                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    mOutputBuffers = mCodec.getOutputBuffers();
-                } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    mFormat = mCodec.getOutputFormat();
-                    Log.d(TAG, "Format changed: " + mFormat.toString());
-                }
-                result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
-            }
-            if (result == MediaCodec.INFO_TRY_AGAIN_LATER) {
-                Log.v(TAG, "Out " + mId + " - TRY_AGAIN_LATER");
-            }
-
-            if (result >= 0) {
-                int outputBufIndex = result;
-                mOutput.buffer = new byte[mBufferInfo.size];
-                mOutputBuffers[outputBufIndex].position(mBufferInfo.offset);
-                mOutputBuffers[outputBufIndex].get(mOutput.buffer, 0, mBufferInfo.size);
-                mOutPresentationTimeUs = mBufferInfo.presentationTimeUs;
-
-                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
-                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
-                    logStr += " CONFIG. ";
-                }
-                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
-                    logStr += " KEY. ";
-                }
-                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    logStr += " EOS. ";
-                }
-                logStr += " Size: " + mBufferInfo.size;
-                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
-                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
-                Log.v(TAG, logStr);
-                if (mOutputFrameIndex == 0 &&
-                        ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
-                    throw new RuntimeException("First frame is not a sync frame.");
-                }
-
-                if (mBufferInfo.size > 0) {
-                    mOutputFrameIndex++;
-                    mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
-                }
-                mCodec.releaseOutputBuffer(outputBufIndex, false);
-
-                mOutput.flags = mBufferInfo.flags;
-                mOutput.outputGenerated = true;
-            }
-            mCallbackReceived = false;
-        }
-
-        public MediaEncoderOutput getOutput() throws Exception {
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    getOutputInternal();
-                    return null;
-                }
-            } );
-            return mOutput;
-        }
-
-        public void forceSyncFrame() throws Exception {
-            final Bundle syncFrame = new Bundle();
-            syncFrame.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    mCodec.setParameters(syncFrame);
-                    return null;
-                }
-            } );
-        }
-
-        public void updateBitrate(int bitrate) throws Exception {
-            final Bundle bitrateUpdate = new Bundle();
-            bitrateUpdate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bitrate);
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    mCodec.setParameters(bitrateUpdate);
-                    return null;
-                }
-            } );
-        }
-
-
-        public void waitForBufferEvent() throws Exception {
-            Log.v(TAG, "----Enc" + mId + " waiting for bufferEvent");
-            if (mAsync) {
-                synchronized (mCallbackEvent) {
-                    if (!mCallbackReceived) {
-                        mCallbackEvent.wait(1000); // wait 1 sec for a callback
-                        // throw an exception if callback was not received
-                        if (!mCallbackReceived) {
-                            throw new RuntimeException("MediaCodec callback was not received");
-                        }
-                    }
-                }
-            } else {
-                Thread.sleep(5);
-            }
-            Log.v(TAG, "----Waiting for bufferEvent done");
-        }
-
-
-        public void waitForCompletion(long timeoutMs) throws Exception {
-            synchronized (mCompletionEvent) {
-                long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
-
-                while (!mCompleted) {
-                    mCompletionEvent.wait(timeoutExpiredMs - System.currentTimeMillis());
-                    if (System.currentTimeMillis() >= timeoutExpiredMs) {
-                        throw new RuntimeException("encoding has timed out!");
-                    }
-                }
-            }
-        }
-
-        public void signalCompletion() {
-            synchronized (mCompletionEvent) {
-                mCompleted = true;
-                mCompletionEvent.notify();
-            }
-        }
-
-        public void deleteCodec() throws Exception {
-            runCallable( new Callable<Void>() {
-                @Override
-                public Void call() throws Exception {
-                    mCodec.stop();
-                    mCodec.release();
-                    return null;
-                }
-            } );
-            if (mAsync) {
-                requestStop(); // Stop looper thread
-            }
-        }
-    }
-
-    /**
-     * Vp8 encoding loop supporting encoding single streams with an option
-     * to run in a looper thread and use buffer ready notification callbacks.
-     *
-     * Output stream is described by encodingParams parameters.
-     *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param streamParams  Structure with encoder parameters
-     * @return              Returns array of encoded frames information for each frame.
-     */
-    protected ArrayList<MediaCodec.BufferInfo> encode(
-            EncoderOutputStreamParameters streamParams) throws Exception {
-
-        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
-        Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
-                streamParams.frameHeight);
-        int bitrate = streamParams.bitrateSet[0];
-
-        // Create minimal media format signifying desired output.
-        MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-        CodecProperties properties = getVpxCodecProperties(
-                true, format, streamParams.forceGoogleEncoder);
-        if (properties == null) {
-            return null;
-        }
-
-        // Open input/output
-        InputStream yuvStream = OpenFileOrResourceId(
-                streamParams.inputYuvFilename, streamParams.inputResourceId);
-        IvfWriter ivf = new IvfWriter(
-                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
-
-        // Create a media format signifying desired output.
-        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
-            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
-        }
-        if (streamParams.temporalLayers > 0) {
-            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
-        }
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
-        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
-                streamParams.frameRate;
-        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
-
-        // Create encoder
-        Log.d(TAG, "Creating encoder " + properties.codecName +
-                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
-                streamParams.frameWidth + " x " + streamParams.frameHeight +
-                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
-                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
-                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
-                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
-        Log.d(TAG, "  Format: " + format);
-        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
-        MediaEncoderAsync codec = new MediaEncoderAsync();
-        codec.createCodec(0, properties.codecName, format,
-                streamParams.timeoutDequeue, streamParams.runInLooperThread);
-
-        // encode loop
-        boolean sawInputEOS = false;  // no more data
-        boolean consumedInputEOS = false; // EOS flag is consumed dy encoder
-        boolean sawOutputEOS = false;
-        boolean inputConsumed = true;
-        int inputFrameIndex = 0;
-        int lastBitrate = bitrate;
-        int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
-        byte[] srcFrame = new byte[srcFrameSize];
-
-        while (!sawOutputEOS) {
-
-            // Read and feed input frame
-            if (!consumedInputEOS) {
-
-                // Read new input buffers - if previous input was consumed and no EOS
-                if (inputConsumed && !sawInputEOS) {
-                    int bytesRead = yuvStream.read(srcFrame);
-
-                    // Check EOS
-                    if (streamParams.frameCount > 0 && inputFrameIndex >= streamParams.frameCount) {
-                        sawInputEOS = true;
-                        Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
-                    }
-
-                    if (!sawInputEOS && bytesRead == -1) {
-                        if (streamParams.frameCount == 0) {
-                            sawInputEOS = true;
-                            Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
-                        } else {
-                            yuvStream.close();
-                            yuvStream = OpenFileOrResourceId(
-                                    streamParams.inputYuvFilename, streamParams.inputResourceId);
-                            bytesRead = yuvStream.read(srcFrame);
-                        }
-                    }
-
-                    // Force sync frame if syncForceFrameinterval is set.
-                    if (!sawInputEOS && inputFrameIndex > 0 &&
-                            streamParams.syncForceFrameInterval > 0 &&
-                            (inputFrameIndex % streamParams.syncForceFrameInterval) == 0) {
-                        Log.d(TAG, "---Requesting sync frame # " + inputFrameIndex);
-                        codec.forceSyncFrame();
-                    }
-
-                    // Dynamic bitrate change.
-                    if (!sawInputEOS && streamParams.bitrateSet.length > inputFrameIndex) {
-                        int newBitrate = streamParams.bitrateSet[inputFrameIndex];
-                        if (newBitrate != lastBitrate) {
-                            Log.d(TAG, "--- Requesting new bitrate " + newBitrate +
-                                    " for frame " + inputFrameIndex);
-                            codec.updateBitrate(newBitrate);
-                            lastBitrate = newBitrate;
-                        }
-                    }
-
-                    // Convert YUV420 to NV12 if necessary
-                    if (properties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
-                        srcFrame = YUV420ToNV(streamParams.frameWidth, streamParams.frameHeight,
-                                srcFrame);
-                    }
-                }
-
-                inputConsumed = codec.feedInput(srcFrame, sawInputEOS);
-                if (inputConsumed) {
-                    inputFrameIndex++;
-                    consumedInputEOS = sawInputEOS;
-                }
-            }
-
-            // Get output from the encoder
-            MediaEncoderOutput out = codec.getOutput();
-            if (out.outputGenerated) {
-                // Detect output EOS
-                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    Log.d(TAG, "----Output EOS ");
-                    sawOutputEOS = true;
-                }
-
-                if (out.buffer.length > 0) {
-                    // Save frame
-                    ivf.writeFrame(out.buffer, out.outPresentationTimeUs);
-
-                    // Update statistics - store presentation time delay in offset
-                    long presentationTimeUsDelta = out.inPresentationTimeUs -
-                            out.outPresentationTimeUs;
-                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
-                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
-                            out.outPresentationTimeUs, out.flags);
-                    bufferInfos.add(bufferInfoCopy);
-                }
-            }
-
-            // If codec is not ready to accept input/poutput - wait for buffer ready callback
-            if ((!inputConsumed || consumedInputEOS) && !out.outputGenerated) {
-                codec.waitForBufferEvent();
-            }
-        }
-
-        codec.deleteCodec();
-        ivf.close();
-        yuvStream.close();
-
-        return bufferInfos;
-    }
-
-    /**
-     * Vp8 encoding run in a looper thread and use buffer ready callbacks.
-     *
-     * Output stream is described by encodingParams parameters.
-     *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param streamParams  Structure with encoder parameters
-     * @return              Returns array of encoded frames information for each frame.
-     */
-    protected ArrayList<MediaCodec.BufferInfo> encodeAsync(
-            EncoderOutputStreamParameters streamParams) throws Exception {
-        if (!streamParams.runInLooperThread) {
-            throw new RuntimeException("encodeAsync should run with a looper thread!");
-        }
-
-        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
-        Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
-                streamParams.frameHeight);
-        int bitrate = streamParams.bitrateSet[0];
-
-        // Create minimal media format signifying desired output.
-        MediaFormat format = MediaFormat.createVideoFormat(
-                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-        CodecProperties properties = getVpxCodecProperties(
-                true, format, streamParams.forceGoogleEncoder);
-        if (properties == null) {
-            return null;
-        }
-
-        // Open input/output
-        IvfWriter ivf = new IvfWriter(
-                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
-
-        // Create a media format signifying desired output.
-        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
-            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
-        }
-        if (streamParams.temporalLayers > 0) {
-            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
-        }
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
-        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
-                streamParams.frameRate;
-        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
-
-        // Create encoder
-        Log.d(TAG, "Creating encoder " + properties.codecName +
-                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
-                streamParams.frameWidth + " x " + streamParams.frameHeight +
-                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
-                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
-                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
-                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
-        Log.d(TAG, "  Format: " + format);
-        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
-
-        MediaEncoderAsync codec = new MediaEncoderAsync();
-        MediaEncoderAsyncHelper helper = new MediaEncoderAsyncHelper(
-                streamParams, properties, bufferInfos, ivf);
-
-        codec.setAsyncHelper(helper);
-        codec.createCodec(0, properties.codecName, format,
-                streamParams.timeoutDequeue, streamParams.runInLooperThread);
-        codec.waitForCompletion(DEFAULT_ENCODE_TIMEOUT_MS);
-
-        codec.deleteCodec();
-        ivf.close();
-
-        return bufferInfos;
-    }
-
-    /**
-     * Vp8 encoding loop supporting encoding multiple streams at a time.
-     * Each output stream is described by encodingParams parameters allowing
-     * simultaneous encoding of various resolutions, bitrates with an option to
-     * control key frame and dynamic bitrate for each output stream indepandently.
-     *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param srcFrameWidth     Frame width of input yuv file
-     * @param srcFrameHeight    Frame height of input yuv file
-     * @param encodingParams    Encoder parameters
-     * @return                  Returns 2D array of encoded frames information for each stream and
-     *                          for each frame.
-     */
-    protected ArrayList<ArrayList<MediaCodec.BufferInfo>> encodeSimulcast(
-            int srcFrameWidth,
-            int srcFrameHeight,
-            ArrayList<EncoderOutputStreamParameters> encodingParams)  throws Exception {
-        int numEncoders = encodingParams.size();
-
-        // Create arrays of input/output, formats, bitrates etc
-        ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos =
-                new ArrayList<ArrayList<MediaCodec.BufferInfo>>(numEncoders);
-        InputStream yuvStream[] = new InputStream[numEncoders];
-        IvfWriter[] ivf = new IvfWriter[numEncoders];
-        FileOutputStream[] yuvScaled = new FileOutputStream[numEncoders];
-        MediaFormat[] format = new MediaFormat[numEncoders];
-        MediaEncoderAsync[] codec = new MediaEncoderAsync[numEncoders];
-        int[] inputFrameIndex = new int[numEncoders];
-        boolean[] sawInputEOS = new boolean[numEncoders];
-        boolean[] consumedInputEOS = new boolean[numEncoders];
-        boolean[] inputConsumed = new boolean[numEncoders];
-        boolean[] bufferConsumed = new boolean[numEncoders];
-        boolean[] sawOutputEOS = new boolean[numEncoders];
-        byte[][] srcFrame = new byte[numEncoders][];
-        boolean sawOutputEOSTotal = false;
-        boolean bufferConsumedTotal = false;
-        CodecProperties[] codecProperties = new CodecProperties[numEncoders];
-
-        numEncoders = 0;
-        for (EncoderOutputStreamParameters params : encodingParams) {
-            int i = numEncoders;
-            Log.d(TAG, "Source resolution: " + params.frameWidth + " x " +
-                    params.frameHeight);
-            int bitrate = params.bitrateSet[0];
-
-            // Create minimal media format signifying desired output.
-            format[i] = MediaFormat.createVideoFormat(VP8_MIME,
-                    params.frameWidth, params.frameHeight);
-            format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
-            CodecProperties properties = getVpxCodecProperties(
-                    true, format[i], params.forceGoogleEncoder);
-            if (properties == null) {
-                continue;
-            }
-
-            // Check if scaled image was created
-            int scale = params.frameWidth / srcFrameWidth;
-            if (!mScaledImages.contains(scale)) {
-                // resize image
-                cacheScaledImage(params.inputYuvFilename, params.inputResourceId,
-                        srcFrameWidth, srcFrameHeight,
-                        params.scaledYuvFilename, params.frameWidth, params.frameHeight);
-                mScaledImages.add(scale);
-            }
-
-            // Create buffer info storage
-            bufferInfos.add(new ArrayList<MediaCodec.BufferInfo>());
-
-            // Create YUV reader
-            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
-
-            // Create IVF writer
-            ivf[i] = new IvfWriter(params.outputIvfFilename, params.frameWidth, params.frameHeight);
-
-            // Frame buffer
-            int frameSize = params.frameWidth * params.frameHeight * 3 / 2;
-            srcFrame[i] = new byte[frameSize];
-
-            // Create a media format signifying desired output.
-            if (params.bitrateType == VIDEO_ControlRateConstant) {
-                format[i].setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
-            }
-            if (params.temporalLayers > 0) {
-                format[i].setInteger("ts-layers", params.temporalLayers); // 1 temporal layer
-            }
-            format[i].setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
-            format[i].setInteger(MediaFormat.KEY_FRAME_RATE, params.frameRate);
-            int syncFrameInterval = (params.syncFrameInterval + params.frameRate/2) /
-                    params.frameRate; // in sec
-            format[i].setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
-            // Create encoder
-            Log.d(TAG, "Creating encoder #" + i +" : " + properties.codecName +
-                    ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
-                    params.frameWidth + " x " + params.frameHeight +
-                    ". Bitrate: " + bitrate + " Bitrate type: " + params.bitrateType +
-                    ". Fps:" + params.frameRate + ". TS Layers: " + params.temporalLayers +
-                    ". Key frame:" + syncFrameInterval * params.frameRate +
-                    ". Force keyFrame: " + params.syncForceFrameInterval);
-            Log.d(TAG, "  Format: " + format[i]);
-            Log.d(TAG, "  Output ivf:" + params.outputIvfFilename);
-
-            // Create encoder
-            codec[i] = new MediaEncoderAsync();
-            codec[i].createCodec(i, properties.codecName, format[i],
-                    params.timeoutDequeue, params.runInLooperThread);
-            codecProperties[i] = new CodecProperties(properties.codecName, properties.colorFormat);
-
-            inputConsumed[i] = true;
-            ++numEncoders;
-        }
-        if (numEncoders == 0) {
-            Log.i(TAG, "no suitable encoders found for any of the streams");
-            return null;
-        }
-
-        while (!sawOutputEOSTotal) {
-            // Feed input buffer to all encoders
-            for (int i = 0; i < numEncoders; i++) {
-                bufferConsumed[i] = false;
-                if (consumedInputEOS[i]) {
-                    continue;
-                }
-
-                EncoderOutputStreamParameters params = encodingParams.get(i);
-                // Read new input buffers - if previous input was consumed and no EOS
-                if (inputConsumed[i] && !sawInputEOS[i]) {
-                    int bytesRead = yuvStream[i].read(srcFrame[i]);
-
-                    // Check EOS
-                    if (params.frameCount > 0 && inputFrameIndex[i] >= params.frameCount) {
-                        sawInputEOS[i] = true;
-                        Log.d(TAG, "---Enc" + i +
-                                ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
-                    }
-
-                    if (!sawInputEOS[i] && bytesRead == -1) {
-                        if (params.frameCount == 0) {
-                            sawInputEOS[i] = true;
-                            Log.d(TAG, "---Enc" + i +
-                                    ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
-                        } else {
-                            yuvStream[i].close();
-                            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
-                            bytesRead = yuvStream[i].read(srcFrame[i]);
-                        }
-                    }
-
-                    // Convert YUV420 to NV12 if necessary
-                    if (codecProperties[i].colorFormat !=
-                            CodecCapabilities.COLOR_FormatYUV420Planar) {
-                        srcFrame[i] =
-                            YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
-                    }
-                }
-
-                inputConsumed[i] = codec[i].feedInput(srcFrame[i], sawInputEOS[i]);
-                if (inputConsumed[i]) {
-                    inputFrameIndex[i]++;
-                    consumedInputEOS[i] = sawInputEOS[i];
-                    bufferConsumed[i] = true;
-                }
-
-            }
-
-            // Get output from all encoders
-            for (int i = 0; i < numEncoders; i++) {
-                if (sawOutputEOS[i]) {
-                    continue;
-                }
-
-                MediaEncoderOutput out = codec[i].getOutput();
-                if (out.outputGenerated) {
-                    bufferConsumed[i] = true;
-                    // Detect output EOS
-                    if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        Log.d(TAG, "----Enc" + i + ". Output EOS ");
-                        sawOutputEOS[i] = true;
-                    }
-
-                    if (out.buffer.length > 0) {
-                        // Save frame
-                        ivf[i].writeFrame(out.buffer, out.outPresentationTimeUs);
-
-                        // Update statistics - store presentation time delay in offset
-                        long presentationTimeUsDelta = out.inPresentationTimeUs -
-                                out.outPresentationTimeUs;
-                        MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
-                        bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
-                                out.outPresentationTimeUs, out.flags);
-                        bufferInfos.get(i).add(bufferInfoCopy);
-                    }
-                }
-            }
-
-            // If codec is not ready to accept input/output - wait for buffer ready callback
-            bufferConsumedTotal = false;
-            for (boolean bufferConsumedCurrent : bufferConsumed) {
-                bufferConsumedTotal |= bufferConsumedCurrent;
-            }
-            if (!bufferConsumedTotal) {
-                // Pick the encoder to wait for
-                for (int i = 0; i < numEncoders; i++) {
-                    if (!bufferConsumed[i] && !sawOutputEOS[i]) {
-                        codec[i].waitForBufferEvent();
-                        break;
-                    }
-                }
-            }
-
-            // Check if EOS happened for all encoders
-            sawOutputEOSTotal = true;
-            for (boolean sawOutputEOSStream : sawOutputEOS) {
-                sawOutputEOSTotal &= sawOutputEOSStream;
-            }
-        }
-
-        for (int i = 0; i < numEncoders; i++) {
-            codec[i].deleteCodec();
-            ivf[i].close();
-            yuvStream[i].close();
-            if (yuvScaled[i] != null) {
-                yuvScaled[i].close();
-            }
-        }
-
-        return bufferInfos;
-    }
-
-    /**
-     * Some encoding statistics.
-     */
-    protected class Vp8EncodingStatistics {
-        Vp8EncodingStatistics() {
-            mBitrates = new ArrayList<Integer>();
-            mFrames = new ArrayList<Integer>();
-            mKeyFrames = new ArrayList<Integer>();
-            mMinimumKeyFrameInterval = Integer.MAX_VALUE;
-        }
-
-        public ArrayList<Integer> mBitrates;// Bitrate values for each second of the encoded stream.
-        public ArrayList<Integer> mFrames; // Number of frames in each second of the encoded stream.
-        public int mAverageBitrate;         // Average stream bitrate.
-        public ArrayList<Integer> mKeyFrames;// Stores the position of key frames in a stream.
-        public int mAverageKeyFrameInterval; // Average key frame interval.
-        public int mMaximumKeyFrameInterval; // Maximum key frame interval.
-        public int mMinimumKeyFrameInterval; // Minimum key frame interval.
-    }
-
-    /**
-     * Calculates average bitrate and key frame interval for the encoded streams.
-     * Output mBitrates field will contain bitrate values for every second
-     * of the encoded stream.
-     * Average stream bitrate will be stored in mAverageBitrate field.
-     * mKeyFrames array will contain the position of key frames in the encoded stream and
-     * mKeyFrameInterval - average key frame interval.
-     */
-    protected Vp8EncodingStatistics computeEncodingStatistics(int encoderId,
-            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
-        Vp8EncodingStatistics statistics = new Vp8EncodingStatistics();
-
-        int totalSize = 0;
-        int frames = 0;
-        int framesPerSecond = 0;
-        int totalFrameSizePerSecond = 0;
-        int maxFrameSize = 0;
-        int currentSecond;
-        int nextSecond = 0;
-        String keyFrameList = "  IFrame List: ";
-        String bitrateList = "  Bitrate list: ";
-        String framesList = "  FPS list: ";
-
-
-        for (int j = 0; j < bufferInfos.size(); j++) {
-            MediaCodec.BufferInfo info = bufferInfos.get(j);
-            currentSecond = (int)(info.presentationTimeUs / 1000000);
-            boolean lastFrame = (j == bufferInfos.size() - 1);
-            if (!lastFrame) {
-                nextSecond = (int)(bufferInfos.get(j+1).presentationTimeUs / 1000000);
-            }
-
-            totalSize += info.size;
-            totalFrameSizePerSecond += info.size;
-            maxFrameSize = Math.max(maxFrameSize, info.size);
-            framesPerSecond++;
-            frames++;
-
-            // Update the bitrate statistics if the next frame will
-            // be for the next second
-            if (lastFrame || nextSecond > currentSecond) {
-                int currentBitrate = totalFrameSizePerSecond * 8;
-                bitrateList += (currentBitrate + " ");
-                framesList += (framesPerSecond + " ");
-                statistics.mBitrates.add(currentBitrate);
-                statistics.mFrames.add(framesPerSecond);
-                totalFrameSizePerSecond = 0;
-                framesPerSecond = 0;
-            }
-
-            // Update key frame statistics.
-            if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
-                statistics.mKeyFrames.add(j);
-                keyFrameList += (j + "  ");
-            }
-        }
-        int duration = (int)(bufferInfos.get(bufferInfos.size() - 1).presentationTimeUs / 1000);
-        duration = (duration + 500) / 1000;
-        statistics.mAverageBitrate = (int)(((long)totalSize * 8) / duration);
-        Log.d(TAG, "Statistics for encoder # " + encoderId);
-        // Calculate average key frame interval in frames.
-        int keyFrames = statistics.mKeyFrames.size();
-        if (keyFrames > 1) {
-            statistics.mAverageKeyFrameInterval =
-                    statistics.mKeyFrames.get(keyFrames - 1) - statistics.mKeyFrames.get(0);
-            statistics.mAverageKeyFrameInterval =
-                    Math.round((float)statistics.mAverageKeyFrameInterval / (keyFrames - 1));
-            for (int j = 1; j < keyFrames; j++) {
-                int keyFrameInterval =
-                        statistics.mKeyFrames.get(j) - statistics.mKeyFrames.get(j - 1);
-                statistics.mMaximumKeyFrameInterval =
-                        Math.max(statistics.mMaximumKeyFrameInterval, keyFrameInterval);
-                statistics.mMinimumKeyFrameInterval =
-                        Math.min(statistics.mMinimumKeyFrameInterval, keyFrameInterval);
-            }
-            Log.d(TAG, "  Key frame intervals: Max: " + statistics.mMaximumKeyFrameInterval +
-                    ". Min: " + statistics.mMinimumKeyFrameInterval +
-                    ". Avg: " + statistics.mAverageKeyFrameInterval);
-        }
-        Log.d(TAG, "  Frames: " + frames + ". Duration: " + duration +
-                ". Total size: " + totalSize + ". Key frames: " + keyFrames);
-        Log.d(TAG, keyFrameList);
-        Log.d(TAG, bitrateList);
-        Log.d(TAG, framesList);
-        Log.d(TAG, "  Bitrate average: " + statistics.mAverageBitrate);
-        Log.d(TAG, "  Maximum frame size: " + maxFrameSize);
-
-        return statistics;
-    }
-
-    protected Vp8EncodingStatistics computeEncodingStatistics(
-            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
-        return computeEncodingStatistics(0, bufferInfos);
-    }
-
-    protected ArrayList<Vp8EncodingStatistics> computeSimulcastEncodingStatistics(
-            ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos) {
-        int numCodecs = bufferInfos.size();
-        ArrayList<Vp8EncodingStatistics> statistics = new ArrayList<Vp8EncodingStatistics>();
-
-        for (int i = 0; i < numCodecs; i++) {
-            Vp8EncodingStatistics currentStatistics =
-                    computeEncodingStatistics(i, bufferInfos.get(i));
-            statistics.add(currentStatistics);
-        }
-        return statistics;
-    }
-
-    /**
-     * Calculates maximum latency for encoder/decoder based on buffer info array
-     * generated either by encoder or decoder.
-     */
-    protected int maxPresentationTimeDifference(ArrayList<MediaCodec.BufferInfo> bufferInfos) {
-        int maxValue = 0;
-        for (MediaCodec.BufferInfo bufferInfo : bufferInfos) {
-            maxValue = Math.max(maxValue,  bufferInfo.offset);
-        }
-        maxValue = (maxValue + 500) / 1000; // mcs -> ms
-        return maxValue;
-    }
-
-    /**
-     * Decoding PSNR statistics.
-     */
-    protected class Vp8DecodingStatistics {
-        Vp8DecodingStatistics() {
-            mMinimumPSNR = Integer.MAX_VALUE;
-        }
-        public double mAveragePSNR;
-        public double mMinimumPSNR;
-    }
-
-    /**
-     * Calculates PSNR value between two video frames.
-     */
-    private double computePSNR(byte[] data0, byte[] data1) {
-        long squareError = 0;
-        assertTrue(data0.length == data1.length);
-        int length = data0.length;
-        for (int i = 0 ; i < length; i++) {
-            int diff = ((int)data0[i] & 0xff) - ((int)data1[i] & 0xff);
-            squareError += diff * diff;
-        }
-        double meanSquareError = (double)squareError / length;
-        double psnr = 10 * Math.log10((double)255 * 255 / meanSquareError);
-        return psnr;
-    }
-
-    /**
-     * Calculates average and minimum PSNR values between
-     * set of reference and decoded video frames.
-     * Runs PSNR calculation for the full duration of the decoded data.
-     */
-    protected Vp8DecodingStatistics computeDecodingStatistics(
-            String referenceYuvFilename,
-            int referenceYuvRawId,
-            String decodedYuvFilename,
-            int width,
-            int height) throws Exception {
-        Vp8DecodingStatistics statistics = new Vp8DecodingStatistics();
-        InputStream referenceStream =
-                OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
-        InputStream decodedStream = new FileInputStream(decodedYuvFilename);
-
-        int ySize = width * height;
-        int uvSize = width * height / 4;
-        byte[] yRef = new byte[ySize];
-        byte[] yDec = new byte[ySize];
-        byte[] uvRef = new byte[uvSize];
-        byte[] uvDec = new byte[uvSize];
-
-        int frames = 0;
-        double averageYPSNR = 0;
-        double averageUPSNR = 0;
-        double averageVPSNR = 0;
-        double minimumYPSNR = Integer.MAX_VALUE;
-        double minimumUPSNR = Integer.MAX_VALUE;
-        double minimumVPSNR = Integer.MAX_VALUE;
-        int minimumPSNRFrameIndex = 0;
-
-        while (true) {
-            // Calculate Y PSNR.
-            int bytesReadRef = referenceStream.read(yRef);
-            int bytesReadDec = decodedStream.read(yDec);
-            if (bytesReadDec == -1) {
-                break;
-            }
-            if (bytesReadRef == -1) {
-                // Reference file wrapping up
-                referenceStream.close();
-                referenceStream =
-                        OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
-                bytesReadRef = referenceStream.read(yRef);
-            }
-            double curYPSNR = computePSNR(yRef, yDec);
-            averageYPSNR += curYPSNR;
-            minimumYPSNR = Math.min(minimumYPSNR, curYPSNR);
-            double curMinimumPSNR = curYPSNR;
-
-            // Calculate U PSNR.
-            bytesReadRef = referenceStream.read(uvRef);
-            bytesReadDec = decodedStream.read(uvDec);
-            double curUPSNR = computePSNR(uvRef, uvDec);
-            averageUPSNR += curUPSNR;
-            minimumUPSNR = Math.min(minimumUPSNR, curUPSNR);
-            curMinimumPSNR = Math.min(curMinimumPSNR, curUPSNR);
-
-            // Calculate V PSNR.
-            bytesReadRef = referenceStream.read(uvRef);
-            bytesReadDec = decodedStream.read(uvDec);
-            double curVPSNR = computePSNR(uvRef, uvDec);
-            averageVPSNR += curVPSNR;
-            minimumVPSNR = Math.min(minimumVPSNR, curVPSNR);
-            curMinimumPSNR = Math.min(curMinimumPSNR, curVPSNR);
-
-            // Frame index for minimum PSNR value - help to detect possible distortions
-            if (curMinimumPSNR < statistics.mMinimumPSNR) {
-                statistics.mMinimumPSNR = curMinimumPSNR;
-                minimumPSNRFrameIndex = frames;
-            }
-
-            String logStr = String.format(Locale.US, "PSNR #%d: Y: %.2f. U: %.2f. V: %.2f",
-                    frames, curYPSNR, curUPSNR, curVPSNR);
-            Log.v(TAG, logStr);
-
-            frames++;
-        }
-
-        averageYPSNR /= frames;
-        averageUPSNR /= frames;
-        averageVPSNR /= frames;
-        statistics.mAveragePSNR = (4 * averageYPSNR + averageUPSNR + averageVPSNR) / 6;
-
-        Log.d(TAG, "PSNR statistics for " + frames + " frames.");
-        String logStr = String.format(Locale.US,
-                "Average PSNR: Y: %.1f. U: %.1f. V: %.1f. Average: %.1f",
-                averageYPSNR, averageUPSNR, averageVPSNR, statistics.mAveragePSNR);
-        Log.d(TAG, logStr);
-        logStr = String.format(Locale.US,
-                "Minimum PSNR: Y: %.1f. U: %.1f. V: %.1f. Overall: %.1f at frame %d",
-                minimumYPSNR, minimumUPSNR, minimumVPSNR,
-                statistics.mMinimumPSNR, minimumPSNRFrameIndex);
-        Log.d(TAG, logStr);
-
-        referenceStream.close();
-        decodedStream.close();
-        return statistics;
-    }
-}
-
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
deleted file mode 100644
index 5552f6c..0000000
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.cts;
-
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.media.MediaFormat;
-import android.util.Log;
-import android.media.cts.R;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Verification test for vp8 encoder and decoder.
- *
- * A raw yv12 stream is encoded at various settings and written to an IVF
- * file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
- * calculate PSNR values for various bitrates.
- */
-public class Vp8EncoderTest extends Vp8CodecTestBase {
-
-    private static final String ENCODED_IVF_BASE = "football";
-    private static final String INPUT_YUV = null;
-    private static final String OUTPUT_YUV = SDCARD_DIR + File.separator +
-            ENCODED_IVF_BASE + "_out.yuv";
-
-    // YUV stream properties.
-    private static final int WIDTH = 320;
-    private static final int HEIGHT = 240;
-    private static final int FPS = 30;
-    // Default encoding bitrate.
-    private static final int BITRATE = 400000;
-    // Default encoding bitrate mode
-    private static final int BITRATE_MODE = VIDEO_ControlRateVariable;
-    // List of bitrates used in quality and basic bitrate tests.
-    private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
-    // Maximum allowed bitrate variation from the target value.
-    private static final double MAX_BITRATE_VARIATION = 0.2;
-    // Average PSNR values for reference Google VP8 codec for the above bitrates.
-    private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
-    // Minimum PSNR values for reference Google VP8 codec for the above bitrates.
-    private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
-    // Maximum allowed average PSNR difference of encoder comparing to reference Google encoder.
-    private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
-    // Maximum allowed minimum PSNR difference of encoder comparing to reference Google encoder.
-    private static final double MAX_MINIMUM_PSNR_DIFFERENCE = 4;
-    // Maximum allowed average PSNR difference of the encoder running in a looper thread with 0 ms
-    // buffer dequeue timeout comparing to the encoder running in a callee's thread with 100 ms
-    // buffer dequeue timeout.
-    private static final double MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE = 0.5;
-    // Maximum allowed minimum PSNR difference of the encoder running in a looper thread
-    // comparing to the encoder running in a callee's thread.
-    private static final double MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE = 2;
-    // Maximum allowed average key frame interval variation from the target value.
-    private static final int MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION = 1;
-    // Maximum allowed key frame interval variation from the target value.
-    private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
-
-    /**
-     * A basic test for VP8 encoder.
-     *
-     * Encodes 9 seconds of raw stream with default configuration options,
-     * and then decodes it to verify the bitstream.
-     * Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
-     */
-    public void testBasic() throws Exception {
-        int encodeSeconds = 9;
-        boolean skipped = true;
-
-        for (int targetBitrate : TEST_BITRATES_SET) {
-            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                    INPUT_YUV,
-                    ENCODED_IVF_BASE,
-                    encodeSeconds,
-                    WIDTH,
-                    HEIGHT,
-                    FPS,
-                    BITRATE_MODE,
-                    targetBitrate,
-                    true);
-            ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
-            if (bufInfo == null) {
-                continue;
-            }
-            skipped = false;
-
-            Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
-
-            assertEquals("Stream bitrate " + statistics.mAverageBitrate +
-                    " is different from the target " + targetBitrate,
-                    targetBitrate, statistics.mAverageBitrate,
-                    MAX_BITRATE_VARIATION * targetBitrate);
-
-            decode(params.outputIvfFilename, null, FPS, params.forceGoogleEncoder);
-        }
-
-        if (skipped) {
-            Log.i(TAG, "SKIPPING testBasic(): codec is not supported");
-        }
-    }
-
-    /**
-     * Asynchronous encoding test for VP8 encoder.
-     *
-     * Encodes 9 seconds of raw stream using synchronous and asynchronous calls.
-     * Checks the PSNR difference between the encoded and decoded output and reference yuv input
-     * does not change much for two different ways of the encoder call.
-     */
-    public void testAsyncEncoding() throws Exception {
-        int encodeSeconds = 9;
-
-        // First test the encoder running in a looper thread with buffer callbacks enabled.
-        boolean syncEncoding = false;
-        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                INPUT_YUV,
-                ENCODED_IVF_BASE,
-                encodeSeconds,
-                WIDTH,
-                HEIGHT,
-                FPS,
-                BITRATE_MODE,
-                BITRATE,
-                syncEncoding);
-        ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params);
-        if (bufInfos == null) {
-            Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
-            return;
-        }
-        computeEncodingStatistics(bufInfos);
-        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-        Vp8DecodingStatistics statisticsAsync = computeDecodingStatistics(
-                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
-                params.frameWidth, params.frameHeight);
-
-
-        // Test the encoder running in a callee's thread.
-        syncEncoding = true;
-        params = getDefaultEncodingParameters(
-                INPUT_YUV,
-                ENCODED_IVF_BASE,
-                encodeSeconds,
-                WIDTH,
-                HEIGHT,
-                FPS,
-                BITRATE_MODE,
-                BITRATE,
-                syncEncoding);
-        bufInfos = encode(params);
-        if (bufInfos == null) {
-            Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
-            return;
-        }
-        computeEncodingStatistics(bufInfos);
-        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-        Vp8DecodingStatistics statisticsSync = computeDecodingStatistics(
-                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
-                params.frameWidth, params.frameHeight);
-
-        // Check PSNR difference.
-        Log.d(TAG, "PSNR Average: Async: " + statisticsAsync.mAveragePSNR +
-                ". Sync: " + statisticsSync.mAveragePSNR);
-        Log.d(TAG, "PSNR Minimum: Async: " + statisticsAsync.mMinimumPSNR +
-                ". Sync: " + statisticsSync.mMinimumPSNR);
-        if ((Math.abs(statisticsAsync.mAveragePSNR - statisticsSync.mAveragePSNR) >
-            MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE) ||
-            (Math.abs(statisticsAsync.mMinimumPSNR - statisticsSync.mMinimumPSNR) >
-            MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE)) {
-            throw new RuntimeException("Difference between PSNRs for async and sync encoders");
-        }
-    }
-
-    /**
-     * Check if MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME is honored.
-     *
-     * Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
-     * The test does not verify the output stream.
-     */
-    public void testSyncFrame() throws Exception {
-        int encodeSeconds = 9;
-
-        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                INPUT_YUV,
-                ENCODED_IVF_BASE,
-                encodeSeconds,
-                WIDTH,
-                HEIGHT,
-                FPS,
-                BITRATE_MODE,
-                BITRATE,
-                true);
-        params.syncFrameInterval = encodeSeconds * FPS;
-        params.syncForceFrameInterval = FPS;
-        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
-        if (bufInfo == null) {
-            Log.i(TAG, "SKIPPING testSyncFrame(): no suitable encoder found");
-            return;
-        }
-
-        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
-
-        // First check if we got expected number of key frames.
-        int actualKeyFrames = statistics.mKeyFrames.size();
-        if (actualKeyFrames != encodeSeconds) {
-            throw new RuntimeException("Number of key frames " + actualKeyFrames +
-                    " is different from the expected " + encodeSeconds);
-        }
-
-        // Check key frame intervals:
-        // Average value should be within +/- 1 frame of the target value,
-        // maximum value should not be greater than target value + 3,
-        // and minimum value should not be less that target value - 3.
-        if (Math.abs(statistics.mAverageKeyFrameInterval - FPS) >
-            MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION ||
-            (statistics.mMaximumKeyFrameInterval - FPS > MAX_KEYFRAME_INTERVAL_VARIATION) ||
-            (FPS - statistics.mMinimumKeyFrameInterval > MAX_KEYFRAME_INTERVAL_VARIATION)) {
-            throw new RuntimeException(
-                    "Key frame intervals are different from the expected " + FPS);
-        }
-    }
-
-    /**
-     * Check if MediaCodec.PARAMETER_KEY_VIDEO_BITRATE is honored.
-     *
-     * Run the the encoder for 12 seconds. Request changes to the
-     * bitrate after 6 seconds and ensure the encoder responds.
-     */
-    public void testDynamicBitrateChange() throws Exception {
-        int encodeSeconds = 12;    // Encoding sequence duration in seconds.
-        int[] bitrateTargetValues = { 400000, 800000 };  // List of bitrates to test.
-
-        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                INPUT_YUV,
-                ENCODED_IVF_BASE,
-                encodeSeconds,
-                WIDTH,
-                HEIGHT,
-                FPS,
-                BITRATE_MODE,
-                bitrateTargetValues[0],
-                true);
-
-        // Number of seconds for each bitrate
-        int stepSeconds = encodeSeconds / bitrateTargetValues.length;
-        // Fill the bitrates values.
-        params.bitrateSet = new int[encodeSeconds * FPS];
-        for (int i = 0; i < bitrateTargetValues.length ; i++) {
-            Arrays.fill(params.bitrateSet,
-                    i * encodeSeconds * FPS / bitrateTargetValues.length,
-                    (i + 1) * encodeSeconds * FPS / bitrateTargetValues.length,
-                    bitrateTargetValues[i]);
-        }
-
-        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
-        if (bufInfo == null) {
-            Log.i(TAG, "SKIPPING testDynamicBitrateChange(): no suitable encoder found");
-            return;
-        }
-
-        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
-
-        // Calculate actual average bitrates  for every [stepSeconds] second.
-        int[] bitrateActualValues = new int[bitrateTargetValues.length];
-        for (int i = 0; i < bitrateTargetValues.length ; i++) {
-            bitrateActualValues[i] = 0;
-            for (int j = i * stepSeconds; j < (i + 1) * stepSeconds; j++) {
-                bitrateActualValues[i] += statistics.mBitrates.get(j);
-            }
-            bitrateActualValues[i] /= stepSeconds;
-            Log.d(TAG, "Actual bitrate for interval #" + i + " : " + bitrateActualValues[i] +
-                    ". Target: " + bitrateTargetValues[i]);
-
-            // Compare actual bitrate values to make sure at least same increasing/decreasing
-            // order as the target bitrate values.
-            for (int j = 0; j < i; j++) {
-                long differenceTarget = bitrateTargetValues[i] - bitrateTargetValues[j];
-                long differenceActual = bitrateActualValues[i] - bitrateActualValues[j];
-                if (differenceTarget * differenceActual < 0) {
-                    throw new RuntimeException("Target bitrates: " +
-                            bitrateTargetValues[j] + " , " + bitrateTargetValues[i] +
-                            ". Actual bitrates: "
-                            + bitrateActualValues[j] + " , " + bitrateActualValues[i]);
-                }
-            }
-        }
-    }
-
-     /**
-      * Check if encoder and decoder can run simultaneously on different threads.
-      *
-      * Encodes and decodes 9 seconds of raw stream sequentially in CBR mode,
-      * and then run parallel encoding and decoding of the same streams.
-      * Compares average bitrate and PSNR for sequential and parallel runs.
-      */
-     public void testParallelEncodingAndDecoding() throws Exception {
-         // check for encoder up front, as by the time we detect lack of
-         // encoder support, we may have already started decoding.
-         MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-         MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, WIDTH, HEIGHT);
-         if (mcl.findEncoderForFormat(format) == null) {
-             Log.i(TAG, "SKIPPING testParallelEncodingAndDecoding(): no suitable encoder found");
-             return;
-         }
-
-         int encodeSeconds = 9;
-         final int[] bitrate = new int[1];
-         final double[] psnr = new double[1];
-         final Exception[] exceptionEncoder = new Exception[1];
-         final Exception[] exceptionDecoder = new Exception[1];
-         final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                 INPUT_YUV,
-                 ENCODED_IVF_BASE,
-                 encodeSeconds,
-                 WIDTH,
-                 HEIGHT,
-                 FPS,
-                 VIDEO_ControlRateConstant,
-                 BITRATE,
-                 true);
-         final String inputIvfFilename = params.outputIvfFilename;
-
-         Runnable runEncoder = new Runnable() {
-             public void run() {
-                 try {
-                     ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
-                     Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
-                     bitrate[0] = statistics.mAverageBitrate;
-                 } catch (Exception e) {
-                     Log.e(TAG, "Encoder error: " + e.toString());
-                     exceptionEncoder[0] = e;
-                 }
-             }
-         };
-         Runnable runDecoder = new Runnable() {
-             public void run() {
-                 try {
-                     decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-                     Vp8DecodingStatistics statistics = computeDecodingStatistics(
-                            params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
-                            params.frameWidth, params.frameHeight);
-                     psnr[0] = statistics.mAveragePSNR;
-                 } catch (Exception e) {
-                     Log.e(TAG, "Decoder error: " + e.toString());
-                     exceptionDecoder[0] = e;
-                 }
-             }
-         };
-
-         // Sequential encoding and decoding.
-         runEncoder.run();
-         if (exceptionEncoder[0] != null) {
-             throw exceptionEncoder[0];
-         }
-         int referenceBitrate = bitrate[0];
-         runDecoder.run();
-         if (exceptionDecoder[0] != null) {
-             throw exceptionDecoder[0];
-         }
-         double referencePsnr = psnr[0];
-
-         // Parallel encoding and decoding.
-         params.outputIvfFilename = SDCARD_DIR + File.separator + ENCODED_IVF_BASE + "_copy.ivf";
-         Thread threadEncoder = new Thread(runEncoder);
-         Thread threadDecoder = new Thread(runDecoder);
-         threadEncoder.start();
-         threadDecoder.start();
-         threadEncoder.join();
-         threadDecoder.join();
-         if (exceptionEncoder[0] != null) {
-             throw exceptionEncoder[0];
-         }
-         if (exceptionDecoder[0] != null) {
-             throw exceptionDecoder[0];
-         }
-
-         // Compare bitrates and PSNRs for sequential and parallel cases.
-         Log.d(TAG, "Sequential bitrate: " + referenceBitrate + ". PSNR: " + referencePsnr);
-         Log.d(TAG, "Parallel bitrate: " + bitrate[0] + ". PSNR: " + psnr[0]);
-         assertEquals("Bitrate for sequenatial encoding" + referenceBitrate +
-                 " is different from parallel encoding " + bitrate[0],
-                 referenceBitrate, bitrate[0], MAX_BITRATE_VARIATION * referenceBitrate);
-         assertEquals("PSNR for sequenatial encoding" + referencePsnr +
-                 " is different from parallel encoding " + psnr[0],
-                 referencePsnr, psnr[0], MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE);
-     }
-
-
-    /**
-     * Check the encoder quality for various bitrates by calculating PSNR
-     *
-     * Run the the encoder for 9 seconds for each bitrate and calculate PSNR
-     * for each encoded stream.
-     * Video streams with higher bitrates should have higher PSNRs.
-     * Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
-     */
-    public void testEncoderQuality() throws Exception {
-        int encodeSeconds = 9;      // Encoding sequence duration in seconds for each bitrate.
-        double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
-        double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
-        boolean[] completed = new boolean[TEST_BITRATES_SET.length];
-        boolean skipped = true;
-
-        // Run platform specific encoder for different bitrates
-        // and compare PSNR of codec with PSNR of reference Google codec.
-        for (int i = 0; i < TEST_BITRATES_SET.length; i++) {
-            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
-                    INPUT_YUV,
-                    ENCODED_IVF_BASE,
-                    encodeSeconds,
-                    WIDTH,
-                    HEIGHT,
-                    FPS,
-                    BITRATE_MODE,
-                    TEST_BITRATES_SET[i],
-                    true);
-            if (encode(params) == null) {
-                // parameters not supported, try other bitrates
-                completed[i] = false;
-                continue;
-            }
-            completed[i] = true;
-            skipped = false;
-
-            decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
-            Vp8DecodingStatistics statistics = computeDecodingStatistics(
-                    params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
-                    params.frameWidth, params.frameHeight);
-            psnrPlatformCodecAverage[i] = statistics.mAveragePSNR;
-            psnrPlatformCodecMin[i] = statistics.mMinimumPSNR;
-        }
-
-        if (skipped) {
-            Log.i(TAG, "SKIPPING testEncoderQuality(): no bitrates supported");
-            return;
-        }
-
-        // First do a sanity check - higher bitrates should results in higher PSNR.
-        for (int i = 1; i < TEST_BITRATES_SET.length ; i++) {
-            if (!completed[i]) {
-                continue;
-            }
-            for (int j = 0; j < i; j++) {
-                if (!completed[j]) {
-                    continue;
-                }
-                double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
-                double differencePSNR = psnrPlatformCodecAverage[i] - psnrPlatformCodecAverage[j];
-                if (differenceBitrate * differencePSNR < 0) {
-                    throw new RuntimeException("Target bitrates: " +
-                            TEST_BITRATES_SET[j] + ", " + TEST_BITRATES_SET[i] +
-                            ". Actual PSNRs: "
-                            + psnrPlatformCodecAverage[j] + ", " + psnrPlatformCodecAverage[i]);
-                }
-            }
-        }
-
-        // Then compare average and minimum PSNR of platform codec with reference Google codec -
-        // average PSNR for platform codec should be no more than 2 dB less than reference PSNR
-        // and minumum PSNR - no more than 4 dB less than reference minimum PSNR.
-        // These PSNR difference numbers are arbitrary for now, will need further estimation
-        // when more devices with HW VP8 codec will appear.
-        for (int i = 0; i < TEST_BITRATES_SET.length ; i++) {
-            if (!completed[i]) {
-                continue;
-            }
-
-            Log.d(TAG, "Bitrate " + TEST_BITRATES_SET[i]);
-            Log.d(TAG, "Reference: Average: " + REFERENCE_AVERAGE_PSNR[i] + ". Minimum: " +
-                    REFERENCE_MINIMUM_PSNR[i]);
-            Log.d(TAG, "Platform:  Average: " + psnrPlatformCodecAverage[i] + ". Minimum: " +
-                    psnrPlatformCodecMin[i]);
-            if (psnrPlatformCodecAverage[i] < REFERENCE_AVERAGE_PSNR[i] -
-                    MAX_AVERAGE_PSNR_DIFFERENCE) {
-                throw new RuntimeException("Low average PSNR " + psnrPlatformCodecAverage[i] +
-                        " comparing to reference PSNR " + REFERENCE_AVERAGE_PSNR[i] +
-                        " for bitrate " + TEST_BITRATES_SET[i]);
-            }
-            if (psnrPlatformCodecMin[i] < REFERENCE_MINIMUM_PSNR[i] -
-                    MAX_MINIMUM_PSNR_DIFFERENCE) {
-                throw new RuntimeException("Low minimum PSNR " + psnrPlatformCodecMin[i] +
-                        " comparing to reference PSNR " + REFERENCE_MINIMUM_PSNR[i] +
-                        " for bitrate " + TEST_BITRATES_SET[i]);
-            }
-        }
-    }
-}
-
diff --git a/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
new file mode 100644
index 0000000..ea72225
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
@@ -0,0 +1,2016 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Looper;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.media.cts.R;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Locale;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Verification test for vpx encoder and decoder.
+ *
+ * A raw yv12 stream is encoded at various settings and written to an IVF
+ * file. Encoded stream bitrate and key frame interval are checked against target values.
+ * The stream is later decoded by the decoder to verify frames are decodable and to
+ * calculate PSNR values for various bitrates.
+ */
+public class VpxCodecTestBase extends AndroidTestCase {
+
+    protected static final String TAG = "VPxCodecTestBase";
+    protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
+    protected static final String VP9_MIME = MediaFormat.MIMETYPE_VIDEO_VP9;
+    private static final String GOOGLE_CODEC_PREFIX = "omx.google.";
+    protected static final String SDCARD_DIR =
+            Environment.getExternalStorageDirectory().getAbsolutePath();
+
+    // Default timeout for MediaCodec buffer dequeue - 200 ms.
+    protected static final long DEFAULT_DEQUEUE_TIMEOUT_US = 200000;
+    // Default timeout for MediaEncoderAsync - 30 sec.
+    protected static final long DEFAULT_ENCODE_TIMEOUT_MS = 30000;
+    // Default sync frame interval in frames (zero means allow the encoder to auto-select
+    // key frame interval).
+    private static final int SYNC_FRAME_INTERVAL = 0;
+    // Video bitrate type - should be set to OMX_Video_ControlRateConstant from OMX_Video.h
+    protected static final int VIDEO_ControlRateVariable = 1;
+    protected static final int VIDEO_ControlRateConstant = 2;
+    // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
+    // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
+    private static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04;
+    // Allowable color formats supported by codec - in order of preference.
+    private static final int[] mSupportedColorList = {
+            CodecCapabilities.COLOR_FormatYUV420Planar,
+            CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
+            CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
+            COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m
+    };
+    // Scaled image cache list - contains scale factors, for which up-scaled frames
+    // were calculated and were written to yuv file.
+    ArrayList<Integer> mScaledImages = new ArrayList<Integer>();
+
+    private Resources mResources;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mResources = mContext.getResources();
+    }
+
+    /**
+     *  VPx codec properties generated by getVpxCodecProperties() function.
+     */
+    private class CodecProperties {
+        CodecProperties(String codecName, int colorFormat) {
+            this.codecName = codecName;
+            this.colorFormat = colorFormat;
+        }
+        public boolean  isGoogleCodec() {
+            return codecName.toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
+        }
+
+        public final String codecName; // OpenMax component name for VPx codec.
+        public final int colorFormat;  // Color format supported by codec.
+    }
+
+    /**
+     * Function to find VPx codec.
+     *
+     * Iterates through the list of available codecs and tries to find
+     * VPX codec, which can support either YUV420 planar or NV12 color formats.
+     * If forceGoogleCodec parameter set to true the function always returns
+     * Google VPX codec.
+     * If forceGoogleCodec parameter set to false the functions looks for platform
+     * specific VPX codec first. If no platform specific codec exist, falls back to
+     * Google VPX codec.
+     *
+     * @param isEncoder     Flag if encoder is requested.
+     * @param forceGoogleCodec  Forces to use Google codec.
+     */
+    private CodecProperties getVpxCodecProperties(
+            boolean isEncoder,
+            MediaFormat format,
+            boolean forceGoogleCodec) throws Exception {
+        CodecProperties codecProperties = null;
+        String mime = format.getString(MediaFormat.KEY_MIME);
+
+        // Loop through the list of omx components in case platform specific codec
+        // is requested.
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+            if (isEncoder != codecInfo.isEncoder()) {
+                continue;
+            }
+            Log.v(TAG, codecInfo.getName());
+            // TODO: remove dependence of Google from the test
+            // Check if this is Google codec - we should ignore it.
+            boolean isGoogleCodec =
+                codecInfo.getName().toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
+            if (!isGoogleCodec && forceGoogleCodec) {
+                continue;
+            }
+
+            for (String type : codecInfo.getSupportedTypes()) {
+                if (!type.equalsIgnoreCase(mime)) {
+                    continue;
+                }
+                CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(type);
+                if (!capabilities.isFormatSupported(format)) {
+                    continue;
+                }
+
+                // Get candidate codec properties.
+                Log.v(TAG, "Found candidate codec " + codecInfo.getName());
+                for (int colorFormat: capabilities.colorFormats) {
+                    Log.v(TAG, "   Color: 0x" + Integer.toHexString(colorFormat));
+                }
+
+                // Check supported color formats.
+                for (int supportedColorFormat : mSupportedColorList) {
+                    for (int codecColorFormat : capabilities.colorFormats) {
+                        if (codecColorFormat == supportedColorFormat) {
+                            codecProperties = new CodecProperties(codecInfo.getName(),
+                                    codecColorFormat);
+                            Log.v(TAG, "Found target codec " + codecProperties.codecName +
+                                    ". Color: 0x" + Integer.toHexString(codecColorFormat));
+                            // return first HW codec found
+                            if (!isGoogleCodec) {
+                                return codecProperties;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (codecProperties == null) {
+            Log.i(TAG, "no suitable " + (forceGoogleCodec ? "google " : "")
+                    + (isEncoder ? "encoder " : "decoder ") + "found for " + format);
+        }
+        return codecProperties;
+    }
+
+    /**
+     * Parameters for encoded video stream.
+     */
+    protected class EncoderOutputStreamParameters {
+        // Name of raw YUV420 input file. When the value of this parameter
+        // is set to null input file descriptor from inputResourceId parameter
+        // is used instead.
+        public String inputYuvFilename;
+        // Name of scaled YUV420 input file.
+        public String scaledYuvFilename;
+        // File descriptor for the raw input file (YUV420). Used only if
+        // inputYuvFilename parameter is null.
+        int inputResourceId;
+        // Name of the IVF file to write encoded bitsream
+        public String outputIvfFilename;
+        // Mime Type of the Encoded content.
+        public String codecMimeType;
+        // Force to use Google VPx encoder.
+        boolean forceGoogleEncoder;
+        // Number of frames to encode.
+        int frameCount;
+        // Frame rate of input file in frames per second.
+        int frameRate;
+        // Encoded frame width.
+        public int frameWidth;
+        // Encoded frame height.
+        public int frameHeight;
+        // Encoding bitrate array in bits/second for every frame. If array length
+        // is shorter than the total number of frames, the last value is re-used for
+        // all remaining frames. For constant bitrate encoding single element
+        // array can be used with first element set to target bitrate value.
+        public int[] bitrateSet;
+        // Encoding bitrate type - VBR or CBR
+        public int bitrateType;
+        // Number of temporal layers
+        public int temporalLayers;
+        // Desired key frame interval - codec is asked to generate key frames
+        // at a period defined by this parameter.
+        public int syncFrameInterval;
+        // Optional parameter - forced key frame interval. Used to
+        // explicitly request the codec to generate key frames using
+        // MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME parameter.
+        public int syncForceFrameInterval;
+        // Buffer timeout
+        long timeoutDequeue;
+        // Flag if encoder should run in Looper thread.
+        boolean runInLooperThread;
+    }
+
+    /**
+     * Generates an array of default parameters for encoder output stream based on
+     * upscaling value.
+     */
+    protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
+            String inputYuvName,
+            String outputIvfBaseName,
+            String codecMimeType,
+            int encodeSeconds,
+            int[] resolutionScales,
+            int frameWidth,
+            int frameHeight,
+            int frameRate,
+            int bitrateMode,
+            int[] bitrates,
+            boolean syncEncoding) {
+        assertTrue(resolutionScales.length == bitrates.length);
+        int numCodecs = resolutionScales.length;
+        ArrayList<EncoderOutputStreamParameters> outputParameters =
+                new ArrayList<EncoderOutputStreamParameters>(numCodecs);
+        for (int i = 0; i < numCodecs; i++) {
+            EncoderOutputStreamParameters params = new EncoderOutputStreamParameters();
+            if (inputYuvName != null) {
+                params.inputYuvFilename = SDCARD_DIR + File.separator + inputYuvName;
+            } else {
+                params.inputYuvFilename = null;
+            }
+            params.scaledYuvFilename = SDCARD_DIR + File.separator +
+                    outputIvfBaseName + resolutionScales[i]+ ".yuv";
+            params.inputResourceId = R.raw.football_qvga;
+            params.codecMimeType = codecMimeType;
+            String codecSuffix = VP8_MIME.equals(codecMimeType) ? "vp8" : "vp9";
+            params.outputIvfFilename = SDCARD_DIR + File.separator +
+                    outputIvfBaseName + resolutionScales[i] + "_" + codecSuffix + ".ivf";
+            params.forceGoogleEncoder = false;
+            params.frameCount = encodeSeconds * frameRate;
+            params.frameRate = frameRate;
+            params.frameWidth = Math.min(frameWidth * resolutionScales[i], 1280);
+            params.frameHeight = Math.min(frameHeight * resolutionScales[i], 720);
+            params.bitrateSet = new int[1];
+            params.bitrateSet[0] = bitrates[i];
+            params.bitrateType = bitrateMode;
+            params.temporalLayers = 0;
+            params.syncFrameInterval = SYNC_FRAME_INTERVAL;
+            params.syncForceFrameInterval = 0;
+            if (syncEncoding) {
+                params.timeoutDequeue = DEFAULT_DEQUEUE_TIMEOUT_US;
+                params.runInLooperThread = false;
+            } else {
+                params.timeoutDequeue = 0;
+                params.runInLooperThread = true;
+            }
+            outputParameters.add(params);
+        }
+        return outputParameters;
+    }
+
+    protected EncoderOutputStreamParameters getDefaultEncodingParameters(
+            String inputYuvName,
+            String outputIvfBaseName,
+            String codecMimeType,
+            int encodeSeconds,
+            int frameWidth,
+            int frameHeight,
+            int frameRate,
+            int bitrateMode,
+            int bitrate,
+            boolean syncEncoding) {
+        int[] scaleValues = { 1 };
+        int[] bitrates = { bitrate };
+        return getDefaultEncodingParameterList(
+                inputYuvName,
+                outputIvfBaseName,
+                codecMimeType,
+                encodeSeconds,
+                scaleValues,
+                frameWidth,
+                frameHeight,
+                frameRate,
+                bitrateMode,
+                bitrates,
+                syncEncoding).get(0);
+    }
+
+    /**
+     * Converts (interleaves) YUV420 planar to NV12.
+     * Assumes packed, macroblock-aligned frame with no cropping
+     * (visible/coded row length == stride).
+     */
+    private static byte[] YUV420ToNV(int width, int height, byte[] yuv) {
+        byte[] nv = new byte[yuv.length];
+        // Y plane we just copy.
+        System.arraycopy(yuv, 0, nv, 0, width * height);
+
+        // U & V plane we interleave.
+        int u_offset = width * height;
+        int v_offset = u_offset + u_offset / 4;
+        int nv_offset = width * height;
+        for (int i = 0; i < width * height / 4; i++) {
+            nv[nv_offset++] = yuv[u_offset++];
+            nv[nv_offset++] = yuv[v_offset++];
+        }
+        return nv;
+    }
+
+    /**
+     * Converts (de-interleaves) NV12 to YUV420 planar.
+     * Stride may be greater than width, slice height may be greater than height.
+     */
+    private static byte[] NV12ToYUV420(int width, int height,
+            int stride, int sliceHeight, byte[] nv12) {
+        byte[] yuv = new byte[width * height * 3 / 2];
+
+        // Y plane we just copy.
+        for (int i = 0; i < height; i++) {
+            System.arraycopy(nv12, i * stride, yuv, i * width, width);
+        }
+
+        // U & V plane - de-interleave.
+        int u_offset = width * height;
+        int v_offset = u_offset + u_offset / 4;
+        int nv_offset;
+        for (int i = 0; i < height / 2; i++) {
+            nv_offset = stride * (sliceHeight + i);
+            for (int j = 0; j < width / 2; j++) {
+                yuv[u_offset++] = nv12[nv_offset++];
+                yuv[v_offset++] = nv12[nv_offset++];
+            }
+        }
+        return yuv;
+    }
+
+    /**
+     * Packs YUV420 frame by moving it to a smaller size buffer with stride and slice
+     * height equal to the original frame width and height.
+     */
+    private static byte[] PackYUV420(int width, int height,
+            int stride, int sliceHeight, byte[] src) {
+        byte[] dst = new byte[width * height * 3 / 2];
+        // Y copy.
+        for (int i = 0; i < height; i++) {
+            System.arraycopy(src, i * stride, dst, i * width, width);
+        }
+        // U and V copy.
+        int u_src_offset = stride * sliceHeight;
+        int v_src_offset = u_src_offset + u_src_offset / 4;
+        int u_dst_offset = width * height;
+        int v_dst_offset = u_dst_offset + u_dst_offset / 4;
+        for (int i = 0; i < height / 2; i++) {
+            System.arraycopy(src, u_src_offset + i * (stride / 2),
+                    dst, u_dst_offset + i * (width / 2), width / 2);
+            System.arraycopy(src, v_src_offset + i * (stride / 2),
+                    dst, v_dst_offset + i * (width / 2), width / 2);
+        }
+        return dst;
+    }
+
+
+    private static void imageUpscale1To2(byte[] src, int srcByteOffset, int srcStride,
+            byte[] dst, int dstByteOffset, int dstWidth, int dstHeight) {
+        for (int i = 0; i < dstHeight/2 - 1; i++) {
+            int dstOffset0 = 2 * i * dstWidth + dstByteOffset;
+            int dstOffset1 = dstOffset0 + dstWidth;
+            int srcOffset0 = i * srcStride + srcByteOffset;
+            int srcOffset1 = srcOffset0 + srcStride;
+            int pixel00 = (int)src[srcOffset0++] & 0xff;
+            int pixel10 = (int)src[srcOffset1++] & 0xff;
+            for (int j = 0; j < dstWidth/2 - 1; j++) {
+                int pixel01 = (int)src[srcOffset0++] & 0xff;
+                int pixel11 = (int)src[srcOffset1++] & 0xff;
+                dst[dstOffset0++] = (byte)pixel00;
+                dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
+                dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+                dst[dstOffset1++] = (byte)((pixel00 + pixel01 + pixel10 + pixel11 + 2) / 4);
+                pixel00 = pixel01;
+                pixel10 = pixel11;
+            }
+            // last column
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+        }
+
+        // last row
+        int dstOffset0 = (dstHeight - 2) * dstWidth + dstByteOffset;
+        int dstOffset1 = dstOffset0 + dstWidth;
+        int srcOffset0 = (dstHeight/2 - 1) * srcStride + srcByteOffset;
+        int pixel00 = (int)src[srcOffset0++] & 0xff;
+        for (int j = 0; j < dstWidth/2 - 1; j++) {
+            int pixel01 = (int)src[srcOffset0++] & 0xff;
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
+            dst[dstOffset1++] = (byte)pixel00;
+            dst[dstOffset1++] = (byte)((pixel00 + pixel01 + 1) / 2);
+            pixel00 = pixel01;
+        }
+        // the very last pixel - bottom right
+        dst[dstOffset0++] = (byte)pixel00;
+        dst[dstOffset0++] = (byte)pixel00;
+        dst[dstOffset1++] = (byte)pixel00;
+        dst[dstOffset1++] = (byte)pixel00;
+    }
+
+    /**
+    * Up-scale image.
+    * Scale factor is defined by source and destination width ratio.
+    * Only 1:2 and 1:4 up-scaling is supported for now.
+    * For 640x480 -> 1280x720 conversion only top 640x360 part of the original
+    * image is scaled.
+    */
+    private static byte[] imageScale(byte[] src, int srcWidth, int srcHeight,
+            int dstWidth, int dstHeight) throws Exception {
+        int srcYSize = srcWidth * srcHeight;
+        int dstYSize = dstWidth * dstHeight;
+        byte[] dst = null;
+        if (dstWidth == 2 * srcWidth && dstHeight <= 2 * srcHeight) {
+            // 1:2 upscale
+            dst = new byte[dstWidth * dstHeight * 3 / 2];
+            imageUpscale1To2(src, 0, srcWidth,
+                    dst, 0, dstWidth, dstHeight);                                 // Y
+            imageUpscale1To2(src, srcYSize, srcWidth / 2,
+                    dst, dstYSize, dstWidth / 2, dstHeight / 2);                  // U
+            imageUpscale1To2(src, srcYSize * 5 / 4, srcWidth / 2,
+                    dst, dstYSize * 5 / 4, dstWidth / 2, dstHeight / 2);          // V
+        } else if (dstWidth == 4 * srcWidth && dstHeight <= 4 * srcHeight) {
+            // 1:4 upscale - in two steps
+            int midWidth = 2 * srcWidth;
+            int midHeight = 2 * srcHeight;
+            byte[] midBuffer = imageScale(src, srcWidth, srcHeight, midWidth, midHeight);
+            dst = imageScale(midBuffer, midWidth, midHeight, dstWidth, dstHeight);
+
+        } else {
+            throw new RuntimeException("Can not find proper scaling function");
+        }
+
+        return dst;
+    }
+
+    private void cacheScaledImage(
+            String srcYuvFilename, int srcResourceId, int srcFrameWidth, int srcFrameHeight,
+            String dstYuvFilename, int dstFrameWidth, int dstFrameHeight) throws Exception {
+        InputStream srcStream = OpenFileOrResourceId(srcYuvFilename, srcResourceId);
+        FileOutputStream dstFile = new FileOutputStream(dstYuvFilename, false);
+        int srcFrameSize = srcFrameWidth * srcFrameHeight * 3 / 2;
+        byte[] srcFrame = new byte[srcFrameSize];
+        byte[] dstFrame = null;
+        Log.d(TAG, "Scale to " + dstFrameWidth + " x " + dstFrameHeight + ". -> " + dstYuvFilename);
+        while (true) {
+            int bytesRead = srcStream.read(srcFrame);
+            if (bytesRead != srcFrame.length) {
+                break;
+            }
+            if (dstFrameWidth == srcFrameWidth && dstFrameHeight == srcFrameHeight) {
+                dstFrame = srcFrame;
+            } else {
+                dstFrame = imageScale(srcFrame, srcFrameWidth, srcFrameHeight,
+                        dstFrameWidth, dstFrameHeight);
+            }
+            dstFile.write(dstFrame);
+        }
+        srcStream.close();
+        dstFile.close();
+    }
+
+
+    /**
+     * A basic check if an encoded stream is decodable.
+     *
+     * The most basic confirmation we can get about a frame
+     * being properly encoded is trying to decode it.
+     * (Especially in realtime mode encode output is non-
+     * deterministic, therefore a more thorough check like
+     * md5 sum comparison wouldn't work.)
+     *
+     * Indeed, MediaCodec will raise an IllegalStateException
+     * whenever vpx decoder fails to decode a frame, and
+     * this test uses that fact to verify the bitstream.
+     *
+     * @param inputIvfFilename  The name of the IVF file containing encoded bitsream.
+     * @param outputYuvFilename The name of the output YUV file (optional).
+     * @param frameRate         Frame rate of input file in frames per second
+     * @param forceGoogleDecoder    Force to use Google VPx decoder.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> decode(
+            String inputIvfFilename,
+            String outputYuvFilename,
+            String codecMimeType,
+            int frameRate,
+            boolean forceGoogleDecoder) throws Exception {
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+
+        // Open input/output.
+        IvfReader ivf = new IvfReader(inputIvfFilename);
+        int frameWidth = ivf.getWidth();
+        int frameHeight = ivf.getHeight();
+        int frameCount = ivf.getFrameCount();
+        int frameStride = frameWidth;
+        int frameSliceHeight = frameHeight;
+        assertTrue(frameWidth > 0);
+        assertTrue(frameHeight > 0);
+        assertTrue(frameCount > 0);
+
+        // Create decoder.
+        MediaFormat format = MediaFormat.createVideoFormat(
+                codecMimeType, ivf.getWidth(), ivf.getHeight());
+        CodecProperties properties = getVpxCodecProperties(
+                false /* encoder */, format, forceGoogleDecoder);
+        if (properties == null) {
+            ivf.close();
+            return null;
+        }
+        int frameColorFormat = properties.colorFormat;
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+
+        FileOutputStream yuv = null;
+        if (outputYuvFilename != null) {
+            yuv = new FileOutputStream(outputYuvFilename, false);
+        }
+
+        Log.d(TAG, "Creating decoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(frameColorFormat) +
+                ". " + frameWidth + " x " + frameHeight);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  In: " + inputIvfFilename + ". Out:" + outputYuvFilename);
+        MediaCodec decoder = MediaCodec.createByCodecName(properties.codecName);
+        decoder.configure(format,
+                          null,  // surface
+                          null,  // crypto
+                          0);    // flags
+        decoder.start();
+
+        ByteBuffer[] inputBuffers = decoder.getInputBuffers();
+        ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
+        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+
+        // decode loop
+        int inputFrameIndex = 0;
+        int outputFrameIndex = 0;
+        long inPresentationTimeUs = 0;
+        long outPresentationTimeUs = 0;
+        boolean sawOutputEOS = false;
+        boolean sawInputEOS = false;
+
+        while (!sawOutputEOS) {
+            if (!sawInputEOS) {
+                int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_DEQUEUE_TIMEOUT_US);
+                if (inputBufIndex >= 0) {
+                    byte[] frame = ivf.readFrame(inputFrameIndex);
+
+                    if (inputFrameIndex == frameCount - 1) {
+                        Log.d(TAG, "  Input EOS for frame # " + inputFrameIndex);
+                        sawInputEOS = true;
+                    }
+
+                    inputBuffers[inputBufIndex].clear();
+                    inputBuffers[inputBufIndex].put(frame);
+                    inputBuffers[inputBufIndex].rewind();
+                    inPresentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
+
+                    decoder.queueInputBuffer(
+                            inputBufIndex,
+                            0,  // offset
+                            frame.length,
+                            inPresentationTimeUs,
+                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+
+                    inputFrameIndex++;
+                }
+            }
+
+            int result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
+            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
+                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                    outputBuffers = decoder.getOutputBuffers();
+                } else  if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                    // Process format change
+                    format = decoder.getOutputFormat();
+                    frameWidth = format.getInteger(MediaFormat.KEY_WIDTH);
+                    frameHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+                    frameColorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+                    Log.d(TAG, "Decoder output format change. Color: 0x" +
+                            Integer.toHexString(frameColorFormat));
+                    Log.d(TAG, "Format: " + format.toString());
+
+                    // Parse frame and slice height from undocumented values
+                    if (format.containsKey("stride")) {
+                        frameStride = format.getInteger("stride");
+                    } else {
+                        frameStride = frameWidth;
+                    }
+                    if (format.containsKey("slice-height")) {
+                        frameSliceHeight = format.getInteger("slice-height");
+                    } else {
+                        frameSliceHeight = frameHeight;
+                    }
+                    Log.d(TAG, "Frame stride and slice height: " + frameStride +
+                            " x " + frameSliceHeight);
+                    frameStride = Math.max(frameWidth, frameStride);
+                    frameSliceHeight = Math.max(frameHeight, frameSliceHeight);
+                }
+                result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
+            }
+            if (result >= 0) {
+                int outputBufIndex = result;
+                outPresentationTimeUs = bufferInfo.presentationTimeUs;
+                Log.v(TAG, "Writing buffer # " + outputFrameIndex +
+                        ". Size: " + bufferInfo.size +
+                        ". InTime: " + (inPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (outPresentationTimeUs + 500)/1000);
+                if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    sawOutputEOS = true;
+                    Log.d(TAG, "   Output EOS for frame # " + outputFrameIndex);
+                }
+
+                if (bufferInfo.size > 0) {
+                    // Save decoder output to yuv file.
+                    if (yuv != null) {
+                        byte[] frame = new byte[bufferInfo.size];
+                        outputBuffers[outputBufIndex].position(bufferInfo.offset);
+                        outputBuffers[outputBufIndex].get(frame, 0, bufferInfo.size);
+                        // Convert NV12 to YUV420 if necessary.
+                        if (frameColorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                            frame = NV12ToYUV420(frameWidth, frameHeight,
+                                    frameStride, frameSliceHeight, frame);
+                        }
+                        int writeLength = Math.min(frameWidth * frameHeight * 3 / 2, frame.length);
+                        // Pack frame if necessary.
+                        if (writeLength < frame.length &&
+                                (frameStride > frameWidth || frameSliceHeight > frameHeight)) {
+                            frame = PackYUV420(frameWidth, frameHeight,
+                                    frameStride, frameSliceHeight, frame);
+                        }
+                        yuv.write(frame, 0, writeLength);
+                    }
+                    outputFrameIndex++;
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = inPresentationTimeUs - outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, bufferInfo.size,
+                            outPresentationTimeUs, bufferInfo.flags);
+                    bufferInfos.add(bufferInfoCopy);
+                }
+                decoder.releaseOutputBuffer(outputBufIndex, false);
+            }
+        }
+        decoder.stop();
+        decoder.release();
+        ivf.close();
+        if (yuv != null) {
+            yuv.close();
+        }
+
+        return bufferInfos;
+    }
+
+
+    /**
+     * Helper function to return InputStream from either filename (if set)
+     * or resource id (if filename is not set).
+     */
+    private InputStream OpenFileOrResourceId(String filename, int resourceId) throws Exception {
+        if (filename != null) {
+            return new FileInputStream(filename);
+        }
+        return mResources.openRawResource(resourceId);
+    }
+
+    /**
+     * Results of frame encoding.
+     */
+    protected class MediaEncoderOutput {
+        public long inPresentationTimeUs;
+        public long outPresentationTimeUs;
+        public boolean outputGenerated;
+        public int flags;
+        public byte[] buffer;
+    }
+
+    protected class MediaEncoderAsyncHelper {
+        private final EncoderOutputStreamParameters mStreamParams;
+        private final CodecProperties mProperties;
+        private final ArrayList<MediaCodec.BufferInfo> mBufferInfos;
+        private final IvfWriter mIvf;
+        private final byte[] mSrcFrame;
+
+        private InputStream mYuvStream;
+        private int mInputFrameIndex;
+
+        MediaEncoderAsyncHelper(
+                EncoderOutputStreamParameters streamParams,
+                CodecProperties properties,
+                ArrayList<MediaCodec.BufferInfo> bufferInfos,
+                IvfWriter ivf)
+                throws Exception {
+            mStreamParams = streamParams;
+            mProperties = properties;
+            mBufferInfos = bufferInfos;
+            mIvf = ivf;
+
+            int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
+            mSrcFrame = new byte[srcFrameSize];
+
+            mYuvStream = OpenFileOrResourceId(
+                    streamParams.inputYuvFilename, streamParams.inputResourceId);
+        }
+
+        public byte[] getInputFrame() {
+            // Check EOS
+            if (mStreamParams.frameCount == 0
+                    || (mStreamParams.frameCount > 0
+                            && mInputFrameIndex >= mStreamParams.frameCount)) {
+                Log.d(TAG, "---Sending EOS empty frame for frame # " + mInputFrameIndex);
+                return null;
+            }
+
+            try {
+                int bytesRead = mYuvStream.read(mSrcFrame);
+
+                if (bytesRead == -1) {
+                    // rewind to beginning of file
+                    mYuvStream.close();
+                    mYuvStream = OpenFileOrResourceId(
+                            mStreamParams.inputYuvFilename, mStreamParams.inputResourceId);
+                    bytesRead = mYuvStream.read(mSrcFrame);
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to read YUV file.");
+                return null;
+            }
+            mInputFrameIndex++;
+
+            // Convert YUV420 to NV12 if necessary
+            if (mProperties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                return YUV420ToNV(mStreamParams.frameWidth, mStreamParams.frameHeight,
+                        mSrcFrame);
+            } else {
+                return mSrcFrame;
+            }
+        }
+
+        public boolean saveOutputFrame(MediaEncoderOutput out) {
+            if (out.outputGenerated) {
+                if (out.buffer.length > 0) {
+                    // Save frame
+                    try {
+                        mIvf.writeFrame(out.buffer, out.outPresentationTimeUs);
+                    } catch (Exception e) {
+                        Log.d(TAG, "Failed to write frame");
+                        return true;
+                    }
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = out.inPresentationTimeUs -
+                            out.outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                            out.outPresentationTimeUs, out.flags);
+                    mBufferInfos.add(bufferInfoCopy);
+                }
+                // Detect output EOS
+                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    Log.d(TAG, "----Output EOS ");
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Video encoder wrapper class.
+     * Allows to run the encoder either in a callee's thread or in a looper thread
+     * using buffer dequeue ready notification callbacks.
+     *
+     * Function feedInput() is used to send raw video frame to the encoder input. When encoder
+     * is configured to run in async mode the function will run in a looper thread.
+     * Encoded frame can be retrieved by calling getOutput() function.
+     */
+    protected class MediaEncoderAsync extends Thread {
+        private int mId;
+        private MediaCodec mCodec;
+        private MediaFormat mFormat;
+        private ByteBuffer[] mInputBuffers;
+        private ByteBuffer[] mOutputBuffers;
+        private int mInputFrameIndex;
+        private int mOutputFrameIndex;
+        private int mInputBufIndex;
+        private int mFrameRate;
+        private long mTimeout;
+        private MediaCodec.BufferInfo mBufferInfo;
+        private long mInPresentationTimeUs;
+        private long mOutPresentationTimeUs;
+        private boolean mAsync;
+        // Flag indicating if input frame was consumed by the encoder in feedInput() call.
+        private boolean mConsumedInput;
+        // Result of frame encoding returned by getOutput() call.
+        private MediaEncoderOutput mOutput;
+        // Object used to signal that looper thread has started and Handler instance associated
+        // with looper thread has been allocated.
+        private final Object mThreadEvent = new Object();
+        // Object used to signal that MediaCodec buffer dequeue notification callback
+        // was received.
+        private final Object mCallbackEvent = new Object();
+        private Handler mHandler;
+        private boolean mCallbackReceived;
+        private MediaEncoderAsyncHelper mHelper;
+        private final Object mCompletionEvent = new Object();
+        private boolean mCompleted;
+
+        private MediaCodec.Callback mCallback = new MediaCodec.Callback() {
+            @Override
+            public void onInputBufferAvailable(MediaCodec codec, int index) {
+                if (mHelper == null) {
+                    Log.e(TAG, "async helper not available");
+                    return;
+                }
+
+                byte[] encFrame = mHelper.getInputFrame();
+                boolean inputEOS = (encFrame == null);
+
+                int encFrameLength = 0;
+                int flags = 0;
+                if (inputEOS) {
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                } else {
+                    encFrameLength = encFrame.length;
+
+                    ByteBuffer byteBuffer = mCodec.getInputBuffer(index);
+                    byteBuffer.put(encFrame);
+                    byteBuffer.rewind();
+
+                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
+
+                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
+                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
+
+                    mInputFrameIndex++;
+                }
+
+                mCodec.queueInputBuffer(
+                        index,
+                        0,  // offset
+                        encFrameLength,  // size
+                        mInPresentationTimeUs,
+                        flags);
+            }
+
+            @Override
+            public void onOutputBufferAvailable(MediaCodec codec,
+                    int index, MediaCodec.BufferInfo info) {
+                if (mHelper == null) {
+                    Log.e(TAG, "async helper not available");
+                    return;
+                }
+
+                MediaEncoderOutput out = new MediaEncoderOutput();
+
+                out.buffer = new byte[info.size];
+                ByteBuffer outputBuffer = mCodec.getOutputBuffer(index);
+                outputBuffer.get(out.buffer, 0, info.size);
+                mOutPresentationTimeUs = info.presentationTimeUs;
+
+                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
+                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                    logStr += " CONFIG. ";
+                }
+                if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                    logStr += " KEY. ";
+                }
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    logStr += " EOS. ";
+                }
+                logStr += " Size: " + info.size;
+                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
+                Log.v(TAG, logStr);
+
+                if (mOutputFrameIndex == 0 &&
+                        ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
+                    throw new RuntimeException("First frame is not a sync frame.");
+                }
+
+                if (info.size > 0) {
+                    mOutputFrameIndex++;
+                    out.inPresentationTimeUs = mInPresentationTimeUs;
+                    out.outPresentationTimeUs = mOutPresentationTimeUs;
+                }
+                mCodec.releaseOutputBuffer(index, false);
+
+                out.flags = info.flags;
+                out.outputGenerated = true;
+
+                if (mHelper.saveOutputFrame(out)) {
+                    // output EOS
+                    signalCompletion();
+                }
+            }
+
+            @Override
+            public void onError(MediaCodec codec, CodecException e) {
+                Log.e(TAG, "onError: " + e
+                        + ", transient " + e.isTransient()
+                        + ", recoverable " + e.isRecoverable()
+                        + ", error " + e.getErrorCode());
+            }
+
+            @Override
+            public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+                Log.i(TAG, "onOutputFormatChanged: " + format.toString());
+            }
+        };
+
+        private synchronized void requestStart() throws Exception {
+            mHandler = null;
+            start();
+            // Wait for Hander allocation
+            synchronized (mThreadEvent) {
+                while (mHandler == null) {
+                    mThreadEvent.wait();
+                }
+            }
+        }
+
+        public void setAsyncHelper(MediaEncoderAsyncHelper helper) {
+            mHelper = helper;
+        }
+
+        @Override
+        public void run() {
+            Looper.prepare();
+            synchronized (mThreadEvent) {
+                mHandler = new Handler();
+                mThreadEvent.notify();
+            }
+            Looper.loop();
+        }
+
+        private void runCallable(final Callable<?> callable) throws Exception {
+            if (mAsync) {
+                final Exception[] exception = new Exception[1];
+                final CountDownLatch countDownLatch = new CountDownLatch(1);
+                mHandler.post( new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            callable.call();
+                        } catch (Exception e) {
+                            exception[0] = e;
+                        } finally {
+                            countDownLatch.countDown();
+                        }
+                    }
+                } );
+
+                // Wait for task completion
+                countDownLatch.await();
+                if (exception[0] != null) {
+                    throw exception[0];
+                }
+            } else {
+                callable.call();
+            }
+        }
+
+        private synchronized void requestStop() throws Exception {
+            mHandler.post( new Runnable() {
+                @Override
+                public void run() {
+                    // This will run on the Looper thread
+                    Log.v(TAG, "MediaEncoder looper quitting");
+                    Looper.myLooper().quitSafely();
+                }
+            } );
+            // Wait for completion
+            join();
+            mHandler = null;
+        }
+
+        private void createCodecInternal(final String name,
+                final MediaFormat format, final long timeout) throws Exception {
+            mBufferInfo = new MediaCodec.BufferInfo();
+            mFormat = format;
+            mFrameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+            mTimeout = timeout;
+            mInputFrameIndex = 0;
+            mOutputFrameIndex = 0;
+            mInPresentationTimeUs = 0;
+            mOutPresentationTimeUs = 0;
+
+            mCodec = MediaCodec.createByCodecName(name);
+            if (mAsync) {
+                mCodec.setCallback(mCallback);
+            }
+            mCodec.configure(mFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+            mCodec.start();
+
+            // get the cached input/output only in sync mode
+            if (!mAsync) {
+                mInputBuffers = mCodec.getInputBuffers();
+                mOutputBuffers = mCodec.getOutputBuffers();
+            }
+        }
+
+        public void createCodec(int id, final String name, final MediaFormat format,
+                final long timeout, boolean async)  throws Exception {
+            mId = id;
+            mAsync = async;
+            if (mAsync) {
+                requestStart(); // start looper thread
+            }
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    createCodecInternal(name, format, timeout);
+                    return null;
+                }
+            } );
+        }
+
+        private void feedInputInternal(final byte[] encFrame, final boolean inputEOS) {
+            mConsumedInput = false;
+            // Feed input
+            mInputBufIndex = mCodec.dequeueInputBuffer(mTimeout);
+
+            if (mInputBufIndex >= 0) {
+                mInputBuffers[mInputBufIndex].clear();
+                mInputBuffers[mInputBufIndex].put(encFrame);
+                mInputBuffers[mInputBufIndex].rewind();
+                int encFrameLength = encFrame.length;
+                int flags = 0;
+                if (inputEOS) {
+                    encFrameLength = 0;
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                }
+                if (!inputEOS) {
+                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
+                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
+                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
+                    mInputFrameIndex++;
+                }
+
+                mCodec.queueInputBuffer(
+                        mInputBufIndex,
+                        0,  // offset
+                        encFrameLength,  // size
+                        mInPresentationTimeUs,
+                        flags);
+
+                mConsumedInput = true;
+            } else {
+                Log.v(TAG, "In " + mId + " - TRY_AGAIN_LATER");
+            }
+            mCallbackReceived = false;
+        }
+
+        public boolean feedInput(final byte[] encFrame, final boolean inputEOS) throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    feedInputInternal(encFrame, inputEOS);
+                    return null;
+                }
+            } );
+            return mConsumedInput;
+        }
+
+        private void getOutputInternal() {
+            mOutput = new MediaEncoderOutput();
+            mOutput.inPresentationTimeUs = mInPresentationTimeUs;
+            mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
+            mOutput.outputGenerated = false;
+
+            // Get output from the encoder
+            int result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
+            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
+                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                    mOutputBuffers = mCodec.getOutputBuffers();
+                } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                    mFormat = mCodec.getOutputFormat();
+                    Log.d(TAG, "Format changed: " + mFormat.toString());
+                }
+                result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
+            }
+            if (result == MediaCodec.INFO_TRY_AGAIN_LATER) {
+                Log.v(TAG, "Out " + mId + " - TRY_AGAIN_LATER");
+            }
+
+            if (result >= 0) {
+                int outputBufIndex = result;
+                mOutput.buffer = new byte[mBufferInfo.size];
+                mOutputBuffers[outputBufIndex].position(mBufferInfo.offset);
+                mOutputBuffers[outputBufIndex].get(mOutput.buffer, 0, mBufferInfo.size);
+                mOutPresentationTimeUs = mBufferInfo.presentationTimeUs;
+
+                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                    logStr += " CONFIG. ";
+                }
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                    logStr += " KEY. ";
+                }
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    logStr += " EOS. ";
+                }
+                logStr += " Size: " + mBufferInfo.size;
+                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
+                Log.v(TAG, logStr);
+                if (mOutputFrameIndex == 0 &&
+                        ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
+                    throw new RuntimeException("First frame is not a sync frame.");
+                }
+
+                if (mBufferInfo.size > 0) {
+                    mOutputFrameIndex++;
+                    mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
+                }
+                mCodec.releaseOutputBuffer(outputBufIndex, false);
+
+                mOutput.flags = mBufferInfo.flags;
+                mOutput.outputGenerated = true;
+            }
+            mCallbackReceived = false;
+        }
+
+        public MediaEncoderOutput getOutput() throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    getOutputInternal();
+                    return null;
+                }
+            } );
+            return mOutput;
+        }
+
+        public void forceSyncFrame() throws Exception {
+            final Bundle syncFrame = new Bundle();
+            syncFrame.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.setParameters(syncFrame);
+                    return null;
+                }
+            } );
+        }
+
+        public void updateBitrate(int bitrate) throws Exception {
+            final Bundle bitrateUpdate = new Bundle();
+            bitrateUpdate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bitrate);
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.setParameters(bitrateUpdate);
+                    return null;
+                }
+            } );
+        }
+
+
+        public void waitForBufferEvent() throws Exception {
+            Log.v(TAG, "----Enc" + mId + " waiting for bufferEvent");
+            if (mAsync) {
+                synchronized (mCallbackEvent) {
+                    if (!mCallbackReceived) {
+                        mCallbackEvent.wait(1000); // wait 1 sec for a callback
+                        // throw an exception if callback was not received
+                        if (!mCallbackReceived) {
+                            throw new RuntimeException("MediaCodec callback was not received");
+                        }
+                    }
+                }
+            } else {
+                Thread.sleep(5);
+            }
+            Log.v(TAG, "----Waiting for bufferEvent done");
+        }
+
+
+        public void waitForCompletion(long timeoutMs) throws Exception {
+            synchronized (mCompletionEvent) {
+                long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
+
+                while (!mCompleted) {
+                    mCompletionEvent.wait(timeoutExpiredMs - System.currentTimeMillis());
+                    if (System.currentTimeMillis() >= timeoutExpiredMs) {
+                        throw new RuntimeException("encoding has timed out!");
+                    }
+                }
+            }
+        }
+
+        public void signalCompletion() {
+            synchronized (mCompletionEvent) {
+                mCompleted = true;
+                mCompletionEvent.notify();
+            }
+        }
+
+        public void deleteCodec() throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.stop();
+                    mCodec.release();
+                    return null;
+                }
+            } );
+            if (mAsync) {
+                requestStop(); // Stop looper thread
+            }
+        }
+    }
+
+    /**
+     * Vpx encoding loop supporting encoding single streams with an option
+     * to run in a looper thread and use buffer ready notification callbacks.
+     *
+     * Output stream is described by encodingParams parameters.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vpx encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param streamParams  Structure with encoder parameters
+     * @return              Returns array of encoded frames information for each frame.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> encode(
+            EncoderOutputStreamParameters streamParams) throws Exception {
+
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+        Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
+                streamParams.frameHeight);
+        int bitrate = streamParams.bitrateSet[0];
+
+        // Create minimal media format signifying desired output.
+        MediaFormat format = MediaFormat.createVideoFormat(
+                streamParams.codecMimeType, streamParams.frameWidth,
+                streamParams.frameHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+        CodecProperties properties = getVpxCodecProperties(
+                true, format, streamParams.forceGoogleEncoder);
+        if (properties == null) {
+            return null;
+        }
+
+        // Open input/output
+        InputStream yuvStream = OpenFileOrResourceId(
+                streamParams.inputYuvFilename, streamParams.inputResourceId);
+        IvfWriter ivf = new IvfWriter(
+                streamParams.outputIvfFilename, streamParams.codecMimeType,
+                streamParams.frameWidth, streamParams.frameHeight);
+
+        // Create a media format signifying desired output.
+        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
+            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+        }
+        if (streamParams.temporalLayers > 0) {
+            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
+        }
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
+        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
+                streamParams.frameRate;
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+
+        // Create encoder
+        Log.d(TAG, "Creating encoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                streamParams.frameWidth + " x " + streamParams.frameHeight +
+                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
+                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
+                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
+                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
+        MediaEncoderAsync codec = new MediaEncoderAsync();
+        codec.createCodec(0, properties.codecName, format,
+                streamParams.timeoutDequeue, streamParams.runInLooperThread);
+
+        // encode loop
+        boolean sawInputEOS = false;  // no more data
+        boolean consumedInputEOS = false; // EOS flag is consumed dy encoder
+        boolean sawOutputEOS = false;
+        boolean inputConsumed = true;
+        int inputFrameIndex = 0;
+        int lastBitrate = bitrate;
+        int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
+        byte[] srcFrame = new byte[srcFrameSize];
+
+        while (!sawOutputEOS) {
+
+            // Read and feed input frame
+            if (!consumedInputEOS) {
+
+                // Read new input buffers - if previous input was consumed and no EOS
+                if (inputConsumed && !sawInputEOS) {
+                    int bytesRead = yuvStream.read(srcFrame);
+
+                    // Check EOS
+                    if (streamParams.frameCount > 0 && inputFrameIndex >= streamParams.frameCount) {
+                        sawInputEOS = true;
+                        Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
+                    }
+
+                    if (!sawInputEOS && bytesRead == -1) {
+                        if (streamParams.frameCount == 0) {
+                            sawInputEOS = true;
+                            Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
+                        } else {
+                            yuvStream.close();
+                            yuvStream = OpenFileOrResourceId(
+                                    streamParams.inputYuvFilename, streamParams.inputResourceId);
+                            bytesRead = yuvStream.read(srcFrame);
+                        }
+                    }
+
+                    // Force sync frame if syncForceFrameinterval is set.
+                    if (!sawInputEOS && inputFrameIndex > 0 &&
+                            streamParams.syncForceFrameInterval > 0 &&
+                            (inputFrameIndex % streamParams.syncForceFrameInterval) == 0) {
+                        Log.d(TAG, "---Requesting sync frame # " + inputFrameIndex);
+                        codec.forceSyncFrame();
+                    }
+
+                    // Dynamic bitrate change.
+                    if (!sawInputEOS && streamParams.bitrateSet.length > inputFrameIndex) {
+                        int newBitrate = streamParams.bitrateSet[inputFrameIndex];
+                        if (newBitrate != lastBitrate) {
+                            Log.d(TAG, "--- Requesting new bitrate " + newBitrate +
+                                    " for frame " + inputFrameIndex);
+                            codec.updateBitrate(newBitrate);
+                            lastBitrate = newBitrate;
+                        }
+                    }
+
+                    // Convert YUV420 to NV12 if necessary
+                    if (properties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                        srcFrame = YUV420ToNV(streamParams.frameWidth, streamParams.frameHeight,
+                                srcFrame);
+                    }
+                }
+
+                inputConsumed = codec.feedInput(srcFrame, sawInputEOS);
+                if (inputConsumed) {
+                    inputFrameIndex++;
+                    consumedInputEOS = sawInputEOS;
+                }
+            }
+
+            // Get output from the encoder
+            MediaEncoderOutput out = codec.getOutput();
+            if (out.outputGenerated) {
+                // Detect output EOS
+                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    Log.d(TAG, "----Output EOS ");
+                    sawOutputEOS = true;
+                }
+
+                if (out.buffer.length > 0) {
+                    // Save frame
+                    ivf.writeFrame(out.buffer, out.outPresentationTimeUs);
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = out.inPresentationTimeUs -
+                            out.outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                            out.outPresentationTimeUs, out.flags);
+                    bufferInfos.add(bufferInfoCopy);
+                }
+            }
+
+            // If codec is not ready to accept input/poutput - wait for buffer ready callback
+            if ((!inputConsumed || consumedInputEOS) && !out.outputGenerated) {
+                codec.waitForBufferEvent();
+            }
+        }
+
+        codec.deleteCodec();
+        ivf.close();
+        yuvStream.close();
+
+        return bufferInfos;
+    }
+
+    /**
+     * Vpx encoding run in a looper thread and use buffer ready callbacks.
+     *
+     * Output stream is described by encodingParams parameters.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vpx encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param streamParams  Structure with encoder parameters
+     * @return              Returns array of encoded frames information for each frame.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> encodeAsync(
+            EncoderOutputStreamParameters streamParams) throws Exception {
+        if (!streamParams.runInLooperThread) {
+            throw new RuntimeException("encodeAsync should run with a looper thread!");
+        }
+
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+        Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
+                streamParams.frameHeight);
+        int bitrate = streamParams.bitrateSet[0];
+
+        // Create minimal media format signifying desired output.
+        MediaFormat format = MediaFormat.createVideoFormat(
+                streamParams.codecMimeType, streamParams.frameWidth,
+                streamParams.frameHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+        CodecProperties properties = getVpxCodecProperties(
+                true, format, streamParams.forceGoogleEncoder);
+        if (properties == null) {
+            return null;
+        }
+
+        // Open input/output
+        IvfWriter ivf = new IvfWriter(
+                streamParams.outputIvfFilename, streamParams.codecMimeType,
+                streamParams.frameWidth, streamParams.frameHeight);
+
+        // Create a media format signifying desired output.
+        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
+            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+        }
+        if (streamParams.temporalLayers > 0) {
+            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
+        }
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
+        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
+                streamParams.frameRate;
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+
+        // Create encoder
+        Log.d(TAG, "Creating encoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                streamParams.frameWidth + " x " + streamParams.frameHeight +
+                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
+                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
+                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
+                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
+
+        MediaEncoderAsync codec = new MediaEncoderAsync();
+        MediaEncoderAsyncHelper helper = new MediaEncoderAsyncHelper(
+                streamParams, properties, bufferInfos, ivf);
+
+        codec.setAsyncHelper(helper);
+        codec.createCodec(0, properties.codecName, format,
+                streamParams.timeoutDequeue, streamParams.runInLooperThread);
+        codec.waitForCompletion(DEFAULT_ENCODE_TIMEOUT_MS);
+
+        codec.deleteCodec();
+        ivf.close();
+
+        return bufferInfos;
+    }
+
+    /**
+     * Vpx encoding loop supporting encoding multiple streams at a time.
+     * Each output stream is described by encodingParams parameters allowing
+     * simultaneous encoding of various resolutions, bitrates with an option to
+     * control key frame and dynamic bitrate for each output stream indepandently.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vpx encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param srcFrameWidth     Frame width of input yuv file
+     * @param srcFrameHeight    Frame height of input yuv file
+     * @param encodingParams    Encoder parameters
+     * @return                  Returns 2D array of encoded frames information for each stream and
+     *                          for each frame.
+     */
+    protected ArrayList<ArrayList<MediaCodec.BufferInfo>> encodeSimulcast(
+            int srcFrameWidth,
+            int srcFrameHeight,
+            ArrayList<EncoderOutputStreamParameters> encodingParams)  throws Exception {
+        int numEncoders = encodingParams.size();
+
+        // Create arrays of input/output, formats, bitrates etc
+        ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos =
+                new ArrayList<ArrayList<MediaCodec.BufferInfo>>(numEncoders);
+        InputStream yuvStream[] = new InputStream[numEncoders];
+        IvfWriter[] ivf = new IvfWriter[numEncoders];
+        FileOutputStream[] yuvScaled = new FileOutputStream[numEncoders];
+        MediaFormat[] format = new MediaFormat[numEncoders];
+        MediaEncoderAsync[] codec = new MediaEncoderAsync[numEncoders];
+        int[] inputFrameIndex = new int[numEncoders];
+        boolean[] sawInputEOS = new boolean[numEncoders];
+        boolean[] consumedInputEOS = new boolean[numEncoders];
+        boolean[] inputConsumed = new boolean[numEncoders];
+        boolean[] bufferConsumed = new boolean[numEncoders];
+        boolean[] sawOutputEOS = new boolean[numEncoders];
+        byte[][] srcFrame = new byte[numEncoders][];
+        boolean sawOutputEOSTotal = false;
+        boolean bufferConsumedTotal = false;
+        CodecProperties[] codecProperties = new CodecProperties[numEncoders];
+
+        numEncoders = 0;
+        for (EncoderOutputStreamParameters params : encodingParams) {
+            int i = numEncoders;
+            Log.d(TAG, "Source resolution: " + params.frameWidth + " x " +
+                    params.frameHeight);
+            int bitrate = params.bitrateSet[0];
+
+            // Create minimal media format signifying desired output.
+            format[i] = MediaFormat.createVideoFormat(
+                    params.codecMimeType, params.frameWidth,
+                    params.frameHeight);
+            format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+            CodecProperties properties = getVpxCodecProperties(
+                    true, format[i], params.forceGoogleEncoder);
+            if (properties == null) {
+                continue;
+            }
+
+            // Check if scaled image was created
+            int scale = params.frameWidth / srcFrameWidth;
+            if (!mScaledImages.contains(scale)) {
+                // resize image
+                cacheScaledImage(params.inputYuvFilename, params.inputResourceId,
+                        srcFrameWidth, srcFrameHeight,
+                        params.scaledYuvFilename, params.frameWidth, params.frameHeight);
+                mScaledImages.add(scale);
+            }
+
+            // Create buffer info storage
+            bufferInfos.add(new ArrayList<MediaCodec.BufferInfo>());
+
+            // Create YUV reader
+            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
+
+            // Create IVF writer
+            ivf[i] = new IvfWriter(
+                    params.outputIvfFilename, params.codecMimeType,
+                    params.frameWidth, params.frameHeight);
+
+            // Frame buffer
+            int frameSize = params.frameWidth * params.frameHeight * 3 / 2;
+            srcFrame[i] = new byte[frameSize];
+
+            // Create a media format signifying desired output.
+            if (params.bitrateType == VIDEO_ControlRateConstant) {
+                format[i].setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+            }
+            if (params.temporalLayers > 0) {
+                format[i].setInteger("ts-layers", params.temporalLayers); // 1 temporal layer
+            }
+            format[i].setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+            format[i].setInteger(MediaFormat.KEY_FRAME_RATE, params.frameRate);
+            int syncFrameInterval = (params.syncFrameInterval + params.frameRate/2) /
+                    params.frameRate; // in sec
+            format[i].setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+            // Create encoder
+            Log.d(TAG, "Creating encoder #" + i +" : " + properties.codecName +
+                    ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                    params.frameWidth + " x " + params.frameHeight +
+                    ". Bitrate: " + bitrate + " Bitrate type: " + params.bitrateType +
+                    ". Fps:" + params.frameRate + ". TS Layers: " + params.temporalLayers +
+                    ". Key frame:" + syncFrameInterval * params.frameRate +
+                    ". Force keyFrame: " + params.syncForceFrameInterval);
+            Log.d(TAG, "  Format: " + format[i]);
+            Log.d(TAG, "  Output ivf:" + params.outputIvfFilename);
+
+            // Create encoder
+            codec[i] = new MediaEncoderAsync();
+            codec[i].createCodec(i, properties.codecName, format[i],
+                    params.timeoutDequeue, params.runInLooperThread);
+            codecProperties[i] = new CodecProperties(properties.codecName, properties.colorFormat);
+
+            inputConsumed[i] = true;
+            ++numEncoders;
+        }
+        if (numEncoders == 0) {
+            Log.i(TAG, "no suitable encoders found for any of the streams");
+            return null;
+        }
+
+        while (!sawOutputEOSTotal) {
+            // Feed input buffer to all encoders
+            for (int i = 0; i < numEncoders; i++) {
+                bufferConsumed[i] = false;
+                if (consumedInputEOS[i]) {
+                    continue;
+                }
+
+                EncoderOutputStreamParameters params = encodingParams.get(i);
+                // Read new input buffers - if previous input was consumed and no EOS
+                if (inputConsumed[i] && !sawInputEOS[i]) {
+                    int bytesRead = yuvStream[i].read(srcFrame[i]);
+
+                    // Check EOS
+                    if (params.frameCount > 0 && inputFrameIndex[i] >= params.frameCount) {
+                        sawInputEOS[i] = true;
+                        Log.d(TAG, "---Enc" + i +
+                                ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
+                    }
+
+                    if (!sawInputEOS[i] && bytesRead == -1) {
+                        if (params.frameCount == 0) {
+                            sawInputEOS[i] = true;
+                            Log.d(TAG, "---Enc" + i +
+                                    ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
+                        } else {
+                            yuvStream[i].close();
+                            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
+                            bytesRead = yuvStream[i].read(srcFrame[i]);
+                        }
+                    }
+
+                    // Convert YUV420 to NV12 if necessary
+                    if (codecProperties[i].colorFormat !=
+                            CodecCapabilities.COLOR_FormatYUV420Planar) {
+                        srcFrame[i] =
+                            YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
+                    }
+                }
+
+                inputConsumed[i] = codec[i].feedInput(srcFrame[i], sawInputEOS[i]);
+                if (inputConsumed[i]) {
+                    inputFrameIndex[i]++;
+                    consumedInputEOS[i] = sawInputEOS[i];
+                    bufferConsumed[i] = true;
+                }
+
+            }
+
+            // Get output from all encoders
+            for (int i = 0; i < numEncoders; i++) {
+                if (sawOutputEOS[i]) {
+                    continue;
+                }
+
+                MediaEncoderOutput out = codec[i].getOutput();
+                if (out.outputGenerated) {
+                    bufferConsumed[i] = true;
+                    // Detect output EOS
+                    if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                        Log.d(TAG, "----Enc" + i + ". Output EOS ");
+                        sawOutputEOS[i] = true;
+                    }
+
+                    if (out.buffer.length > 0) {
+                        // Save frame
+                        ivf[i].writeFrame(out.buffer, out.outPresentationTimeUs);
+
+                        // Update statistics - store presentation time delay in offset
+                        long presentationTimeUsDelta = out.inPresentationTimeUs -
+                                out.outPresentationTimeUs;
+                        MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                        bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                                out.outPresentationTimeUs, out.flags);
+                        bufferInfos.get(i).add(bufferInfoCopy);
+                    }
+                }
+            }
+
+            // If codec is not ready to accept input/output - wait for buffer ready callback
+            bufferConsumedTotal = false;
+            for (boolean bufferConsumedCurrent : bufferConsumed) {
+                bufferConsumedTotal |= bufferConsumedCurrent;
+            }
+            if (!bufferConsumedTotal) {
+                // Pick the encoder to wait for
+                for (int i = 0; i < numEncoders; i++) {
+                    if (!bufferConsumed[i] && !sawOutputEOS[i]) {
+                        codec[i].waitForBufferEvent();
+                        break;
+                    }
+                }
+            }
+
+            // Check if EOS happened for all encoders
+            sawOutputEOSTotal = true;
+            for (boolean sawOutputEOSStream : sawOutputEOS) {
+                sawOutputEOSTotal &= sawOutputEOSStream;
+            }
+        }
+
+        for (int i = 0; i < numEncoders; i++) {
+            codec[i].deleteCodec();
+            ivf[i].close();
+            yuvStream[i].close();
+            if (yuvScaled[i] != null) {
+                yuvScaled[i].close();
+            }
+        }
+
+        return bufferInfos;
+    }
+
+    /**
+     * Some encoding statistics.
+     */
+    protected class VpxEncodingStatistics {
+        VpxEncodingStatistics() {
+            mBitrates = new ArrayList<Integer>();
+            mFrames = new ArrayList<Integer>();
+            mKeyFrames = new ArrayList<Integer>();
+            mMinimumKeyFrameInterval = Integer.MAX_VALUE;
+        }
+
+        public ArrayList<Integer> mBitrates;// Bitrate values for each second of the encoded stream.
+        public ArrayList<Integer> mFrames; // Number of frames in each second of the encoded stream.
+        public int mAverageBitrate;         // Average stream bitrate.
+        public ArrayList<Integer> mKeyFrames;// Stores the position of key frames in a stream.
+        public int mAverageKeyFrameInterval; // Average key frame interval.
+        public int mMaximumKeyFrameInterval; // Maximum key frame interval.
+        public int mMinimumKeyFrameInterval; // Minimum key frame interval.
+    }
+
+    /**
+     * Calculates average bitrate and key frame interval for the encoded streams.
+     * Output mBitrates field will contain bitrate values for every second
+     * of the encoded stream.
+     * Average stream bitrate will be stored in mAverageBitrate field.
+     * mKeyFrames array will contain the position of key frames in the encoded stream and
+     * mKeyFrameInterval - average key frame interval.
+     */
+    protected VpxEncodingStatistics computeEncodingStatistics(int encoderId,
+            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
+        VpxEncodingStatistics statistics = new VpxEncodingStatistics();
+
+        int totalSize = 0;
+        int frames = 0;
+        int framesPerSecond = 0;
+        int totalFrameSizePerSecond = 0;
+        int maxFrameSize = 0;
+        int currentSecond;
+        int nextSecond = 0;
+        String keyFrameList = "  IFrame List: ";
+        String bitrateList = "  Bitrate list: ";
+        String framesList = "  FPS list: ";
+
+
+        for (int j = 0; j < bufferInfos.size(); j++) {
+            MediaCodec.BufferInfo info = bufferInfos.get(j);
+            currentSecond = (int)(info.presentationTimeUs / 1000000);
+            boolean lastFrame = (j == bufferInfos.size() - 1);
+            if (!lastFrame) {
+                nextSecond = (int)(bufferInfos.get(j+1).presentationTimeUs / 1000000);
+            }
+
+            totalSize += info.size;
+            totalFrameSizePerSecond += info.size;
+            maxFrameSize = Math.max(maxFrameSize, info.size);
+            framesPerSecond++;
+            frames++;
+
+            // Update the bitrate statistics if the next frame will
+            // be for the next second
+            if (lastFrame || nextSecond > currentSecond) {
+                int currentBitrate = totalFrameSizePerSecond * 8;
+                bitrateList += (currentBitrate + " ");
+                framesList += (framesPerSecond + " ");
+                statistics.mBitrates.add(currentBitrate);
+                statistics.mFrames.add(framesPerSecond);
+                totalFrameSizePerSecond = 0;
+                framesPerSecond = 0;
+            }
+
+            // Update key frame statistics.
+            if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                statistics.mKeyFrames.add(j);
+                keyFrameList += (j + "  ");
+            }
+        }
+        int duration = (int)(bufferInfos.get(bufferInfos.size() - 1).presentationTimeUs / 1000);
+        duration = (duration + 500) / 1000;
+        statistics.mAverageBitrate = (int)(((long)totalSize * 8) / duration);
+        Log.d(TAG, "Statistics for encoder # " + encoderId);
+        // Calculate average key frame interval in frames.
+        int keyFrames = statistics.mKeyFrames.size();
+        if (keyFrames > 1) {
+            statistics.mAverageKeyFrameInterval =
+                    statistics.mKeyFrames.get(keyFrames - 1) - statistics.mKeyFrames.get(0);
+            statistics.mAverageKeyFrameInterval =
+                    Math.round((float)statistics.mAverageKeyFrameInterval / (keyFrames - 1));
+            for (int j = 1; j < keyFrames; j++) {
+                int keyFrameInterval =
+                        statistics.mKeyFrames.get(j) - statistics.mKeyFrames.get(j - 1);
+                statistics.mMaximumKeyFrameInterval =
+                        Math.max(statistics.mMaximumKeyFrameInterval, keyFrameInterval);
+                statistics.mMinimumKeyFrameInterval =
+                        Math.min(statistics.mMinimumKeyFrameInterval, keyFrameInterval);
+            }
+            Log.d(TAG, "  Key frame intervals: Max: " + statistics.mMaximumKeyFrameInterval +
+                    ". Min: " + statistics.mMinimumKeyFrameInterval +
+                    ". Avg: " + statistics.mAverageKeyFrameInterval);
+        }
+        Log.d(TAG, "  Frames: " + frames + ". Duration: " + duration +
+                ". Total size: " + totalSize + ". Key frames: " + keyFrames);
+        Log.d(TAG, keyFrameList);
+        Log.d(TAG, bitrateList);
+        Log.d(TAG, framesList);
+        Log.d(TAG, "  Bitrate average: " + statistics.mAverageBitrate);
+        Log.d(TAG, "  Maximum frame size: " + maxFrameSize);
+
+        return statistics;
+    }
+
+    protected VpxEncodingStatistics computeEncodingStatistics(
+            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
+        return computeEncodingStatistics(0, bufferInfos);
+    }
+
+    protected ArrayList<VpxEncodingStatistics> computeSimulcastEncodingStatistics(
+            ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos) {
+        int numCodecs = bufferInfos.size();
+        ArrayList<VpxEncodingStatistics> statistics = new ArrayList<VpxEncodingStatistics>();
+
+        for (int i = 0; i < numCodecs; i++) {
+            VpxEncodingStatistics currentStatistics =
+                    computeEncodingStatistics(i, bufferInfos.get(i));
+            statistics.add(currentStatistics);
+        }
+        return statistics;
+    }
+
+    /**
+     * Calculates maximum latency for encoder/decoder based on buffer info array
+     * generated either by encoder or decoder.
+     */
+    protected int maxPresentationTimeDifference(ArrayList<MediaCodec.BufferInfo> bufferInfos) {
+        int maxValue = 0;
+        for (MediaCodec.BufferInfo bufferInfo : bufferInfos) {
+            maxValue = Math.max(maxValue,  bufferInfo.offset);
+        }
+        maxValue = (maxValue + 500) / 1000; // mcs -> ms
+        return maxValue;
+    }
+
+    /**
+     * Decoding PSNR statistics.
+     */
+    protected class VpxDecodingStatistics {
+        VpxDecodingStatistics() {
+            mMinimumPSNR = Integer.MAX_VALUE;
+        }
+        public double mAveragePSNR;
+        public double mMinimumPSNR;
+    }
+
+    /**
+     * Calculates PSNR value between two video frames.
+     */
+    private double computePSNR(byte[] data0, byte[] data1) {
+        long squareError = 0;
+        assertTrue(data0.length == data1.length);
+        int length = data0.length;
+        for (int i = 0 ; i < length; i++) {
+            int diff = ((int)data0[i] & 0xff) - ((int)data1[i] & 0xff);
+            squareError += diff * diff;
+        }
+        double meanSquareError = (double)squareError / length;
+        double psnr = 10 * Math.log10((double)255 * 255 / meanSquareError);
+        return psnr;
+    }
+
+    /**
+     * Calculates average and minimum PSNR values between
+     * set of reference and decoded video frames.
+     * Runs PSNR calculation for the full duration of the decoded data.
+     */
+    protected VpxDecodingStatistics computeDecodingStatistics(
+            String referenceYuvFilename,
+            int referenceYuvRawId,
+            String decodedYuvFilename,
+            int width,
+            int height) throws Exception {
+        VpxDecodingStatistics statistics = new VpxDecodingStatistics();
+        InputStream referenceStream =
+                OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
+        InputStream decodedStream = new FileInputStream(decodedYuvFilename);
+
+        int ySize = width * height;
+        int uvSize = width * height / 4;
+        byte[] yRef = new byte[ySize];
+        byte[] yDec = new byte[ySize];
+        byte[] uvRef = new byte[uvSize];
+        byte[] uvDec = new byte[uvSize];
+
+        int frames = 0;
+        double averageYPSNR = 0;
+        double averageUPSNR = 0;
+        double averageVPSNR = 0;
+        double minimumYPSNR = Integer.MAX_VALUE;
+        double minimumUPSNR = Integer.MAX_VALUE;
+        double minimumVPSNR = Integer.MAX_VALUE;
+        int minimumPSNRFrameIndex = 0;
+
+        while (true) {
+            // Calculate Y PSNR.
+            int bytesReadRef = referenceStream.read(yRef);
+            int bytesReadDec = decodedStream.read(yDec);
+            if (bytesReadDec == -1) {
+                break;
+            }
+            if (bytesReadRef == -1) {
+                // Reference file wrapping up
+                referenceStream.close();
+                referenceStream =
+                        OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
+                bytesReadRef = referenceStream.read(yRef);
+            }
+            double curYPSNR = computePSNR(yRef, yDec);
+            averageYPSNR += curYPSNR;
+            minimumYPSNR = Math.min(minimumYPSNR, curYPSNR);
+            double curMinimumPSNR = curYPSNR;
+
+            // Calculate U PSNR.
+            bytesReadRef = referenceStream.read(uvRef);
+            bytesReadDec = decodedStream.read(uvDec);
+            double curUPSNR = computePSNR(uvRef, uvDec);
+            averageUPSNR += curUPSNR;
+            minimumUPSNR = Math.min(minimumUPSNR, curUPSNR);
+            curMinimumPSNR = Math.min(curMinimumPSNR, curUPSNR);
+
+            // Calculate V PSNR.
+            bytesReadRef = referenceStream.read(uvRef);
+            bytesReadDec = decodedStream.read(uvDec);
+            double curVPSNR = computePSNR(uvRef, uvDec);
+            averageVPSNR += curVPSNR;
+            minimumVPSNR = Math.min(minimumVPSNR, curVPSNR);
+            curMinimumPSNR = Math.min(curMinimumPSNR, curVPSNR);
+
+            // Frame index for minimum PSNR value - help to detect possible distortions
+            if (curMinimumPSNR < statistics.mMinimumPSNR) {
+                statistics.mMinimumPSNR = curMinimumPSNR;
+                minimumPSNRFrameIndex = frames;
+            }
+
+            String logStr = String.format(Locale.US, "PSNR #%d: Y: %.2f. U: %.2f. V: %.2f",
+                    frames, curYPSNR, curUPSNR, curVPSNR);
+            Log.v(TAG, logStr);
+
+            frames++;
+        }
+
+        averageYPSNR /= frames;
+        averageUPSNR /= frames;
+        averageVPSNR /= frames;
+        statistics.mAveragePSNR = (4 * averageYPSNR + averageUPSNR + averageVPSNR) / 6;
+
+        Log.d(TAG, "PSNR statistics for " + frames + " frames.");
+        String logStr = String.format(Locale.US,
+                "Average PSNR: Y: %.1f. U: %.1f. V: %.1f. Average: %.1f",
+                averageYPSNR, averageUPSNR, averageVPSNR, statistics.mAveragePSNR);
+        Log.d(TAG, logStr);
+        logStr = String.format(Locale.US,
+                "Minimum PSNR: Y: %.1f. U: %.1f. V: %.1f. Overall: %.1f at frame %d",
+                minimumYPSNR, minimumUPSNR, minimumVPSNR,
+                statistics.mMinimumPSNR, minimumPSNRFrameIndex);
+        Log.d(TAG, logStr);
+
+        referenceStream.close();
+        decodedStream.close();
+        return statistics;
+    }
+}
+
diff --git a/tests/tests/media/src/android/media/cts/VpxEncoderTest.java b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
new file mode 100644
index 0000000..0e9c940
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.util.Log;
+import android.media.cts.R;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Verification test for vp8/vp9 encoder and decoder.
+ *
+ * A raw yv12 stream is encoded at various settings and written to an IVF
+ * file. Encoded stream bitrate and key frame interval are checked against target values.
+ * The stream is later decoded by vp8/vp9 decoder to verify frames are decodable and to
+ * calculate PSNR values for various bitrates.
+ */
+public class VpxEncoderTest extends VpxCodecTestBase {
+
+    private static final String ENCODED_IVF_BASE = "football";
+    private static final String INPUT_YUV = null;
+    private static final String OUTPUT_YUV = SDCARD_DIR + File.separator +
+            ENCODED_IVF_BASE + "_out.yuv";
+
+    // YUV stream properties.
+    private static final int WIDTH = 320;
+    private static final int HEIGHT = 240;
+    private static final int FPS = 30;
+    // Default encoding bitrate.
+    private static final int BITRATE = 400000;
+    // Default encoding bitrate mode
+    private static final int BITRATE_MODE = VIDEO_ControlRateVariable;
+    // List of bitrates used in quality and basic bitrate tests.
+    private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
+    // Maximum allowed bitrate variation from the target value.
+    private static final double MAX_BITRATE_VARIATION = 0.2;
+    // Average PSNR values for reference Google VPx codec for the above bitrates.
+    private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
+    // Minimum PSNR values for reference Google VPx codec for the above bitrates.
+    private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
+    // Maximum allowed average PSNR difference of encoder comparing to reference Google encoder.
+    private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
+    // Maximum allowed minimum PSNR difference of encoder comparing to reference Google encoder.
+    private static final double MAX_MINIMUM_PSNR_DIFFERENCE = 4;
+    // Maximum allowed average PSNR difference of the encoder running in a looper thread with 0 ms
+    // buffer dequeue timeout comparing to the encoder running in a callee's thread with 100 ms
+    // buffer dequeue timeout.
+    private static final double MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE = 0.5;
+    // Maximum allowed minimum PSNR difference of the encoder running in a looper thread
+    // comparing to the encoder running in a callee's thread.
+    private static final double MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE = 2;
+    // Maximum allowed average key frame interval variation from the target value.
+    private static final int MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION = 1;
+    // Maximum allowed key frame interval variation from the target value.
+    private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
+
+    /**
+     * A basic test for VPx encoder.
+     *
+     * Encodes 9 seconds of raw stream with default configuration options,
+     * and then decodes it to verify the bitstream.
+     * Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
+     */
+    private void internalTestBasic(String codecMimeType) throws Exception {
+        int encodeSeconds = 9;
+        boolean skipped = true;
+
+        for (int targetBitrate : TEST_BITRATES_SET) {
+            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                    INPUT_YUV,
+                    ENCODED_IVF_BASE,
+                    codecMimeType,
+                    encodeSeconds,
+                    WIDTH,
+                    HEIGHT,
+                    FPS,
+                    BITRATE_MODE,
+                    targetBitrate,
+                    true);
+            ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+            if (bufInfo == null) {
+                continue;
+            }
+            skipped = false;
+
+            VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+
+            assertEquals("Stream bitrate " + statistics.mAverageBitrate +
+                    " is different from the target " + targetBitrate,
+                    targetBitrate, statistics.mAverageBitrate,
+                    MAX_BITRATE_VARIATION * targetBitrate);
+
+            decode(params.outputIvfFilename, null, codecMimeType, FPS, params.forceGoogleEncoder);
+        }
+
+        if (skipped) {
+            Log.i(TAG, "SKIPPING testBasic(): codec is not supported");
+        }
+    }
+
+    /**
+     * Asynchronous encoding test for VPx encoder.
+     *
+     * Encodes 9 seconds of raw stream using synchronous and asynchronous calls.
+     * Checks the PSNR difference between the encoded and decoded output and reference yuv input
+     * does not change much for two different ways of the encoder call.
+     */
+    private void internalTestAsyncEncoding(String codecMimeType) throws Exception {
+        int encodeSeconds = 9;
+
+        // First test the encoder running in a looper thread with buffer callbacks enabled.
+        boolean syncEncoding = false;
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                codecMimeType,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                syncEncoding);
+        ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params);
+        if (bufInfos == null) {
+            Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
+            return;
+        }
+        computeEncodingStatistics(bufInfos);
+        decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+        VpxDecodingStatistics statisticsAsync = computeDecodingStatistics(
+                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                params.frameWidth, params.frameHeight);
+
+
+        // Test the encoder running in a callee's thread.
+        syncEncoding = true;
+        params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                codecMimeType,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                syncEncoding);
+        bufInfos = encode(params);
+        if (bufInfos == null) {
+            Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
+            return;
+        }
+        computeEncodingStatistics(bufInfos);
+        decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+        VpxDecodingStatistics statisticsSync = computeDecodingStatistics(
+                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                params.frameWidth, params.frameHeight);
+
+        // Check PSNR difference.
+        Log.d(TAG, "PSNR Average: Async: " + statisticsAsync.mAveragePSNR +
+                ". Sync: " + statisticsSync.mAveragePSNR);
+        Log.d(TAG, "PSNR Minimum: Async: " + statisticsAsync.mMinimumPSNR +
+                ". Sync: " + statisticsSync.mMinimumPSNR);
+        if ((Math.abs(statisticsAsync.mAveragePSNR - statisticsSync.mAveragePSNR) >
+            MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE) ||
+            (Math.abs(statisticsAsync.mMinimumPSNR - statisticsSync.mMinimumPSNR) >
+            MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE)) {
+            throw new RuntimeException("Difference between PSNRs for async and sync encoders");
+        }
+    }
+
+    /**
+     * Check if MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME is honored.
+     *
+     * Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
+     * The test does not verify the output stream.
+     */
+    private void internalTestSyncFrame(String codecMimeType) throws Exception {
+        int encodeSeconds = 9;
+
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                codecMimeType,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                true);
+        params.syncFrameInterval = encodeSeconds * FPS;
+        params.syncForceFrameInterval = FPS;
+        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+        if (bufInfo == null) {
+            Log.i(TAG, "SKIPPING testSyncFrame(): no suitable encoder found");
+            return;
+        }
+
+        VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+
+        // First check if we got expected number of key frames.
+        int actualKeyFrames = statistics.mKeyFrames.size();
+        if (actualKeyFrames != encodeSeconds) {
+            throw new RuntimeException("Number of key frames " + actualKeyFrames +
+                    " is different from the expected " + encodeSeconds);
+        }
+
+        // Check key frame intervals:
+        // Average value should be within +/- 1 frame of the target value,
+        // maximum value should not be greater than target value + 3,
+        // and minimum value should not be less that target value - 3.
+        if (Math.abs(statistics.mAverageKeyFrameInterval - FPS) >
+            MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION ||
+            (statistics.mMaximumKeyFrameInterval - FPS > MAX_KEYFRAME_INTERVAL_VARIATION) ||
+            (FPS - statistics.mMinimumKeyFrameInterval > MAX_KEYFRAME_INTERVAL_VARIATION)) {
+            throw new RuntimeException(
+                    "Key frame intervals are different from the expected " + FPS);
+        }
+    }
+
+    /**
+     * Check if MediaCodec.PARAMETER_KEY_VIDEO_BITRATE is honored.
+     *
+     * Run the the encoder for 12 seconds. Request changes to the
+     * bitrate after 6 seconds and ensure the encoder responds.
+     */
+    private void internalTestDynamicBitrateChange(String codecMimeType) throws Exception {
+        int encodeSeconds = 12;    // Encoding sequence duration in seconds.
+        int[] bitrateTargetValues = { 400000, 800000 };  // List of bitrates to test.
+
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                codecMimeType,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                bitrateTargetValues[0],
+                true);
+
+        // Number of seconds for each bitrate
+        int stepSeconds = encodeSeconds / bitrateTargetValues.length;
+        // Fill the bitrates values.
+        params.bitrateSet = new int[encodeSeconds * FPS];
+        for (int i = 0; i < bitrateTargetValues.length ; i++) {
+            Arrays.fill(params.bitrateSet,
+                    i * encodeSeconds * FPS / bitrateTargetValues.length,
+                    (i + 1) * encodeSeconds * FPS / bitrateTargetValues.length,
+                    bitrateTargetValues[i]);
+        }
+
+        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+        if (bufInfo == null) {
+            Log.i(TAG, "SKIPPING testDynamicBitrateChange(): no suitable encoder found");
+            return;
+        }
+
+        VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+
+        // Calculate actual average bitrates  for every [stepSeconds] second.
+        int[] bitrateActualValues = new int[bitrateTargetValues.length];
+        for (int i = 0; i < bitrateTargetValues.length ; i++) {
+            bitrateActualValues[i] = 0;
+            for (int j = i * stepSeconds; j < (i + 1) * stepSeconds; j++) {
+                bitrateActualValues[i] += statistics.mBitrates.get(j);
+            }
+            bitrateActualValues[i] /= stepSeconds;
+            Log.d(TAG, "Actual bitrate for interval #" + i + " : " + bitrateActualValues[i] +
+                    ". Target: " + bitrateTargetValues[i]);
+
+            // Compare actual bitrate values to make sure at least same increasing/decreasing
+            // order as the target bitrate values.
+            for (int j = 0; j < i; j++) {
+                long differenceTarget = bitrateTargetValues[i] - bitrateTargetValues[j];
+                long differenceActual = bitrateActualValues[i] - bitrateActualValues[j];
+                if (differenceTarget * differenceActual < 0) {
+                    throw new RuntimeException("Target bitrates: " +
+                            bitrateTargetValues[j] + " , " + bitrateTargetValues[i] +
+                            ". Actual bitrates: "
+                            + bitrateActualValues[j] + " , " + bitrateActualValues[i]);
+                }
+            }
+        }
+    }
+
+     /**
+      * Check if encoder and decoder can run simultaneously on different threads.
+      *
+      * Encodes and decodes 9 seconds of raw stream sequentially in CBR mode,
+      * and then run parallel encoding and decoding of the same streams.
+      * Compares average bitrate and PSNR for sequential and parallel runs.
+      */
+     private void internalTestParallelEncodingAndDecoding(String codecMimeType) throws Exception {
+         // check for encoder up front, as by the time we detect lack of
+         // encoder support, we may have already started decoding.
+         MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+         MediaFormat format = MediaFormat.createVideoFormat(codecMimeType, WIDTH, HEIGHT);
+         if (mcl.findEncoderForFormat(format) == null) {
+             Log.i(TAG, "SKIPPING testParallelEncodingAndDecoding(): no suitable encoder found");
+             return;
+         }
+
+         int encodeSeconds = 9;
+         final int[] bitrate = new int[1];
+         final double[] psnr = new double[1];
+         final Exception[] exceptionEncoder = new Exception[1];
+         final Exception[] exceptionDecoder = new Exception[1];
+         final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                 INPUT_YUV,
+                 ENCODED_IVF_BASE,
+                 codecMimeType,
+                 encodeSeconds,
+                 WIDTH,
+                 HEIGHT,
+                 FPS,
+                 VIDEO_ControlRateConstant,
+                 BITRATE,
+                 true);
+         final String inputIvfFilename = params.outputIvfFilename;
+
+         Runnable runEncoder = new Runnable() {
+             public void run() {
+                 try {
+                     ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+                     VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+                     bitrate[0] = statistics.mAverageBitrate;
+                 } catch (Exception e) {
+                     Log.e(TAG, "Encoder error: " + e.toString());
+                     exceptionEncoder[0] = e;
+                 }
+             }
+         };
+         Runnable runDecoder = new Runnable() {
+             public void run() {
+                 try {
+                     decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+                     VpxDecodingStatistics statistics = computeDecodingStatistics(
+                            params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                            params.frameWidth, params.frameHeight);
+                     psnr[0] = statistics.mAveragePSNR;
+                 } catch (Exception e) {
+                     Log.e(TAG, "Decoder error: " + e.toString());
+                     exceptionDecoder[0] = e;
+                 }
+             }
+         };
+
+         // Sequential encoding and decoding.
+         runEncoder.run();
+         if (exceptionEncoder[0] != null) {
+             throw exceptionEncoder[0];
+         }
+         int referenceBitrate = bitrate[0];
+         runDecoder.run();
+         if (exceptionDecoder[0] != null) {
+             throw exceptionDecoder[0];
+         }
+         double referencePsnr = psnr[0];
+
+         // Parallel encoding and decoding.
+         params.outputIvfFilename = SDCARD_DIR + File.separator + ENCODED_IVF_BASE + "_copy.ivf";
+         Thread threadEncoder = new Thread(runEncoder);
+         Thread threadDecoder = new Thread(runDecoder);
+         threadEncoder.start();
+         threadDecoder.start();
+         threadEncoder.join();
+         threadDecoder.join();
+         if (exceptionEncoder[0] != null) {
+             throw exceptionEncoder[0];
+         }
+         if (exceptionDecoder[0] != null) {
+             throw exceptionDecoder[0];
+         }
+
+         // Compare bitrates and PSNRs for sequential and parallel cases.
+         Log.d(TAG, "Sequential bitrate: " + referenceBitrate + ". PSNR: " + referencePsnr);
+         Log.d(TAG, "Parallel bitrate: " + bitrate[0] + ". PSNR: " + psnr[0]);
+         assertEquals("Bitrate for sequenatial encoding" + referenceBitrate +
+                 " is different from parallel encoding " + bitrate[0],
+                 referenceBitrate, bitrate[0], MAX_BITRATE_VARIATION * referenceBitrate);
+         assertEquals("PSNR for sequenatial encoding" + referencePsnr +
+                 " is different from parallel encoding " + psnr[0],
+                 referencePsnr, psnr[0], MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE);
+     }
+
+
+    /**
+     * Check the encoder quality for various bitrates by calculating PSNR
+     *
+     * Run the the encoder for 9 seconds for each bitrate and calculate PSNR
+     * for each encoded stream.
+     * Video streams with higher bitrates should have higher PSNRs.
+     * Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
+     */
+    private void internalTestEncoderQuality(String codecMimeType) throws Exception {
+        int encodeSeconds = 9;      // Encoding sequence duration in seconds for each bitrate.
+        double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
+        double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
+        boolean[] completed = new boolean[TEST_BITRATES_SET.length];
+        boolean skipped = true;
+
+        // Run platform specific encoder for different bitrates
+        // and compare PSNR of codec with PSNR of reference Google codec.
+        for (int i = 0; i < TEST_BITRATES_SET.length; i++) {
+            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                    INPUT_YUV,
+                    ENCODED_IVF_BASE,
+                    codecMimeType,
+                    encodeSeconds,
+                    WIDTH,
+                    HEIGHT,
+                    FPS,
+                    BITRATE_MODE,
+                    TEST_BITRATES_SET[i],
+                    true);
+            if (encode(params) == null) {
+                // parameters not supported, try other bitrates
+                completed[i] = false;
+                continue;
+            }
+            completed[i] = true;
+            skipped = false;
+
+            decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+            VpxDecodingStatistics statistics = computeDecodingStatistics(
+                    params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                    params.frameWidth, params.frameHeight);
+            psnrPlatformCodecAverage[i] = statistics.mAveragePSNR;
+            psnrPlatformCodecMin[i] = statistics.mMinimumPSNR;
+        }
+
+        if (skipped) {
+            Log.i(TAG, "SKIPPING testEncoderQuality(): no bitrates supported");
+            return;
+        }
+
+        // First do a sanity check - higher bitrates should results in higher PSNR.
+        for (int i = 1; i < TEST_BITRATES_SET.length ; i++) {
+            if (!completed[i]) {
+                continue;
+            }
+            for (int j = 0; j < i; j++) {
+                if (!completed[j]) {
+                    continue;
+                }
+                double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
+                double differencePSNR = psnrPlatformCodecAverage[i] - psnrPlatformCodecAverage[j];
+                if (differenceBitrate * differencePSNR < 0) {
+                    throw new RuntimeException("Target bitrates: " +
+                            TEST_BITRATES_SET[j] + ", " + TEST_BITRATES_SET[i] +
+                            ". Actual PSNRs: "
+                            + psnrPlatformCodecAverage[j] + ", " + psnrPlatformCodecAverage[i]);
+                }
+            }
+        }
+
+        // Then compare average and minimum PSNR of platform codec with reference Google codec -
+        // average PSNR for platform codec should be no more than 2 dB less than reference PSNR
+        // and minumum PSNR - no more than 4 dB less than reference minimum PSNR.
+        // These PSNR difference numbers are arbitrary for now, will need further estimation
+        // when more devices with HW VP8 codec will appear.
+        for (int i = 0; i < TEST_BITRATES_SET.length ; i++) {
+            if (!completed[i]) {
+                continue;
+            }
+
+            Log.d(TAG, "Bitrate " + TEST_BITRATES_SET[i]);
+            Log.d(TAG, "Reference: Average: " + REFERENCE_AVERAGE_PSNR[i] + ". Minimum: " +
+                    REFERENCE_MINIMUM_PSNR[i]);
+            Log.d(TAG, "Platform:  Average: " + psnrPlatformCodecAverage[i] + ". Minimum: " +
+                    psnrPlatformCodecMin[i]);
+            if (psnrPlatformCodecAverage[i] < REFERENCE_AVERAGE_PSNR[i] -
+                    MAX_AVERAGE_PSNR_DIFFERENCE) {
+                throw new RuntimeException("Low average PSNR " + psnrPlatformCodecAverage[i] +
+                        " comparing to reference PSNR " + REFERENCE_AVERAGE_PSNR[i] +
+                        " for bitrate " + TEST_BITRATES_SET[i]);
+            }
+            if (psnrPlatformCodecMin[i] < REFERENCE_MINIMUM_PSNR[i] -
+                    MAX_MINIMUM_PSNR_DIFFERENCE) {
+                throw new RuntimeException("Low minimum PSNR " + psnrPlatformCodecMin[i] +
+                        " comparing to reference PSNR " + REFERENCE_MINIMUM_PSNR[i] +
+                        " for bitrate " + TEST_BITRATES_SET[i]);
+            }
+        }
+    }
+
+    public void testBasicVP8() throws Exception { internalTestBasic(VP8_MIME); }
+    public void testBasicVP9() throws Exception { internalTestBasic(VP9_MIME); }
+
+    public void testAsyncEncodingVP8() throws Exception { internalTestAsyncEncoding(VP8_MIME); }
+    public void testAsyncEncodingVP9() throws Exception { internalTestAsyncEncoding(VP9_MIME); }
+
+    public void testSyncFrameVP8() throws Exception { internalTestSyncFrame(VP8_MIME); }
+    public void testSyncFrameVP9() throws Exception { internalTestSyncFrame(VP9_MIME); }
+
+    public void testDynamicBitrateChangeVP8() throws Exception {
+        internalTestDynamicBitrateChange(VP8_MIME);
+    }
+    public void testDynamicBitrateChangeVP9() throws Exception {
+        internalTestDynamicBitrateChange(VP9_MIME);
+    }
+
+    public void testParallelEncodingAndDecodingVP8() throws Exception {
+        internalTestParallelEncodingAndDecoding(VP8_MIME);
+    }
+    public void testParallelEncodingAndDecodingVP9() throws Exception {
+        internalTestParallelEncodingAndDecoding(VP9_MIME);
+    }
+
+    public void testEncoderQualityVP8() throws Exception { internalTestEncoderQuality(VP8_MIME); }
+    public void testEncoderQualityVP9() throws Exception { internalTestEncoderQuality(VP9_MIME); }
+
+}
+
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index bbee284..7ba9a5a 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctsdeviceutil ctstestrunner guava platform-test-annotations
+    ctsdeviceutil ctstestrunner guava platform-test-annotations android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index e01f386..b77f617 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -18,8 +18,8 @@
 */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android" coreApp="true" android:sharedUserId="android.uid.system"
-          android:sharedUserLabel="@string/android_system_label">
+    package="android" coreApp="true" android:sharedUserId="android.uid.system"
+    android:sharedUserLabel="@string/android_system_label">
 
     <!-- ================================================ -->
     <!-- Special broadcasts that only the system can send -->
@@ -138,49 +138,46 @@
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
     <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
-    <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+        android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+        android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+        android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+        android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+        android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
     <protected-broadcast
-            android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+        android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+        android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+        android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
     <protected-broadcast
-            android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+        android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
     <protected-broadcast
-            android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
-    <protected-broadcast
-            android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+        android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
     <protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
     <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
@@ -192,7 +189,6 @@
     <protected-broadcast android:name="android.btopp.intent.action.RETRY" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN" />
     <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
-    <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
@@ -307,7 +303,7 @@
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
 
-    <protected-broadcast android:name="com.android.server.ACTION_TRIGGER_IDLE" />
+    <protected-broadcast android:name="com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE" />
 
     <protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
 
@@ -324,11 +320,11 @@
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
 
     <protected-broadcast
-            android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+        android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
 
     <!-- Defined in RestrictionsManager -->
     <protected-broadcast
-            android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+        android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
     <!-- Defined in RestrictionsManager -->
 
     <protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
@@ -487,28 +483,28 @@
     <!-- Used for runtime permissions related to contacts and profiles on this
         device. -->
     <permission-group android:name="android.permission-group.CONTACTS"
-                      android:icon="@drawable/perm_group_contacts"
-                      android:label="@string/permgrouplab_contacts"
-                      android:description="@string/permgroupdesc_contacts"
-                      android:priority="100" />
+        android:icon="@drawable/perm_group_contacts"
+        android:label="@string/permgrouplab_contacts"
+        android:description="@string/permgroupdesc_contacts"
+        android:priority="100" />
 
     <!-- Allows an application to read the user's contacts data.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CONTACTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:label="@string/permlab_readContacts"
-                android:description="@string/permdesc_readContacts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:label="@string/permlab_readContacts"
+        android:description="@string/permdesc_readContacts"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's contacts data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CONTACTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:label="@string/permlab_writeContacts"
-                android:description="@string/permdesc_writeContacts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:label="@string/permlab_writeContacts"
+        android:description="@string/permdesc_writeContacts"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing user's calendar                              -->
@@ -517,28 +513,28 @@
 
     <!-- Used for runtime permissions related to user's calendar. -->
     <permission-group android:name="android.permission-group.CALENDAR"
-                      android:icon="@drawable/perm_group_calendar"
-                      android:label="@string/permgrouplab_calendar"
-                      android:description="@string/permgroupdesc_calendar"
-                      android:priority="200" />
+        android:icon="@drawable/perm_group_calendar"
+        android:label="@string/permgrouplab_calendar"
+        android:description="@string/permgroupdesc_calendar"
+        android:priority="200" />
 
     <!-- Allows an application to read the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALENDAR"
-                android:permissionGroup="android.permission-group.CALENDAR"
-                android:label="@string/permlab_readCalendar"
-                android:description="@string/permdesc_readCalendar"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CALENDAR"
+        android:label="@string/permlab_readCalendar"
+        android:description="@string/permdesc_readCalendar"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALENDAR"
-                android:permissionGroup="android.permission-group.CALENDAR"
-                android:label="@string/permlab_writeCalendar"
-                android:description="@string/permdesc_writeCalendar"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CALENDAR"
+        android:label="@string/permlab_writeCalendar"
+        android:description="@string/permdesc_writeCalendar"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing and modifying user's SMS messages            -->
@@ -547,56 +543,56 @@
 
     <!-- Used for runtime permissions related to user's SMS messages. -->
     <permission-group android:name="android.permission-group.SMS"
-                      android:icon="@drawable/perm_group_sms"
-                      android:label="@string/permgrouplab_sms"
-                      android:description="@string/permgroupdesc_sms"
-                      android:priority="300" />
+        android:icon="@drawable/perm_group_sms"
+        android:label="@string/permgrouplab_sms"
+        android:description="@string/permgroupdesc_sms"
+        android:priority="300" />
 
     <!-- Allows an application to send SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.SEND_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_sendSms"
-                android:description="@string/permdesc_sendSms"
-                android:permissionFlags="costsMoney"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_sendSms"
+        android:description="@string/permdesc_sendSms"
+        android:permissionFlags="costsMoney"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveSms"
-                android:description="@string/permdesc_receiveSms"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveSms"
+        android:description="@string/permdesc_receiveSms"
+        android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to read SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_SMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_readSms"
-                android:description="@string/permdesc_readSms"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_readSms"
+        android:description="@string/permdesc_readSms"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive WAP push messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_WAP_PUSH"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveWapPush"
-                android:description="@string/permdesc_receiveWapPush"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveWapPush"
+        android:description="@string/permdesc_receiveWapPush"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to monitor incoming MMS messages.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_MMS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_receiveMms"
-                android:description="@string/permdesc_receiveMms"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_receiveMms"
+        android:description="@string/permdesc_receiveMms"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
@@ -611,10 +607,10 @@
          <p>Protection level: dangerous
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_CELL_BROADCASTS"
-                android:permissionGroup="android.permission-group.SMS"
-                android:label="@string/permlab_readCellBroadcasts"
-                android:description="@string/permdesc_readCellBroadcasts"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SMS"
+        android:label="@string/permlab_readCellBroadcasts"
+        android:description="@string/permdesc_readCellBroadcasts"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing external storage                             -->
@@ -623,10 +619,10 @@
 
     <!-- Used for runtime permissions related to the shared external storage. -->
     <permission-group android:name="android.permission-group.STORAGE"
-                      android:icon="@drawable/perm_group_storage"
-                      android:label="@string/permgrouplab_storage"
-                      android:description="@string/permgroupdesc_storage"
-                      android:priority="900" />
+        android:icon="@drawable/perm_group_storage"
+        android:label="@string/permgrouplab_storage"
+        android:description="@string/permgroupdesc_storage"
+        android:priority="900" />
 
     <!-- Allows an application to read from external storage.
      <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
@@ -651,10 +647,10 @@
      <p>Protection level: dangerous
      -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-                android:permissionGroup="android.permission-group.STORAGE"
-                android:label="@string/permlab_sdcardRead"
-                android:description="@string/permdesc_sdcardRead"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardRead"
+        android:description="@string/permdesc_sdcardRead"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write to external storage.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -672,10 +668,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-                android:permissionGroup="android.permission-group.STORAGE"
-                android:label="@string/permlab_sdcardWrite"
-                android:description="@string/permdesc_sdcardWrite"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardWrite"
+        android:description="@string/permdesc_sdcardWrite"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device location                          -->
@@ -684,28 +680,28 @@
 
     <!-- Used for permissions that allow accessing the device location. -->
     <permission-group android:name="android.permission-group.LOCATION"
-                      android:icon="@drawable/perm_group_location"
-                      android:label="@string/permgrouplab_location"
-                      android:description="@string/permgroupdesc_location"
-                      android:priority="400" />
+        android:icon="@drawable/perm_group_location"
+        android:label="@string/permgrouplab_location"
+        android:description="@string/permgroupdesc_location"
+        android:priority="400" />
 
     <!-- Allows an app to access precise location.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
-                android:permissionGroup="android.permission-group.LOCATION"
-                android:label="@string/permlab_accessFineLocation"
-                android:description="@string/permdesc_accessFineLocation"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessFineLocation"
+        android:description="@string/permdesc_accessFineLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an app to access approximate location.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
-                android:permissionGroup="android.permission-group.LOCATION"
-                android:label="@string/permlab_accessCoarseLocation"
-                android:description="@string/permdesc_accessCoarseLocation"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessCoarseLocation"
+        android:description="@string/permdesc_accessCoarseLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device telephony                         -->
@@ -714,10 +710,10 @@
 
     <!-- Used for permissions that are associated telephony features. -->
     <permission-group android:name="android.permission-group.PHONE"
-                      android:icon="@drawable/perm_group_phone_calls"
-                      android:label="@string/permgrouplab_phone"
-                      android:description="@string/permgroupdesc_phone"
-                      android:priority="500" />
+        android:icon="@drawable/perm_group_phone_calls"
+        android:label="@string/permgrouplab_phone"
+        android:description="@string/permgroupdesc_phone"
+        android:priority="500" />
 
     <!-- Allows read only access to phone state, including the phone number of the device,
          current cellular network information, the status of any ongoing calls, and a list of any
@@ -733,21 +729,21 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_PHONE_STATE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_readPhoneState"
-                android:description="@string/permdesc_readPhoneState"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_readPhoneState"
+        android:description="@string/permdesc_readPhoneState"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to initiate a phone call without going through
         the Dialer user interface for the user to confirm the call.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CALL_PHONE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:permissionFlags="costsMoney"
-                android:label="@string/permlab_callPhone"
-                android:description="@string/permdesc_callPhone"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:permissionFlags="costsMoney"
+        android:label="@string/permlab_callPhone"
+        android:description="@string/permdesc_callPhone"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to access the IMS call service: making and
          modifying a call
@@ -755,10 +751,10 @@
         @hide
     -->
     <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_accessImsCallService"
-                android:description="@string/permdesc_accessImsCallService"
-                android:protectionLevel="signature|privileged" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_accessImsCallService"
+        android:description="@string/permdesc_accessImsCallService"
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read the user's call log.
          <p class="note"><strong>Note:</strong> If your app uses the
@@ -773,10 +769,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALL_LOG"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_readCallLog"
-                android:description="@string/permdesc_readCallLog"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_readCallLog"
+        android:description="@string/permdesc_readCallLog"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write (but not read) the user's
          call log data.
@@ -792,28 +788,28 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_writeCallLog"
-                android:description="@string/permdesc_writeCallLog"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_writeCallLog"
+        android:description="@string/permdesc_writeCallLog"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to add voicemails into the system.
          <p>Protection level: dangerous
     -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_addVoicemail"
-                android:description="@string/permdesc_addVoicemail"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_addVoicemail"
+        android:description="@string/permdesc_addVoicemail"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an application to use SIP service.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.USE_SIP"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:description="@string/permdesc_use_sip"
-                android:label="@string/permlab_use_sip"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:description="@string/permdesc_use_sip"
+        android:label="@string/permlab_use_sip"
+        android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to see the number being dialed during an outgoing
          call with the option to redirect the call to a different number or
@@ -821,10 +817,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:label="@string/permlab_processOutgoingCalls"
-                android:description="@string/permdesc_processOutgoingCalls"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_processOutgoingCalls"
+        android:description="@string/permdesc_processOutgoingCalls"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
@@ -835,19 +831,19 @@
          microphone audio from the device. Note that phone calls also capture audio
          but are in a separate (more visible) permission group. -->
     <permission-group android:name="android.permission-group.MICROPHONE"
-                      android:icon="@drawable/perm_group_microphone"
-                      android:label="@string/permgrouplab_microphone"
-                      android:description="@string/permgroupdesc_microphone"
-                      android:priority="600" />
+        android:icon="@drawable/perm_group_microphone"
+        android:label="@string/permgrouplab_microphone"
+        android:description="@string/permgroupdesc_microphone"
+        android:priority="600" />
 
     <!-- Allows an application to record audio.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECORD_AUDIO"
-                android:permissionGroup="android.permission-group.MICROPHONE"
-                android:label="@string/permlab_recordAudio"
-                android:description="@string/permdesc_recordAudio"
-                android:protectionLevel="dangerous"/>
+        android:permissionGroup="android.permission-group.MICROPHONE"
+        android:label="@string/permlab_recordAudio"
+        android:description="@string/permdesc_recordAudio"
+        android:protectionLevel="dangerous"/>
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the UCE Service                              -->
@@ -857,15 +853,15 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:protectionLevel="signatureOrSystem"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:protectionLevel="signatureOrSystem"/>
 
     <!-- @hide Allows an application to Access UCE-OPTIONS.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
-                android:permissionGroup="android.permission-group.PHONE"
-                android:protectionLevel="signatureOrSystem"/>
+        android:permissionGroup="android.permission-group.PHONE"
+        android:protectionLevel="signatureOrSystem"/>
 
 
 
@@ -877,10 +873,10 @@
     <!-- Used for permissions that are associated with accessing
      camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.CAMERA"
-                      android:icon="@drawable/perm_group_camera"
-                      android:label="@string/permgrouplab_camera"
-                      android:description="@string/permgroupdesc_camera"
-                      android:priority="700" />
+        android:icon="@drawable/perm_group_camera"
+        android:label="@string/permgrouplab_camera"
+        android:description="@string/permgroupdesc_camera"
+        android:priority="700" />
 
     <!-- Required to be able to access the camera device.
          <p>This will automatically enforce the <a
@@ -892,10 +888,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CAMERA"
-                android:permissionGroup="android.permission-group.CAMERA"
-                android:label="@string/permlab_camera"
-                android:description="@string/permdesc_camera"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.CAMERA"
+        android:label="@string/permlab_camera"
+        android:description="@string/permdesc_camera"
+        android:protectionLevel="dangerous" />
 
 
     <!-- ====================================================================== -->
@@ -906,28 +902,28 @@
     <!-- Used for permissions that are associated with accessing
          camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.SENSORS"
-                      android:icon="@drawable/perm_group_sensors"
-                      android:label="@string/permgrouplab_sensors"
-                      android:description="@string/permgroupdesc_sensors"
-                      android:priority="800" />
+        android:icon="@drawable/perm_group_sensors"
+        android:label="@string/permgrouplab_sensors"
+        android:description="@string/permgroupdesc_sensors"
+        android:priority="800" />
 
     <!-- Allows an application to access data from sensors that the user uses to
          measure what is happening inside his/her body, such as heart rate.
          <p>Protection level: dangerous -->
     <permission android:name="android.permission.BODY_SENSORS"
-                android:permissionGroup="android.permission-group.SENSORS"
-                android:label="@string/permlab_bodySensors"
-                android:description="@string/permdesc_bodySensors"
-                android:protectionLevel="dangerous" />
+        android:permissionGroup="android.permission-group.SENSORS"
+        android:label="@string/permlab_bodySensors"
+        android:description="@string/permdesc_bodySensors"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an app to use fingerprint hardware.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.USE_FINGERPRINT"
-                android:permissionGroup="android.permission-group.SENSORS"
-                android:label="@string/permlab_useFingerprint"
-                android:description="@string/permdesc_useFingerprint"
-                android:protectionLevel="normal" />
+        android:permissionGroup="android.permission-group.SENSORS"
+        android:label="@string/permlab_useFingerprint"
+        android:description="@string/permdesc_useFingerprint"
+        android:protectionLevel="normal" />
 
     <!-- ====================================================================== -->
     <!-- REMOVED PERMISSIONS                                                    -->
@@ -935,78 +931,78 @@
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_PROFILE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_PROFILE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_SOCIAL_STREAM"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_USER_DICTIONARY"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SMS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.MANAGE_ACCOUNTS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.USE_CREDENTIALS"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.FLASHLIGHT"
-                android:protectionLevel="normal"
-                android:permissionFlags="removed"/>
+        android:protectionLevel="normal"
+        android:permissionFlags="removed"/>
 
     <!-- ====================================================================== -->
     <!-- INSTALL PERMISSIONS                                                    -->
@@ -1021,37 +1017,35 @@
          to handle the respond-via-message action during incoming calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
-         <p>Not for use by third-party applications.
-         @hide -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to filter carrier specific sms.
          @hide -->
     <permission android:name="android.permission.CARRIER_FILTER_SMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
          to record or display them to the user.
-         <p>Not for use by third-party applications.
-         @hide -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
          or perform processing on them. -->
     <!-- @hide -->
     <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to execute contacts directory search.
          This should only be used by ContactsProvider.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
          <p>Not for use by third-party applications. -->
@@ -1067,9 +1061,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.alarm.permission.SET_ALARM"
-                android:label="@string/permlab_setAlarm"
-                android:description="@string/permdesc_setAlarm"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setAlarm"
+        android:description="@string/permdesc_setAlarm"
+        android:protectionLevel="normal" />
 
     <!-- =============================================================== -->
     <!-- Permissions for accessing the user voicemail                    -->
@@ -1080,13 +1074,13 @@
         <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read voicemails in the system.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
@@ -1097,26 +1091,26 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
-                android:label="@string/permlab_accessLocationExtraCommands"
-                android:description="@string/permdesc_accessLocationExtraCommands"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_accessLocationExtraCommands"
+        android:description="@string/permdesc_accessLocationExtraCommands"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install a location provider into the Location Manager.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
          This should only be used by HDMI-CEC service.
     -->
     <permission android:name="android.permission.HDMI_CEC"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use location features in hardware,
          such as the geofencing api.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.LOCATION_HARDWARE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
 
     <!-- @SystemApi Allows an application to create mock location providers for testing.
@@ -1124,7 +1118,7 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing networks -->
@@ -1135,73 +1129,73 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.INTERNET"
-                android:description="@string/permdesc_createNetworkSockets"
-                android:label="@string/permlab_createNetworkSockets"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_createNetworkSockets"
+        android:label="@string/permlab_createNetworkSockets"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to access information about networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NETWORK_STATE"
-                android:description="@string/permdesc_accessNetworkState"
-                android:label="@string/permlab_accessNetworkState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessNetworkState"
+        android:label="@string/permlab_accessNetworkState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to access information about Wi-Fi networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_WIFI_STATE"
-                android:description="@string/permdesc_accessWifiState"
-                android:label="@string/permlab_accessWifiState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessWifiState"
+        android:label="@string/permlab_accessWifiState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to change Wi-Fi connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_STATE"
-                android:description="@string/permdesc_changeWifiState"
-                android:label="@string/permlab_changeWifiState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWifiState"
+        android:label="@string/permlab_changeWifiState"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows applications to change tether state and run
          tether carrier provisioning.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.TETHER_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allow system apps to receive broadcast
          when a wifi network credential is changed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
      by another application. Once reconfigured the original creator cannot make any further
      modifications.
      <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.ACCESS_WIMAX_STATE"
-                android:description="@string/permdesc_accessWimaxState"
-                android:label="@string/permlab_accessWimaxState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_accessWimaxState"
+        android:label="@string/permlab_accessWimaxState"
+        android:protectionLevel="normal" />
 
     <!-- @hide -->
     <permission android:name="android.permission.CHANGE_WIMAX_STATE"
-                android:description="@string/permdesc_changeWimaxState"
-                android:label="@string/permlab_changeWimaxState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWimaxState"
+        android:label="@string/permlab_changeWimaxState"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to act as network scorers. @hide @SystemApi-->
     <permission android:name="android.permission.SCORE_NETWORKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
@@ -1212,68 +1206,68 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH"
-                android:description="@string/permdesc_bluetooth"
-                android:label="@string/permlab_bluetooth"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_bluetooth"
+        android:label="@string/permlab_bluetooth"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to discover and pair bluetooth devices.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
-                android:description="@string/permdesc_bluetoothAdmin"
-                android:label="@string/permlab_bluetoothAdmin"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_bluetoothAdmin"
+        android:label="@string/permlab_bluetoothAdmin"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
          allow or disallow phonebook access or message access.
          This is not available to third party applications. -->
     <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Control access to email providers exclusively for Bluetooth
          @hide
     -->
     <permission android:name="android.permission.BLUETOOTH_MAP"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows bluetooth stack to access files
          @hide This should only be used by Bluetooth apk.
     -->
     <permission android:name="android.permission.BLUETOOTH_STACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows applications to perform I/O operations over NFC.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC"
-                android:description="@string/permdesc_nfc"
-                android:label="@string/permlab_nfc"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_nfc"
+        android:label="@string/permlab_nfc"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows a system application to access hardware packet offload capabilities.
          @hide -->
     <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          @hide -->
     <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
          @hide -->
     <permission android:name="android.permission.LOOP_RADIO"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
          @hide -->
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
@@ -1292,15 +1286,15 @@
     <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
-                android:permissionGroup="android.permission-group.CONTACTS"
-                android:protectionLevel="dangerous"
-                android:description="@string/permdesc_getAccounts"
-                android:label="@string/permlab_getAccounts" />
+        android:permissionGroup="android.permission-group.CONTACTS"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_getAccounts"
+        android:label="@string/permlab_getAccounts" />
 
     <!-- @SystemApi Allows applications to call into AccountAuthenticators.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCOUNT_MANAGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware that may effect battery life-->
@@ -1311,34 +1305,34 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
-                android:description="@string/permdesc_changeWifiMulticastState"
-                android:label="@string/permlab_changeWifiMulticastState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeWifiMulticastState"
+        android:label="@string/permlab_changeWifiMulticastState"
+        android:protectionLevel="normal" />
 
     <!-- Allows access to the vibrator.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.VIBRATE"
-                android:label="@string/permlab_vibrate"
-                android:description="@string/permdesc_vibrate"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_vibrate"
+        android:description="@string/permdesc_vibrate"
+        android:protectionLevel="normal" />
 
     <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
          from dimming.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WAKE_LOCK"
-                android:label="@string/permlab_wakeLock"
-                android:description="@string/permdesc_wakeLock"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_wakeLock"
+        android:description="@string/permdesc_wakeLock"
+        android:protectionLevel="normal" />
 
     <!-- Allows using the device's IR transmitter, if available.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.TRANSMIT_IR"
-                android:label="@string/permlab_transmitIr"
-                android:description="@string/permdesc_transmitIr"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_transmitIr"
+        android:description="@string/permdesc_transmitIr"
+        android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing audio settings   -->
@@ -1349,9 +1343,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
-                android:label="@string/permlab_modifyAudioSettings"
-                android:description="@string/permdesc_modifyAudioSettings"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_modifyAudioSettings"
+        android:description="@string/permdesc_modifyAudioSettings"
+        android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
@@ -1361,68 +1355,68 @@
     <!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
          @hide -->
     <permission android:name="android.permission.MANAGE_USB"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to access the MTP USB kernel driver.
          For use only by the device side MTP implementation.
          @hide -->
     <permission android:name="android.permission.ACCESS_MTP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to hardware peripherals.  Intended only for hardware testing.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.HARDWARE_TEST"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows access to FM
          @hide This is not a third-party API (intended for system apps).-->
     <permission android:name="android.permission.ACCESS_FM_RADIO"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows access to configure network interfaces, configure/use IPSec, etc.
          @hide -->
     <permission android:name="android.permission.NET_ADMIN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows registration for remote audio playback. @hide -->
     <permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide This should only be used by OEM's TvInputService's.
     -->
     <permission android:name="android.permission.TV_INPUT_HARDWARE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows to capture a frame of TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.CAPTURE_TV_INPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows TvInputService to access DVB device.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DVB_DEVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows enabling/disabling OEM unlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OEM_UNLOCK_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows querying state of PersistentDataBlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_PDB_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows system update service to notify device owner about pending updates.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with camera and image capture -->
@@ -1433,12 +1427,12 @@
          a camera is in use by an application.
          @hide -->
     <permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending the camera service notifications about system-wide events.
         @hide -->
     <permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
@@ -1449,50 +1443,50 @@
          Does not include placing calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows read only access to precise phone state.
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read access to privileged phone state.
          @hide Used internally. -->
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
          corresponds to a device SIM.
          @hide -->
     <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CALL_PROVIDER.
          @hide -->
     <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CONNECTION_MANAGER
          @hide -->
     <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.InCallService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.CallScreeningService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_SCREENING_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
@@ -1501,24 +1495,24 @@
          @SystemApi
          @hide -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to control the in-call experience.
          @hide -->
     <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to receive STK related commands.
          @hide -->
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
@@ -1528,7 +1522,7 @@
     <!-- @SystemApi Allows an application to write to internal media storage
          @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage access to documents, usually as part
          of a document picker.
@@ -1538,14 +1532,14 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.MANAGE_DOCUMENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to cache content.
          <p>Not for use by third-party applications.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.CACHE_CONTENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
@@ -1556,9 +1550,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.DISABLE_KEYGUARD"
-                android:description="@string/permdesc_disableKeyguard"
-                android:label="@string/permlab_disableKeyguard"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_disableKeyguard"
+        android:label="@string/permlab_disableKeyguard"
+        android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions to access other installed applications  -->
@@ -1567,9 +1561,9 @@
 
     <!-- @deprecated No longer enforced. -->
     <permission android:name="android.permission.GET_TASKS"
-                android:label="@string/permlab_getTasks"
-                android:description="@string/permdesc_getTasks"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_getTasks"
+        android:description="@string/permdesc_getTasks"
+        android:protectionLevel="normal" />
 
     <!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
          give access to task information.  We need this new one because there are
@@ -1582,99 +1576,99 @@
          @hide
          @SystemApi -->
     <permission android:name="android.permission.REAL_GET_TASKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
          @hide -->
     <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
          across the users on the device, using singleton services and
          user-targeted broadcasts.  This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
          that removes restrictions on where broadcasts can be sent and allows other
          types of interactions
          @hide -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
          users on the device. This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.MANAGE_USERS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows an application to set the profile owners and the device owner.
          This permission is not available to third party applications.-->
     <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
-                android:protectionLevel="signature"
-                android:label="@string/permlab_manageProfileAndDeviceOwners"
-                android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+        android:protectionLevel="signature"
+        android:label="@string/permlab_manageProfileAndDeviceOwners"
+        android:description="@string/permdesc_manageProfileAndDeviceOwners" />
 
     <!-- Allows an application to get full detailed information about
          recently running tasks, with full fidelity to the real state.
          @hide -->
     <permission android:name="android.permission.GET_DETAILED_TASKS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to change the Z-order of tasks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REORDER_TASKS"
-                android:label="@string/permlab_reorderTasks"
-                android:description="@string/permdesc_reorderTasks"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_reorderTasks"
+        android:description="@string/permdesc_reorderTasks"
+        android:protectionLevel="normal" />
 
     <!-- @hide Allows an application to change to remove/kill tasks -->
     <permission android:name="android.permission.REMOVE_TASKS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
     <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state.
          @hide -->
     <permission android:name="android.permission.START_ANY_ACTIVITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
-                android:label="@string/permlab_killBackgroundProcesses"
-                android:description="@string/permdesc_killBackgroundProcesses"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to call
         {@link android.app.ActivityManager#killBackgroundProcesses}.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
-                android:label="@string/permlab_killBackgroundProcesses"
-                android:description="@string/permdesc_killBackgroundProcesses"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_killBackgroundProcesses"
+        android:description="@string/permdesc_killBackgroundProcesses"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows an application to query process states and current
          OOM adjustment scores.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi @hide Allows an application to retrieve a package's importance.
          This permission is not available to third party applications. -->
     <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows use of PendingIntent.getIntent().
          @hide -->
     <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the display of other applications  -->
@@ -1697,9 +1691,9 @@
          Settings.canDrawOverlays()}.
          <p>Protection level: signature -->
     <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
-                android:label="@string/permlab_systemAlertWindow"
-                android:description="@string/permdesc_systemAlertWindow"
-                android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+        android:label="@string/permlab_systemAlertWindow"
+        android:description="@string/permdesc_systemAlertWindow"
+        android:protectionLevel="signature|preinstalled|appop|pre23|development" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
@@ -1710,17 +1704,17 @@
          <p>Protection level: normal
      -->
     <permission android:name="android.permission.SET_WALLPAPER"
-                android:label="@string/permlab_setWallpaper"
-                android:description="@string/permdesc_setWallpaper"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setWallpaper"
+        android:description="@string/permdesc_setWallpaper"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to set the wallpaper hints.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.SET_WALLPAPER_HINTS"
-                android:label="@string/permlab_setWallpaperHints"
-                android:description="@string/permdesc_setWallpaperHints"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setWallpaperHints"
+        android:description="@string/permdesc_setWallpaperHints"
+        android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for changing the system clock -->
@@ -1730,15 +1724,15 @@
     <!-- @SystemApi Allows applications to set the system time.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_TIME"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to set the system time zone.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
-                android:label="@string/permlab_setTimeZone"
-                android:description="@string/permdesc_setTimeZone"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setTimeZone"
+        android:description="@string/permdesc_setTimeZone"
+        android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
@@ -1749,9 +1743,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.EXPAND_STATUS_BAR"
-                android:label="@string/permlab_expandStatusBar"
-                android:description="@string/permdesc_expandStatusBar"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_expandStatusBar"
+        android:description="@string/permdesc_expandStatusBar"
+        android:protectionLevel="normal" />
 
     <!-- ============================================================== -->
     <!-- Permissions related to adding/removing shortcuts from Launcher -->
@@ -1762,17 +1756,17 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
-                android:label="@string/permlab_install_shortcut"
-                android:description="@string/permdesc_install_shortcut"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_install_shortcut"
+        android:description="@string/permdesc_install_shortcut"
+        android:protectionLevel="normal"/>
 
     <!-- Allows an application to uninstall a shortcut in Launcher.
          <p>Protection level: normal
     -->
     <permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
-                android:label="@string/permlab_uninstall_shortcut"
-                android:description="@string/permdesc_uninstall_shortcut"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_uninstall_shortcut"
+        android:description="@string/permdesc_uninstall_shortcut"
+        android:protectionLevel="normal"/>
 
     <!-- ==================================================== -->
     <!-- Permissions related to accessing sync settings   -->
@@ -1783,25 +1777,25 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_SETTINGS"
-                android:description="@string/permdesc_readSyncSettings"
-                android:label="@string/permlab_readSyncSettings"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_readSyncSettings"
+        android:label="@string/permlab_readSyncSettings"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to write the sync settings.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
-                android:description="@string/permdesc_writeSyncSettings"
-                android:label="@string/permlab_writeSyncSettings"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_writeSyncSettings"
+        android:label="@string/permlab_writeSyncSettings"
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to read the sync stats.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_STATS"
-                android:description="@string/permdesc_readSyncStats"
-                android:label="@string/permlab_readSyncStats"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_readSyncStats"
+        android:label="@string/permlab_readSyncStats"
+        android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
@@ -1810,12 +1804,12 @@
 
     <!-- @SystemApi @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- Allows an application to read or write the system settings.
 
@@ -1830,51 +1824,51 @@
         <p>Protection level: signature
     -->
     <permission android:name="android.permission.WRITE_SETTINGS"
-                android:label="@string/permlab_writeSettings"
-                android:description="@string/permdesc_writeSettings"
-                android:protectionLevel="signature|preinstalled|appop|pre23" />
+        android:label="@string/permlab_writeSettings"
+        android:description="@string/permdesc_writeSettings"
+        android:protectionLevel="signature|preinstalled|appop|pre23" />
 
     <!-- @SystemApi Allows an application to modify the Google service map.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_GSERVICES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
     <permission android:name="android.permission.FORCE_STOP_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to retrieve the content of the active window
          An active window is the window that has fired an accessibility event. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Modify the global animation scaling factor.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ANIMATION_SCALE"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @deprecated This functionality will be removed in the future; please do
          not use. Allow an application to make its activities persistent. -->
     <permission android:name="android.permission.PERSISTENT_ACTIVITY"
-                android:label="@string/permlab_persistentActivity"
-                android:description="@string/permdesc_persistentActivity"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_persistentActivity"
+        android:description="@string/permdesc_persistentActivity"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to find out the space used by any package.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.GET_PACKAGE_SIZE"
-                android:label="@string/permlab_getPackageSize"
-                android:description="@string/permdesc_getPackageSize"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_getPackageSize"
+        android:description="@string/permdesc_getPackageSize"
+        android:protectionLevel="normal" />
 
     <!-- @deprecated No longer useful, see
          {@link android.content.pm.PackageManager#addPackageToPreferred}
          for details. -->
     <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to receive the
          {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -1890,9 +1884,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
-                android:label="@string/permlab_receiveBootCompleted"
-                android:description="@string/permdesc_receiveBootCompleted"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_receiveBootCompleted"
+        android:description="@string/permdesc_receiveBootCompleted"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to broadcast sticky intents.  These are
          broadcasts whose data is held by the system after being finished,
@@ -1901,90 +1895,90 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BROADCAST_STICKY"
-                android:label="@string/permlab_broadcastSticky"
-                android:description="@string/permdesc_broadcastSticky"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_broadcastSticky"
+        android:description="@string/permdesc_broadcastSticky"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
     <p>Not for use by third-party applications.-->
     <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows formatting file systems for removable storage.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.STORAGE_INTERNAL"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows access to ASEC non-destructive API calls
          @hide  -->
     <permission android:name="android.permission.ASEC_ACCESS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows creation of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_CREATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows destruction of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_DESTROY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows mount / unmount of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows rename of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_RENAME"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to write the apn settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_APN_SETTINGS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change network connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_NETWORK_STATE"
-                android:description="@string/permdesc_changeNetworkState"
-                android:label="@string/permlab_changeNetworkState"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_changeNetworkState"
+        android:label="@string/permlab_changeNetworkState"
+        android:protectionLevel="normal" />
 
     <!-- Allows an application to clear the caches of all installed
          applications on the device.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use any media decoder when decoding for playback
          @hide -->
     <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
          behalf of the user.
          @hide -->
     <permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to do certain operations needed for
          interacting with the recovery (system update) system.
          @hide -->
     <permission android:name="android.permission.RECOVERY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows the system to bind to an application's task services
          @hide -->
     <permission android:name="android.permission.BIND_JOB_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
 
     <!-- Allows an application to initiate configuration updates
@@ -1993,12 +1987,7 @@
          it off to the various individual installer components
          @hide -->
     <permission android:name="android.permission.UPDATE_CONFIG"
-                android:protectionLevel="signature|privileged" />
-
-    <!-- Allows the system to reset throttling in shortcut manager.
-         @hide -->
-    <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -2008,40 +1997,40 @@
     <!-- @SystemApi Allows an application to read or write the secure system settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to retrieve state dump information from system services.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DUMP"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to read the low-level system log files.
     <p>Not for use by third-party applications, because
     Log entries can contain the user's private information. -->
     <permission android:name="android.permission.READ_LOGS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Configure an application for debugging.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_DEBUG_APP"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to set the maximum number of (not needed)
          application processes that can be running.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_PROCESS_LIMIT"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control whether activities are immediately
          finished when put in the background.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ALWAYS_FINISH"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allow an application to request that a signal be sent to all persistent processes.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- ==================================== -->
     <!-- Private permissions                  -->
@@ -2050,34 +2039,34 @@
 
     <!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
     <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows but does not guarantee access to user passwords at the conclusion of add account
     @hide -->
     <permission android:name="android.permission.GET_PASSWORD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to RW to diagnostic resources.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DIAGNOSTIC"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to open, close, or disable the status bar
          and its icons.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.STATUS_BAR"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
     @hide -->
     <permission android:name="android.permission.STATUS_BAR_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to bind to third party quick settings tiles.
          <p>Should only be requested by the System, should be required by
          TileService declarations.-->
     <permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to force a BACK operation on whatever is the
          top activity.
@@ -2085,28 +2074,28 @@
          @hide
     -->
     <permission android:name="android.permission.FORCE_BACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to update device statistics.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.UPDATE_DEVICE_STATS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to collect battery statistics -->
     <permission android:name="android.permission.GET_APP_OPS_STATS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to update application operation statistics. Not for
          use by third party apps.
          @hide -->
     <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
-                android:protectionLevel="signature|privileged|installer" />
+        android:protectionLevel="signature|privileged|installer" />
 
     <!-- @SystemApi Allows an application to update the user app op restrictions.
          Not for use by third party apps.
          @hide -->
     <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi Allows an application to open windows that are for use by parts
          of the system user interface.
@@ -2114,7 +2103,7 @@
          @hide
     -->
     <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to manage (create, destroy,
          Z-order) application tokens in the window manager.
@@ -2122,17 +2111,17 @@
          @hide
     -->
     <permission android:name="android.permission.MANAGE_APP_TOKENS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows System UI to register listeners for events from Window Manager.
          @hide -->
     <permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows the application to temporarily freeze the screen for a
          full-screen transition. -->
     <permission android:name="android.permission.FREEZE_SCREEN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
          into the event stream and deliver them to ANY window.  Without this
@@ -2141,24 +2130,24 @@
          @hide
     -->
     <permission android:name="android.permission.INJECT_EVENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to register an input filter which filters the stream
          of user events (keys, touch, trackball) before they are dispatched to any window. -->
     <permission android:name="android.permission.FILTER_EVENTS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to collect frame statistics -->
     <permission android:name="android.permission.FRAME_STATS"
-                android:protectionLevel="signature" />
+         android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to temporary enable accessibility on the device. -->
     <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
@@ -2167,13 +2156,13 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ACTIVITY_WATCHER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to call the activity manager shutdown() API
          to put the higher-level system there into a shutdown state.
          @hide -->
     <permission android:name="android.permission.SHUTDOWN"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the activity manager to temporarily
          stop application switches, putting it into a special mode that
@@ -2181,7 +2170,7 @@
          critical UI such as the home screen.
          @hide -->
     <permission android:name="android.permission.STOP_APP_SWITCHES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to retrieve private information about
          the current top activity, such as any assist context it can provide.
@@ -2189,42 +2178,42 @@
          @hide
     -->
     <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to retrieve the current state of keys and
          switches.
          <p>Not for use by third-party applications.
          @deprecated The API that used this permission has been removed. -->
     <permission android:name="android.permission.READ_INPUT_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_INPUT_METHOD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.PrintService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
      to ensure that only the system can bind to it.
@@ -2233,7 +2222,7 @@
      <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
@@ -2241,65 +2230,65 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NFC_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
          that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a TextService (e.g. SpellCheckerService)
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TEXT_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.net.VpnService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VPN_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
          to ensure that only the system can bind to it.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_WALLPAPER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VOICE_INTERACTION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
          to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_REMOTE_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.media.tv.TvInputService}
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TV_INPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
@@ -2308,7 +2297,7 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required for a virtual remote controller for TV.
@@ -2316,32 +2305,32 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify parental controls
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.media.routing.MediaRouteService}
          to ensure that only the system can interact with it.
          @hide -->
     <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to add or remove another application as a device admin.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows low-level access to setting the orientation (actually
          rotation) of the screen.
@@ -2349,33 +2338,33 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ORIENTATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows low-level access to setting the pointer speed.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.SET_POINTER_SPEED"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting input device calibration.
          <p>Not for use by normal applications.
          @hide -->
     <permission android:name="android.permission.SET_INPUT_CALIBRATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting the keyboard layout.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to query tablet mode state and monitor changes
          in it.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.TABLET_MODE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to request installing packages. Apps
          targeting APIs greater than 22 must hold this permission in
@@ -2383,290 +2372,290 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
-                android:label="@string/permlab_requestInstallPackages"
-                android:description="@string/permdesc_requestInstallPackages"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_requestInstallPackages"
+        android:description="@string/permdesc_requestInstallPackages"
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install packages.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to clear user data.
          <p>Not for use by third-party applications
          @hide
     -->
     <permission android:name="android.permission.CLEAR_APP_USER_DATA"
-                android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer" />
 
     <!-- @hide Allows an application to get the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to clear the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission
-            android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
-            android:protectionLevel="signature" />
+        android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to delete cache files.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to delete packages.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DELETE_PACKAGES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to move location of installed package.
          @hide -->
     <permission android:name="android.permission.MOVE_PACKAGE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to change whether an application component (other than its own) is
          enabled or not.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to grant specific permissions.
          @hide -->
     <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+        android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
          to request certain runtime permissions to be granted at installation.
          @hide -->
     <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+        android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an application to revoke specific permissions.
         @hide -->
     <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+         android:protectionLevel="signature|installer|verifier" />
 
     <!-- @hide Allows an application to observe permission changes. -->
     <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to take screen shots and more generally
          get access to the frame buffer data.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_FRAME_BUFFER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to use InputFlinger's low level features.
          @hide -->
     <permission android:name="android.permission.ACCESS_INPUT_FLINGER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to configure and connect to Wifi displays
          @hide -->
     <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control low-level features of Wifi displays
          such as opening an RTSP socket.  This permission should only be used
          by the display manager.
          @hide -->
     <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control the color transforms applied to
          displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to control VPN.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONTROL_VPN"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.CONTROL_VPN" />
 
     <!-- @SystemApi Allows an application to capture audio output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture audio for hotword detection.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture secure video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
     <permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Required to be able to disable the device (very dangerous!).
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.BRICK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to be able to reboot the device.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.REBOOT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows low-level access to power management.
-         <p>Not for use by third-party applications.
-         @hide
-     -->
-    <permission android:name="android.permission.DEVICE_POWER"
-                android:protectionLevel="signature" />
+   <!-- @SystemApi Allows low-level access to power management.
+        <p>Not for use by third-party applications.
+        @hide
+    -->
+   <permission android:name="android.permission.DEVICE_POWER"
+        android:protectionLevel="signature" />
 
-    <!-- Allows access to the PowerManager.userActivity function.
-    <p>Not for use by third-party applications. @hide @SystemApi -->
+   <!-- Allows access to the PowerManager.userActivity function.
+   <p>Not for use by third-party applications. @hide @SystemApi -->
     <permission android:name="android.permission.USER_ACTIVITY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
-    <!-- @hide Allows low-level access to tun tap driver -->
+   <!-- @hide Allows low-level access to tun tap driver -->
     <permission android:name="android.permission.NET_TUNNELING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Run as a manufacturer test application, running as the root user.
          Only available when the device is running in manufacturer test mode.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.FACTORY_TEST"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a notification that an application
          package has been removed.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast an SMS receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_SMS"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a WAP PUSH receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_WAP_PUSH"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to broadcast privileged networking requests.
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Not for use by third-party applications. -->
     <permission android:name="android.permission.MASTER_CLEAR"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call any phone number, including emergency
          numbers, without going through the Dialer user interface for the user
          to confirm the call being placed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CALL_PRIVILEGED"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
     <permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform SIM Activation @hide -->
     <permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows enabling/disabling location update notifications from
          the radio.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read/write access to the "properties" table in the checkin
          database, to change values that get uploaded.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to collect component usage
          statistics
          <p>Declaring the permission implies intention to use the API and the user of the
          device can grant permission through the Settings application. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
-                android:protectionLevel="signature|privileged|development|appop" />
+        android:protectionLevel="signature|privileged|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @hide Allows an application to change the app idle state of an app.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
          access the network and acquire wakelocks.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Permission an application must hold in order to use
          {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
          This is a normal permission: an app requesting it will always be granted the
          permission, without the user needing to approve or see it. -->
     <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
-                android:protectionLevel="normal" />
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
-                android:protectionLevel="signature|privileged|development" />
+        android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control the backup and restore process.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.BACKUP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows a package to launch the secure full-backup confirmation UI.
          ONLY the system process may hold this permission.
          @hide -->
     <permission android:name="android.permission.CONFIRM_FULL_BACKUP"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by a {@link android.widget.RemoteViewsService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_REMOTEVIEWS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
@@ -2675,25 +2664,25 @@
          An application that has this permission should honor that contract.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_APPWIDGET"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
          keyguard widget
          @hide -->
     <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Internal permission allowing an application to query/set which
          applications can bind AppWidgets.
          @hide -->
     <permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change the background data setting.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi This permission can be used on content providers to allow the global
          search system to access their data.  Typically it used when the
@@ -2704,7 +2693,7 @@
          it is used by applications to protect themselves from everyone else
          besides global search. -->
     <permission android:name="android.permission.GLOBAL_SEARCH"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Internal permission protecting access to the global search
          system: ensures that only the system can access the provider
@@ -2714,33 +2703,33 @@
          ranking).
          @hide -->
     <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission to allows an application to read indexable data.
         @hide -->
     <permission android:name="android.permission.READ_SEARCH_INDEXABLES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
     <permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to read dream settings and dream state.
          @hide -->
     <permission android:name="android.permission.READ_DREAM_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
          @hide -->
     <permission android:name="android.permission.WRITE_DREAM_STATE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allow an application to read and write the cache partition.
          @hide -->
     <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by default container service so that only
          the system can bind to it and use it to copy
@@ -2748,67 +2737,67 @@
          accessible to the system.
          @hide -->
     <permission android:name="android.permission.COPY_PROTECTED_DATA"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission protecting access to the encryption methods
         @hide
     -->
     <permission android:name="android.permission.CRYPT_KEEPER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read historical network usage for
          specific networks and applications. @hide -->
     <permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage network policies (such as warning and disable
          limits) and to define application-specific rules. @hide -->
     <permission android:name="android.permission.MANAGE_NETWORK_POLICY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to account its network traffic against other UIDs. Used
          by system services like download manager and media server. Not for use by
          third party apps. @hide -->
     <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- C2DM permission.
          @hide Used internally.
      -->
     <permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
-                android:protectionLevel="signature" />
+          android:protectionLevel="signature" />
     <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
 
     <!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
          trust it to verify packages.
     -->
     <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by package verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
          PackageManager will trust it to verify intent filters.
     -->
     <permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by intent filter verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to access serial ports via the SerialManager.
          @hide -->
     <permission android:name="android.permission.SERIAL_PORT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows the holder to access content providers from outside an ApplicationThread.
          This permission is enforced by the ActivityManagerService on the corresponding APIs,
@@ -2817,27 +2806,27 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
          OTA reboot *not* occur while the lock is held.
          @hide -->
     <permission android:name="android.permission.UPDATE_LOCK"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read the current set of notifications, including
          any metadata and intents attached.
          @hide -->
     <permission android:name="android.permission.ACCESS_NOTIFICATIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Marker permission for applications that wish to access notification policy.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
-                android:description="@string/permdesc_access_notification_policy"
-                android:label="@string/permlab_access_notification_policy"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_access_notification_policy"
+        android:label="@string/permlab_access_notification_policy"
+        android:protectionLevel="normal" />
 
     <!-- Allows modification of do not disturb rules and policies. Only allowed for system
         processes.
@@ -2848,42 +2837,42 @@
     <!-- Allows access to keyguard secure storage.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_FINGERPRINT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
     <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to control keyguard.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.CONTROL_KEYGUARD"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to listen to trust changes.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.TRUST_LISTENER"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to provide a trust agent.
          @hide For security reasons, this is a platform-only permission. -->
     <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to launch the trust agent settings activity.
         @hide -->
     <permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Must be required by an {@link
         android.service.trust.TrustAgentService},
         to ensure that only the system can bind to it.
         @hide -->
     <permission android:name="android.permission.BIND_TRUST_AGENT"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationListenerService},
@@ -2891,7 +2880,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
@@ -2899,7 +2888,7 @@
          @hide This is not a third-party API (intended for system apps). -->
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.chooser.ChooserTargetService}, to ensure that
@@ -2907,7 +2896,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
@@ -2915,57 +2904,57 @@
          <p>Protection level: signature
          -->
     <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.service.dreams.DreamService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DREAM_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
          carrier setup application to enforce that this permission is required
          @hide This is not a third-party API (intended for OEMs and system apps). -->
     <permission android:name="android.permission.INVOKE_CARRIER_SETUP"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to listen for network condition observations.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to provision and access DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Api Allows an application to manage media projection sessions.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to read install sessions
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.READ_INSTALL_SESSIONS"
-                android:label="@string/permlab_readInstallSessions"
-                android:description="@string/permdesc_readInstallSessions"
-                android:protectionLevel="normal"/>
+        android:label="@string/permlab_readInstallSessions"
+        android:description="@string/permdesc_readInstallSessions"
+        android:protectionLevel="normal"/>
 
     <!-- @SystemApi Allows an application to remove DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
     <permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to interact with the currently active
          {@link android.service.voice.VoiceInteractionService}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- The system process that is allowed to bind to services in carrier apps will
          have this permission. Carrier apps should use this permission to protect
@@ -2973,9 +2962,9 @@
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_CARRIER_SERVICES"
-                android:label="@string/permlab_bindCarrierServices"
-                android:description="@string/permdesc_bindCarrierServices"
-                android:protectionLevel="signature|privileged" />
+        android:label="@string/permlab_bindCarrierServices"
+        android:description="@string/permdesc_bindCarrierServices"
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
          flag is set.
@@ -3021,7 +3010,7 @@
     <!-- Allows the holder to access the ephemeral applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -3033,7 +3022,7 @@
          APIs given by {@link SoundTriggerManager}.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
          Provisioning app. If requesting app does not have permission, it will be ignored.
@@ -3057,17 +3046,17 @@
          the system can bind to it.
          <p>Protection level: signature -->
     <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Required to make calls to {@link android.service.vr.IVrManager}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VR_MANAGER"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Allows an application to whitelist tasks during lock task mode
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
-                android:protectionLevel="signature|setup" />
+        android:protectionLevel="signature|setup" />
 
     <!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
          in the N-release and later.
@@ -3088,13 +3077,12 @@
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
-                  android:theme="@style/Theme.DeviceDefault.Resolver"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:excludeFromRecents="true"
-                  android:documentLaunchMode="never"
-                  android:relinquishTaskIdentity="true"
-                  android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                  android:process=":ui">
+                android:theme="@style/Theme.DeviceDefault.Resolver"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:documentLaunchMode="never"
+                android:relinquishTaskIdentity="true"
+                android:process=":ui">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3102,102 +3090,102 @@
             </intent-filter>
         </activity>
         <activity android:name="com.android.internal.app.IntentForwarderActivity"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true"
-                  android:label="@string/user_owner_label"
-                  android:exported="true"
-        >
+                android:finishOnCloseSystemDialogs="true"
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:label="@string/user_owner_label"
+                android:exported="true"
+                >
         </activity>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
-                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                        android:exported="true"
-                        android:label="@string/user_owner_label">
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:exported="true"
+                android:label="@string/user_owner_label">
         </activity-alias>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
-                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                        android:icon="@drawable/ic_corp_icon"
-                        android:exported="true"
-                        android:label="@string/managed_profile_label">
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/ic_corp_icon"
+                android:exported="true"
+                android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/heavy_weight_switcher_title"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/heavy_weight_switcher_title"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.PlatLogoActivity"
-                  android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
-                  android:configChanges="orientation|keyboardHidden"
-                  android:process=":ui">
+                android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+                android:configChanges="orientation|keyboardHidden"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DisableCarModeActivity"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DumpHeapActivity"
-                  android:theme="@style/Theme.Translucent.NoTitleBar"
-                  android:label="@string/dump_heap_title"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:noHistory="true"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Translucent.NoTitleBar"
+                android:label="@string/dump_heap_title"
+                android:finishOnCloseSystemDialogs="true"
+                android:noHistory="true"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
         <provider android:name="com.android.server.am.DumpHeapProvider"
-                  android:authorities="com.android.server.heapdump"
-                  android:grantUriPermissions="true"
-                  android:multiprocess="false"
-                  android:singleUser="true" />
+                android:authorities="com.android.server.heapdump"
+                android:grantUriPermissions="true"
+                android:multiprocess="false"
+                android:singleUser="true" />
 
         <activity android:name="android.accounts.ChooseAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
-                  android:excludeFromRecents="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.CantAddAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.DialogWhenLarge"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/sync_too_many_deletes"
-                  android:process=":ui">
+               android:theme="@style/Theme.Material.Light.Dialog"
+               android:label="@string/sync_too_many_deletes"
+               android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.ShutdownActivity"
-                  android:permission="android.permission.SHUTDOWN"
-                  android:theme="@style/Theme.NoDisplay"
-                  android:excludeFromRecents="true">
+            android:permission="android.permission.SHUTDOWN"
+            android:theme="@style/Theme.NoDisplay"
+            android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3209,9 +3197,9 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3228,9 +3216,9 @@
         <!-- Activity to prompt user if it's ok to create a new user sandbox for a
              specified account. -->
         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
-                  android:excludeFromRecents="true"
-                  android:process=":ui"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert">
+                android:excludeFromRecents="true"
+                android:process=":ui"
+                android:theme="@style/Theme.Material.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3238,20 +3226,20 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
 
         <receiver android:name="com.android.server.BootReceiver"
-                  android:systemUserOnly="true">
+                android:systemUserOnly="true">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.CertPinInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_PINS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3259,7 +3247,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3267,7 +3255,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3275,7 +3263,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3283,7 +3271,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3291,23 +3279,15 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.TzDataInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_TZDATA" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
 
-        <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
-            <intent-filter>
-                <action android:name="android.intent.action.UPDATE_SEPOLICY" />
-                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
-            </intent-filter>
-        </receiver>
-
         <receiver android:name="com.android.server.MasterClearReceiver"
-                  android:permission="android.permission.MASTER_CLEAR">
+            android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
                     android:priority="100" >
                 <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
@@ -3320,12 +3300,12 @@
         </receiver>
 
         <service android:name="android.hardware.location.GeofenceHardwareService"
-                 android:permission="android.permission.LOCATION_HARDWARE"
-                 android:exported="false" />
+            android:permission="android.permission.LOCATION_HARDWARE"
+            android:exported="false" />
 
         <service android:name="com.android.internal.backup.LocalTransportService"
-                 android:permission="android.permission.CONFIRM_FULL_BACKUP"
-                 android:exported="false">
+                android:permission="android.permission.CONFIRM_FULL_BACKUP"
+                android:exported="false">
             <intent-filter>
                 <action android:name="android.backup.TRANSPORT_HOST" />
             </intent-filter>
@@ -3350,9 +3330,9 @@
         </service>
 
         <service
-                android:name="com.android.server.pm.BackgroundDexOptService"
-                android:exported="true"
-                android:permission="android.permission.BIND_JOB_SERVICE">
+            android:name="com.android.server.pm.BackgroundDexOptService"
+            android:exported="true"
+            android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
 
     </application>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index f440389..0bee8b9 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -106,7 +106,7 @@
 
         // OEMs cannot define permissions in the platform namespace
         for (String permission : declaredPermissionsMap.keySet()) {
-            assertFalse("Cannot define permission " + permission + " in android namespace",
+            assertFalse("Cannot define permission in android namespace",
                     permission.startsWith(PLATFORM_ROOT_NAMESPACE));
         }
 
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
index bceaacc..d0c1a81 100644
--- a/tests/tests/print/Android.mk
+++ b/tests/tests/print/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_PACKAGE_NAME := CtsPrintTestCases
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil android-support-test
 
 LOCAL_SDK_VERSION := test_current
 
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
index f8f610a..0c6f411 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
@@ -29,6 +29,7 @@
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
 import android.provider.cts.contacts.ContactUtil;
@@ -228,6 +229,15 @@
                 new long[]{contact.getId()}
         );
 
+        // Contacts.CONTENT_FILTER_URI
+        DatabaseAsserts.checkProjection(mResolver,
+                Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon().appendEncodedPath("xxx")
+                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                                String.valueOf(Directory.DEFAULT)).build(),
+                PROJECTION,
+                new long[]{contact.getId()}
+        );
+
         // Contacts.CONTENT_LOOKUP_URI
         DatabaseAsserts.checkProjection(mResolver,
                 Contacts.getLookupUri(contactId, lookupKey),
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
index 33d3a28..62c6fdd 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
@@ -36,6 +36,7 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Contacts.Entity;
 import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.RawContactsEntity;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -533,6 +534,37 @@
         assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
     }
 
+    public void testEnterpriseCallableFilterByNameOrOrganization_returnsCorrectDataRows()
+            throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "doe").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        // Only callables belonging to John Doe (name) and Cold Tamago (organization) are returned.
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[5],
+                sContentValues[6]);
+    }
+
+    public void testEnterpriseCallableFilterByNumber_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "510").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1]);
+    }
+
+    public void testEnterpriseCallableFilterBySipAddress_returnsCorrectDataRows()
+            throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "mysip").buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
+    }
+
     public void testDataInsert_updatesContactLastUpdatedTimestamp() {
         DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
         long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
index 847e357..b049996 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
@@ -28,6 +28,7 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.SearchSnippets;
 import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -85,6 +86,15 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids);
     }
 
+    public void testEnterpriseSearchSnippets_NoMatch() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).appendPath("nomatch").build();
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids);
+    }
+
     public void testSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -96,6 +106,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("farm").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "eggs@[farmers].org");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -107,6 +129,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("510").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "[510-123-5769]");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -118,6 +152,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("street").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "123 Main [Street] Unit 3113\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_LongMatchTruncation() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -129,6 +175,18 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
     }
 
+    public void testEnterpriseSearchSnippets_LongMatchTruncation() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("over").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026dog jumps [over] the quick\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
     public void testSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
         long[] ids = setupTestData();
         final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -145,6 +203,23 @@
         assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
     }
 
+    public void testEnterpriseSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("123").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT)).build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "[123-456-7890]");
+
+        final ContentValues expected2 = new ContentValues();
+        expected2.put(Contacts._ID, ids[2]);
+        expected2.put(SearchSnippets.SNIPPET, "[123] Main Street Unit 3113\u2026");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
+    }
+
     /**
      * Tests that if deferred snippeting is indicated, the provider will not perform formatting
      * of the snippet for a single word query.
@@ -163,6 +238,25 @@
     }
 
     /**
+     * Tests that if deferred snippeting is indicated, the provider will not perform formatting
+     * of the snippet for a single word query.
+     */
+    public void testEnterpriseSearchSnippets_DeferredSnippetingSingleWordQuerySnippetDeferred()
+            throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .appendPath("510").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "510-123-5769");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
      * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
      * of the snippet done by the provider using SQLite
      */
@@ -180,6 +274,25 @@
     }
 
     /**
+     * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
+     * of the snippet done by the provider using SQLite
+     */
+    public void testEnterpriseSearchSnippets_DeferredSnippetingMultiWordQuerySnippetNotDeferred()
+            throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+                        String.valueOf(Directory.DEFAULT))
+                .appendPath("jumps over").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026lazy dog [jumps] [over] the\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
      * Given a uri, performs a query on the contacts provider for that uri and asserts that the
      * cursor returned from the query matches the expected results.
      *
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index d731561..173c3ea 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -428,8 +428,32 @@
 /////////////////////////////////////////////////////////////////////////
 
 // Test out-of-range result.
+
+// When a result is ulong, it can take on values not representable on
+// the Java side, where there are no unsigned integral types and long
+// is the largest integral type -- i.e., all values in the range
+// (MAX_LONG, MAX_ULONG] are not representable in Java.  The reflected
+// result_*.get() methods throw an exception if the result value is
+// out of range.  The globals and reduction kernels below allow a test
+// case on the Java side to describe what kind of result we should
+// produce -- in particular, what to use for an in-range value and an
+// out-of-range value, and where (if anywhere) to put an out-of-range
+// value within the result (which might be scalar, vector, array of
+// scalar, or array of vector).
+
 // We don't care about the input at all.
 // We use these globals to configure the generation of the result.
+// A kernel puts 2*oorrBadResultHalf in the position (if any) of the result
+// given by oorrBadResult, and oorrGoodResult everywhere else.
+// The oorrBadPos encoding is as follows:
+// - For scalar result, 0 = scalar; anything else = nowhere
+// - For vector result, 0..length(vector)-1 = corresponding vector component
+//     (0 = x, 1 = y, 2 = z, 3 = w); anything else = nowhere
+// - For array of scalar result, 0..length(array)-1 = corresponding array element;
+//     anything else = nowhere
+// - For array of vector result, 0..length(vector)*length(array)-1 = corresponding
+//     vector component C of corresponding array element E; anything else = nowhere
+//     (encoding is C + length(vector)*E)
 ulong oorrGoodResult;     // the value of a good result
 ulong oorrBadResultHalf;  // half the value of a bad result
                           //   ("half" because Java can only set the global from long not from ulong)
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 3d95053..68e0cba 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -21,7 +21,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 536d2a8..c31d825 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telecom/Android.mk b/tests/tests/telecom/Android.mk
index 5a8922e..27947af 100644
--- a/tests/tests/telecom/Android.mk
+++ b/tests/tests/telecom/Android.mk
@@ -24,7 +24,7 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
index 0f09314..b15a4e8 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
@@ -265,4 +265,20 @@
         } catch (SecurityException expected) {
         }
     }
+
+    /**
+     * Tests the TelephonyManager.getIccAuthentication() API. This makes a call to
+     * getIccAuthentication() API and expects a SecurityException since the test apk is not
+     * signed by certificate on the SIM.
+     */
+    public void testGetIccAuthentication() {
+        try {
+            if (isSimCardPresent()) {
+                TelephonyManager.getDefault().getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+                        TelephonyManager.AUTHTYPE_EAP_AKA, "");
+                fail("Expected SecurityException. App doesn't have carrier privileges.");
+            }
+        } catch (SecurityException expected) {
+        }
+    }
 }
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index 65a93fb..731fa9b 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
index 1705326..212d4eb 100644
--- a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -59,6 +59,31 @@
     }
 
     @SmallTest
+    public void testCRLF() {
+        EditorState state = new EditorState();
+
+        // U+000A is LINE FEED.
+        state.setByString("U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        // U+000D is CARRIAGE RETURN.
+        state.setByString("U+000D |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+000D U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+000A U+000D |");
+        backspace(state, 0);
+        state.assertEquals("U+000A |");
+        backspace(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
     public void testSurrogatePairs() {
         EditorState state = new EditorState();
 
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
index 40ed593..3b226fb 100644
--- a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -59,6 +59,30 @@
     }
 
     @SmallTest
+    public void testCRLF() {
+        EditorState state = new EditorState();
+
+        // U+000A is LINE FEED.
+        state.setByString("| U+000A");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+000D is CARRIAGE RETURN.
+        state.setByString("| U+000D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+000D U+000A");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+000A U+000D");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+000D");
+        forwardDelete(state, 0);
+    }
+
+    @SmallTest
     public void testSurrogatePairs() {
         EditorState state = new EditorState();
 
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index a159da9..431c754 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -592,13 +592,6 @@
     }
 
     @SmallTest
-    public void testAddLinks_partiallyMatchesUrlWithInvalidRequestParameter() throws Exception {
-        String url = "http://android.com?p=value";
-        assertAddLinksWithWebUrlPartiallyMatches("Should partially match URL with invalid " +
-                "request parameter", "http://android.com", url);
-    }
-
-    @SmallTest
     public void testAddLinks_matchesValidUrlWithEmoji() throws Exception {
         String url = "Thank\u263A.com";
         assertAddLinksWithWebUrlSucceeds("Should match URL with emoji", url);
@@ -669,6 +662,48 @@
         }
     }
 
+    @SmallTest
+    public void testAddLinks_matchesDomainNameWithDash() throws Exception {
+        String url = "http://a-nd.r-oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+
+        url = "a-nd.r-oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesDomainNameWithUnderscore() throws Exception {
+        String url = "http://a_nd.r_oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+
+        url = "a_nd.r_oid.com";
+        assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesPathAndQueryWithDollarSign() throws Exception {
+        String url = "http://android.com/path$?v=$val";
+        assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+
+        url = "android.com/path$?v=$val";
+        assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+    }
+
+    @SmallTest
+    public void testAddLinks_matchesEmptyPathWithQueryParams() throws Exception {
+        String url = "http://android.com?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "android.com?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "http://android.com/?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+        url = "android.com/?q=v";
+        assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+    }
+
     // EMAIL_ADDRESSES Related Tests
 
     public void testAddLinks_email_matchesShortValidEmail() throws Exception {
diff --git a/tests/tests/transition/Android.mk b/tests/tests/transition/Android.mk
index af8b4eb..6dd90e3 100644
--- a/tests/tests/transition/Android.mk
+++ b/tests/tests/transition/Android.mk
@@ -24,7 +24,7 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index fd01e10..a2e54d0 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
new file mode 100644
index 0000000..c95568a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/dashed_oval.xml b/tests/tests/uirendering/res/drawable/dashed_oval.xml
new file mode 100644
index 0000000..904b016
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/dashed_oval.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+  -->
+<shape
+    android:shape="oval"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <stroke
+        android:width="2px"
+        android:dashGap="6px"
+        android:dashWidth="2px"
+        android:color="@android:color/black"
+        />
+</shape>
diff --git a/tests/tests/uirendering/res/layout/frame_layout.xml b/tests/tests/uirendering/res/layout/frame_layout.xml
new file mode 100644
index 0000000..4ceac5d
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/frame_layout.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_layout"
+    android:layout_width="@dimen/test_width"
+    android:layout_height="@dimen/test_height"/>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
index 1e7a832..8360948 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -16,12 +16,18 @@
 
 package android.uirendering.cts.testclasses;
 
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.bitmapverifiers.ColorVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.util.DisplayMetrics;
+
 import org.junit.Test;
 
 import static org.junit.Assert.assertFalse;
@@ -114,4 +120,68 @@
                 })
                 .runWithoutVerification();
     }
+
+    private void testFailureOnBitmapDraw(Bitmap bitmap) {
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    boolean sawException = false;
+                    try {
+                        canvas.drawBitmap(bitmap, 0, 0, null);
+                    } catch (RuntimeException e) {
+                        sawException = true;
+                    }
+                    assertTrue(sawException);
+                })
+                .runWithoutVerification();
+    }
+
+    @Test
+    public void testFailureOnDrawRecycledBitmap() {
+        Bitmap recycledBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        recycledBitmap.recycle();
+        testFailureOnBitmapDraw(recycledBitmap);
+    }
+
+    @Test
+    public void testFailureOnNonPremultipliedBitmap() {
+        Bitmap nonPremultipliedBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        nonPremultipliedBitmap.setPremultiplied(false);
+        nonPremultipliedBitmap.setHasAlpha(true);
+        testFailureOnBitmapDraw(nonPremultipliedBitmap);
+    }
+
+    @Test
+    public void testDrawScreenWideBitmap() {
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    DisplayMetrics displayMetrics =
+                            getActivity().getResources().getDisplayMetrics();
+                    assertTrue(displayMetrics.widthPixels <= canvas.getMaximumBitmapWidth());
+                    assertTrue(displayMetrics.heightPixels <= canvas.getMaximumBitmapHeight());
+                    Bitmap bitmap = Bitmap.createBitmap(displayMetrics.widthPixels,
+                            displayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
+                    bitmap.eraseColor(Color.RED);
+                    canvas.drawBitmap(bitmap, 0, 0, null);
+                })
+                .runWithVerifier(new ColorVerifier(Color.RED, 0));
+    }
+
+    @Test
+    public void testDrawLargeBitmap() {
+        // verify that HW and SW pipelines can both draw screen-and-a-half sized bitmap
+        createTest()
+                .addCanvasClient((canvas, width, height) -> {
+                    DisplayMetrics displayMetrics =
+                            getActivity().getResources().getDisplayMetrics();
+
+                    int bWidth = displayMetrics.widthPixels * 3 / 2;
+                    int bHeight = displayMetrics.heightPixels * 3 / 2;
+                    bWidth = Math.min(bWidth, canvas.getMaximumBitmapWidth());
+                    bHeight = Math.min(bHeight, canvas.getMaximumBitmapHeight());
+                    Bitmap bitmap = Bitmap.createBitmap(bWidth, bHeight, Bitmap.Config.ARGB_8888);
+                    bitmap.eraseColor(Color.RED);
+                    canvas.drawBitmap(bitmap, 0, 0, null);
+                })
+                .runWithVerifier(new ColorVerifier(Color.RED, 0));
+    }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
new file mode 100644
index 0000000..3670797
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
@@ -0,0 +1,22 @@
+package android.uirendering.cts.testclasses;
+
+import android.graphics.*;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import org.junit.Test;
+
+@MediumTest
+public class ShapeTests extends ActivityTestBase {
+    @Test
+    public void testDashedOval() {
+        Bitmap goldenBitmap = BitmapFactory.decodeResource(getActivity().getResources(),
+                R.drawable.golden_dashed_oval);
+        createTest()
+                .addLayout(R.layout.frame_layout,
+                        view -> view.setBackgroundResource(R.drawable.dashed_oval))
+                .runWithVerifier(new GoldenImageVerifier(goldenBitmap, new MSSIMComparer(0.99)));
+    }
+}
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 57dc0ce..ea9ce5a 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctsdeviceutil ctstestrunner mockito-target platform-test-annotations
+    ctsdeviceutil ctstestrunner mockito-target platform-test-annotations android-support-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/view/jni/Android.mk b/tests/tests/view/jni/Android.mk
index ac7b844..288e250 100644
--- a/tests/tests/view/jni/Android.mk
+++ b/tests/tests/view/jni/Android.mk
@@ -18,6 +18,8 @@
 
 LOCAL_MODULE := libctsview_jni
 
+LOCAL_CFLAGS += -Werror
+
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
diff --git a/tests/tests/view/jni/CtsViewJniOnLoad.cpp b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
index 2c1e643..1a7ef3c 100644
--- a/tests/tests/view/jni/CtsViewJniOnLoad.cpp
+++ b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
@@ -16,8 +16,8 @@
  */
 #include <jni.h>
 
-#include <utils/Log.h>
 #define LOG_TAG "CtsViewJniOnLoad"
+#include <utils/Log.h>
 
 extern int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env);
 
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index 64ebe39..df1fae9 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -111,15 +111,15 @@
           android:orientation="vertical"
           android:layout_width="match_parent"
           android:layout_height="70px"
-          android:pointerIcon="crosshair">
+          android:pointerShape="crosshair">
         <View android:layout_width="match_parent"
               android:layout_height="20px"
-              android:pointerIcon="help"/>
+              android:pointerShape="help"/>
         <View android:layout_width="match_parent"
               android:layout_height="20px"/>
         <View android:layout_width="match_parent"
               android:layout_height="20px"
-              android:pointerIcon="@drawable/custom_pointer_icon"/>
+              android:pointerShape="@drawable/custom_pointer_icon"/>
       </LinearLayout>
     </LinearLayout>
 
diff --git a/tests/tests/view/src/android/view/cts/MockView.java b/tests/tests/view/src/android/view/cts/MockView.java
index c5e4ab4..f07e991 100644
--- a/tests/tests/view/src/android/view/cts/MockView.java
+++ b/tests/tests/view/src/android/view/cts/MockView.java
@@ -69,7 +69,7 @@
     private boolean mCalledComputeScroll = false;
     private boolean mCalledDispatchKeyEventPreIme = false;
     private boolean mCalledOnKeyPreIme = false;
-    private boolean mCalledOnResolvePointerIcon = false;
+    private boolean mCalledGetPointerIcon = false;
     private boolean mCalledOnVisibilityAggregated = false;
     private boolean mCalledDispatchStartTemporaryDetach = false;
     private boolean mCalledDispatchFinishTemporaryDetach = false;
@@ -614,13 +614,13 @@
     }
 
     @Override
-    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
-        mCalledOnResolvePointerIcon = true;
-        return super.onResolvePointerIcon(event, pointerIndex);
+    public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
+        mCalledGetPointerIcon = true;
+        return super.getPointerIcon(event, x, y);
     }
 
-    public boolean hasCalledOnResolvePointerIcon() {
-        return mCalledOnResolvePointerIcon;
+    public boolean hasCalledGetPointerIcon() {
+        return mCalledGetPointerIcon;
     }
 
     @Override
@@ -716,7 +716,7 @@
         mCalledComputeScroll = false;
         mCalledDispatchKeyEventPreIme = false;
         mCalledOnKeyPreIme = false;
-        mCalledOnResolvePointerIcon = false;
+        mCalledGetPointerIcon = false;
         mCalledOnVisibilityAggregated = false;
         mCalledOnVisibilityAggregated = false;
         mCalledDispatchStartTemporaryDetach = false;
diff --git a/tests/tests/view/src/android/view/cts/NumberPickerTest.java b/tests/tests/view/src/android/view/cts/NumberPickerTest.java
deleted file mode 100644
index 2e2733e..0000000
--- a/tests/tests/view/src/android/view/cts/NumberPickerTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- *
- * 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.view.cts;
-
-import android.test.AndroidTestCase;
-import android.widget.NumberPicker;
-
-public class NumberPickerTest extends AndroidTestCase {
-
-    public void testSetDisplayedValues1() throws Exception {
-        NumberPicker numberPicker = new NumberPicker(getContext());
-        numberPicker.setMinValue(10);
-        numberPicker.setMaxValue(12);
-        numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
-    }
-
-    public void testSetDisplayedValues2() throws Exception {
-        NumberPicker numberPicker = new NumberPicker(getContext());
-        numberPicker.setMinValue(10);
-        numberPicker.setMaxValue(14);
-        try {
-            numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
-            fail("The size of the displayed values array must be equal to the selectable numbers!");
-        } catch (Exception e) {
-            /* expected */
-        }
-    }
-}
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index d3ff57d..3f667f5 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -377,73 +377,73 @@
         getInstrumentation().sendPointerSync(event);
         getInstrumentation().waitForIdleSync();
 
-        assertTrue(view.hasCalledOnResolvePointerIcon());
+        assertTrue(view.hasCalledGetPointerIcon());
 
         final MockView view2 = (MockView) mActivity.findViewById(R.id.scroll_view);
-        assertFalse(view2.hasCalledOnResolvePointerIcon());
+        assertFalse(view2.hasCalledGetPointerIcon());
     }
 
-    public void testAccessPointerIcon() {
+    public void testAccessPointerShape() {
         View view = mActivity.findViewById(R.id.pointer_icon_layout);
         MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE,
                                                view.getX(), view.getY(), 0);
 
-        // First view has pointerIcon="help"
-        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HELP),
-                     view.onResolvePointerIcon(event, 0));
+        // First view has pointerShape="help"
+        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_HELP),
+                     view.getPointerIcon(event, 0, 0));
 
-        // Second view inherits pointerIcon="crosshair" from the parent
+        // Second view inherits pointerShape="crosshair" from the parent
         event.setLocation(0, 21);
-        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR),
-                     view.onResolvePointerIcon(event, 0));
+        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_CROSSHAIR),
+                     view.getPointerIcon(event, 0, 21));
 
-        // Third view has custom pointer icon defined in a resource.
+        // Third view has custom pointer shape defined in a resource.
         event.setLocation(0, 41);
-        assertNotNull(view.onResolvePointerIcon(event, 0));
+        assertNotNull(view.getPointerIcon(event, 0, 41));
 
-        // Parent view has pointerIcon="crosshair"
+        // Parent view has pointerShape="crosshair"
         event.setLocation(0, 61);
-        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR),
-                     view.onResolvePointerIcon(event, 0));
+        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_CROSSHAIR),
+                     view.getPointerIcon(event, 0, 61));
 
-        // Outside of the parent view, no pointer icon defined.
+        // Outside of the parent view, no pointer shape defined.
         event.setLocation(0, 71);
-        assertNull(view.onResolvePointerIcon(event, 0));
+        assertNull(view.getPointerIcon(event, 0, 71));
 
-        view.setPointerIcon(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT));
-        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT),
-                     view.onResolvePointerIcon(event, 0));
+        view.setPointerIcon(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_TEXT));
+        assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.STYLE_TEXT),
+                     view.getPointerIcon(event, 0,71));
         event.recycle();
     }
 
     public void testCreatePointerIcons() {
-        assertSystemPointerIcon(PointerIcon.TYPE_NULL);
-        assertSystemPointerIcon(PointerIcon.TYPE_DEFAULT);
-        assertSystemPointerIcon(PointerIcon.TYPE_ARROW);
-        assertSystemPointerIcon(PointerIcon.TYPE_CONTEXT_MENU);
-        assertSystemPointerIcon(PointerIcon.TYPE_HAND);
-        assertSystemPointerIcon(PointerIcon.TYPE_HELP);
-        assertSystemPointerIcon(PointerIcon.TYPE_WAIT);
-        assertSystemPointerIcon(PointerIcon.TYPE_CELL);
-        assertSystemPointerIcon(PointerIcon.TYPE_CROSSHAIR);
-        assertSystemPointerIcon(PointerIcon.TYPE_TEXT);
-        assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_TEXT);
-        assertSystemPointerIcon(PointerIcon.TYPE_ALIAS);
-        assertSystemPointerIcon(PointerIcon.TYPE_COPY);
-        assertSystemPointerIcon(PointerIcon.TYPE_NO_DROP);
-        assertSystemPointerIcon(PointerIcon.TYPE_ALL_SCROLL);
-        assertSystemPointerIcon(PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW);
-        assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW);
-        assertSystemPointerIcon(PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW);
-        assertSystemPointerIcon(PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW);
-        assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_IN);
-        assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_OUT);
-        assertSystemPointerIcon(PointerIcon.TYPE_GRAB);
+        assertSystemPointerIcon(PointerIcon.STYLE_NULL);
+        assertSystemPointerIcon(PointerIcon.STYLE_DEFAULT);
+        assertSystemPointerIcon(PointerIcon.STYLE_ARROW);
+        assertSystemPointerIcon(PointerIcon.STYLE_CONTEXT_MENU);
+        assertSystemPointerIcon(PointerIcon.STYLE_HAND);
+        assertSystemPointerIcon(PointerIcon.STYLE_HELP);
+        assertSystemPointerIcon(PointerIcon.STYLE_WAIT);
+        assertSystemPointerIcon(PointerIcon.STYLE_CELL);
+        assertSystemPointerIcon(PointerIcon.STYLE_CROSSHAIR);
+        assertSystemPointerIcon(PointerIcon.STYLE_TEXT);
+        assertSystemPointerIcon(PointerIcon.STYLE_VERTICAL_TEXT);
+        assertSystemPointerIcon(PointerIcon.STYLE_ALIAS);
+        assertSystemPointerIcon(PointerIcon.STYLE_COPY);
+        assertSystemPointerIcon(PointerIcon.STYLE_NO_DROP);
+        assertSystemPointerIcon(PointerIcon.STYLE_ALL_SCROLL);
+        assertSystemPointerIcon(PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW);
+        assertSystemPointerIcon(PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW);
+        assertSystemPointerIcon(PointerIcon.STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW);
+        assertSystemPointerIcon(PointerIcon.STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW);
+        assertSystemPointerIcon(PointerIcon.STYLE_ZOOM_IN);
+        assertSystemPointerIcon(PointerIcon.STYLE_ZOOM_OUT);
+        assertSystemPointerIcon(PointerIcon.STYLE_GRAB);
 
-        assertNotNull(PointerIcon.load(mResources, R.drawable.custom_pointer_icon));
+        assertNotNull(PointerIcon.loadCustomIcon(mResources, R.drawable.custom_pointer_icon));
 
         Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.icon_blue);
-        assertNotNull(PointerIcon.create(bitmap, 0, 0));
+        assertNotNull(PointerIcon.createCustomIcon(bitmap, 0, 0));
     }
 
     private void assertSystemPointerIcon(int style) {
@@ -3876,7 +3876,7 @@
 
         assertFalse(view.hasPointerCapture());
 
-        view.requestPointerCapture();
+        view.setPointerCapture();
         assertTrue(view.hasPointerCapture());
         getInstrumentation().sendPointerSync(dummyMotion);
         getInstrumentation().waitForIdleSync();
@@ -3895,7 +3895,7 @@
         });
         getInstrumentation().waitForIdleSync();
 
-        view.requestPointerCapture();
+        view.setPointerCapture();
         assertTrue(view.hasPointerCapture());
         assertFalse(view2.hasPointerCapture());
 
@@ -3905,7 +3905,7 @@
         assertFalse(view2.hasCalledOnHoverEvent());
         view.reset();
 
-        view2.requestPointerCapture();
+        view2.setPointerCapture();
         assertFalse(view.hasPointerCapture());
         assertTrue(view2.hasPointerCapture());
 
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 96f10fc..914ac54 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -26,7 +26,8 @@
     android-common \
     ctsdeviceutil \
     ctstestrunner \
-    platform-test-annotations
+    platform-test-annotations \
+    android-support-test
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 224966d..167a3aa 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -92,9 +92,25 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.SpinnerCtsActivity"
+                  android:label="SpinnerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.ToolbarCtsActivity"
-            android:theme="@android:style/Theme.Material.Light.NoActionBar"
-            android:label="ToolbarCtsActivity">
+                  android:theme="@android:style/Theme.Material.Light.NoActionBar"
+                  android:label="ToolbarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ActionMenuViewCtsActivity"
+                  android:label="ActionMenuViewCtsActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -388,6 +404,54 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.DatePickerCtsActivity"
+                  android:label="DatePickerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.SearchViewCtsActivity"
+                  android:label="SearchViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ImageButtonCtsActivity"
+                  android:label="ImageButtonCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.NumberPickerCtsActivity"
+                  android:label="NumberPickerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.CheckBoxCtsActivity"
+                  android:label="CheckBoxCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.RadioButtonCtsActivity"
+                  android:label="CheckBoxCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.app.ActivityGroup"
             android:label="ActivityGroup" />
 
diff --git a/tests/tests/widget/res/drawable/blue_fill.xml b/tests/tests/widget/res/drawable/blue_fill.xml
index 5a24f08..383e7db 100644
--- a/tests/tests/widget/res/drawable/blue_fill.xml
+++ b/tests/tests/widget/res/drawable/blue_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#0000FF" />
+    <solid android:color="#00F" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/green_fill.xml b/tests/tests/widget/res/drawable/green_fill.xml
new file mode 100644
index 0000000..76c1101
--- /dev/null
+++ b/tests/tests/widget/res/drawable/green_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#0F0" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
new file mode 100644
index 0000000..2dbd654
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="#F0F" />
+    <size
+        android:width="@dimen/linear_layout_divider_size"
+        android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_red.xml b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
new file mode 100644
index 0000000..56e88ef
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="#F00" />
+    <size
+        android:width="@dimen/linear_layout_divider_size"
+        android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/magenta_fill.xml b/tests/tests/widget/res/drawable/magenta_fill.xml
index cbb594f..8b6da76 100644
--- a/tests/tests/widget/res/drawable/magenta_fill.xml
+++ b/tests/tests/widget/res/drawable/magenta_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#FF00FF" />
+    <solid android:color="#F0F" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_fill.xml b/tests/tests/widget/res/drawable/red_fill.xml
index e443240..8baf5b6 100644
--- a/tests/tests/widget/res/drawable/red_fill.xml
+++ b/tests/tests/widget/res/drawable/red_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#8F00" />
+    <solid android:color="#F00" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_translucent_fill.xml b/tests/tests/widget/res/drawable/red_translucent_fill.xml
new file mode 100644
index 0000000..edfbfa0
--- /dev/null
+++ b/tests/tests/widget/res/drawable/red_translucent_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#80FF0000" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/yellow_fill.xml b/tests/tests/widget/res/drawable/yellow_fill.xml
index 3bd8097..44f88c4 100644
--- a/tests/tests/widget/res/drawable/yellow_fill.xml
+++ b/tests/tests/widget/res/drawable/yellow_fill.xml
@@ -17,5 +17,5 @@
 <shape
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="#FFFF00" />
+    <solid android:color="#FF0" />
 </shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/actionmenuview_layout.xml b/tests/tests/widget/res/layout/actionmenuview_layout.xml
new file mode 100644
index 0000000..5d2895e
--- /dev/null
+++ b/tests/tests/widget/res/layout/actionmenuview_layout.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/button" />
+
+    <ActionMenuView
+        android:id="@+id/action_menu_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
+
diff --git a/tests/tests/widget/res/layout/autocompletetextview_layout.xml b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
index 27eccab..8e023a1 100644
--- a/tests/tests/widget/res/layout/autocompletetextview_layout.xml
+++ b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
@@ -24,10 +24,11 @@
         android:layout_height="wrap_content"
         android:text="@string/notify" />
 
-    <android.widget.cts.AutoCompleteTextViewNoIme android:id="@+id/autocompletetv_edit"
-        android:completionThreshold="1"
-        android:completionHint="@string/tabs_1"
+    <android.widget.cts.AutoCompleteTextViewNoIme
+        android:id="@+id/autocompletetv_edit"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:completionThreshold="1"
+        android:completionHint="@string/tabs_1"
         android:inputType="none"/>
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/calendarview_layout.xml b/tests/tests/widget/res/layout/calendarview_layout.xml
index 3bc5e47..507d48e 100644
--- a/tests/tests/widget/res/layout/calendarview_layout.xml
+++ b/tests/tests/widget/res/layout/calendarview_layout.xml
@@ -17,6 +17,7 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scroller"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true">
diff --git a/tests/tests/widget/res/layout/checkbox_layout.xml b/tests/tests/widget/res/layout/checkbox_layout.xml
index a1f1718..c922436 100644
--- a/tests/tests/widget/res/layout/checkbox_layout.xml
+++ b/tests/tests/widget/res/layout/checkbox_layout.xml
@@ -14,12 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <CheckBox android:id="@+id/check_box"
+    <CheckBox
+        android:id="@+id/check_box"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/hello_world" />
diff --git a/tests/tests/widget/res/layout/checkedtextview_layout.xml b/tests/tests/widget/res/layout/checkedtextview_layout.xml
index d5b9c1f..fbee93e 100644
--- a/tests/tests/widget/res/layout/checkedtextview_layout.xml
+++ b/tests/tests/widget/res/layout/checkedtextview_layout.xml
@@ -14,20 +14,22 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <ListView android:id="@+id/checkedtextview_listview"
-        android:orientation="vertical"
+    <ListView
+        android:id="@+id/checkedtextview_listview"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    </ListView>
+        android:layout_height="0dip"
+        android:layout_weight="1" />
 
-    <CheckedTextView android:id="@+id/checkedtextview_test"
-        android:orientation="vertical"
+    <CheckedTextView
+        android:id="@+id/checkedtextview_test"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    </CheckedTextView>
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
 
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/datepicker_layout.xml b/tests/tests/widget/res/layout/datepicker_layout.xml
index 925674c..9857440 100644
--- a/tests/tests/widget/res/layout/datepicker_layout.xml
+++ b/tests/tests/widget/res/layout/datepicker_layout.xml
@@ -14,14 +14,29 @@
      limitations under the License.
 -->
 
-<RelativeLayout
+<ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <DatePicker
-        android:id="@+id/datePicker_dp"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerInParent="true" />
+    android:layout_height="match_parent"
+    android:fillViewport="true">
 
-</RelativeLayout>
+    <LinearLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <DatePicker
+            android:id="@+id/date_picker_calendar_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:datePickerMode="calendar" />
+
+        <DatePicker
+            android:id="@+id/date_picker_spinner_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:datePickerMode="spinner" />
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/imagebutton_layout.xml b/tests/tests/widget/res/layout/imagebutton_layout.xml
new file mode 100644
index 0000000..f59f669
--- /dev/null
+++ b/tests/tests/widget/res/layout/imagebutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <ImageButton
+        android:id="@+id/image_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/icon_red" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/imagebutton_test.xml b/tests/tests/widget/res/layout/imagebutton_test.xml
deleted file mode 100644
index 7d4b691..0000000
--- a/tests/tests/widget/res/layout/imagebutton_test.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/imagebutton"
-    android:layout_width="96px"
-    android:layout_height="76px"
-    android:soundEffectsEnabled="false"
-/>
-
diff --git a/tests/tests/widget/res/layout/linearlayout_layout.xml b/tests/tests/widget/res/layout/linearlayout_layout.xml
index 8881552..11d2a71 100644
--- a/tests/tests/widget/res/layout/linearlayout_layout.xml
+++ b/tests/tests/widget/res/layout/linearlayout_layout.xml
@@ -14,125 +14,228 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:id="@+id/linearlayout_root"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/linearlayout_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <LinearLayout android:id="@+id/horizontal"
-        android:orientation="horizontal"
+    <LinearLayout
+        android:id="@+id/horizontal"
         android:layout_width="wrap_content"
         android:layout_height="100dip"
-        android:background="#FF909090">
+        android:orientation="horizontal"
+        android:background="#888">
 
-        <TextView android:id="@+id/gravity_top"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_top"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="top"
-            android:text="@string/horizontal_text_1"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_1" />
 
-        <TextView android:id="@+id/gravity_center_vertical"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_center_vertical"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="center_vertical"
-            android:text="@string/horizontal_text_2"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_2" />
 
-        <TextView android:id="@+id/gravity_bottom"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_bottom"
             android:layout_width="wrap_content"
             android:layout_height="50dip"
             android:layout_gravity="bottom"
-            android:text="@string/horizontal_text_3"/>
+            android:background="#0F0"
+            android:text="@string/horizontal_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/vertical"
-        android:orientation="vertical"
+    <LinearLayout
+        android:id="@+id/vertical"
         android:layout_width="100dip"
         android:layout_height="wrap_content"
-        android:background="#FFFF0909">
+        android:orientation="vertical"
+        android:background="#F00">
 
-        <TextView android:id="@+id/gravity_left"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_left"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="left"
-            android:text="@string/vertical_text_1"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_1" />
 
-        <TextView android:id="@+id/gravity_center_horizontal"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/gravity_center_horizontal"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="center_horizontal"
-            android:text="@string/vertical_text_2"/>
+            android:background="#00F"
+            android:text="@string/vertical_text_2" />
 
-        <TextView android:id="@+id/gravity_right"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/gravity_right"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="right"
-            android:text="@string/vertical_text_3"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/weightsum"
+    <LinearLayout
+        android:id="@+id/weightsum"
+        android:layout_width="100dip"
+        android:layout_height="100dip"
         android:orientation="horizontal"
         android:weightSum="1.0"
         android:baselineAligned="false"
-        android:layout_width="100dip"
-        android:layout_height="100dip"
-        android:background="#FF909090">
+        android:background="#888">
 
-        <TextView android:id="@+id/weight_0_2"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/weight_0_2"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.2"
-            android:text="@string/horizontal_text_1"/>
+            android:background="#00F"
+            android:text="@string/horizontal_text_1" />
 
-        <TextView android:id="@+id/weight_0_5"
-            android:background="#FFF00F0F"
+        <TextView
+            android:id="@+id/weight_0_5"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.5"
-            android:text="@string/horizontal_text_2"/>
+            android:background="#F00"
+            android:text="@string/horizontal_text_2" />
 
-        <TextView android:id="@+id/weight_0_3"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/weight_0_3"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="0.3"
-            android:text="@string/horizontal_text_3"/>
+            android:background="#00F"
+            android:text="@string/horizontal_text_3" />
     </LinearLayout>
 
-    <LinearLayout android:id="@+id/baseline_aligned_child_index"
+    <LinearLayout
+        android:id="@+id/weightsum_vertical"
+        android:layout_width="100dip"
+        android:layout_height="100dip"
         android:orientation="vertical"
-        android:baselineAlignedChildIndex="1"
+        android:weightSum="1.0"
+        android:baselineAligned="false"
+        android:background="#888">
+
+        <TextView
+            android:id="@+id/weight_0_1"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.1"
+            android:background="#00F"
+            android:text="@string/vertical_text_1" />
+
+        <TextView
+            android:id="@+id/weight_0_4"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.4"
+            android:background="#F00"
+            android:text="@string/vertical_text_2" />
+
+        <TextView
+            android:id="@+id/weight_0_5"
+            android:layout_width="wrap_content"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#00F"
+            android:text="@string/vertical_text_3" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/baseline_aligned_child_index"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:background="#FFFF0909">
+        android:orientation="vertical"
+        android:baselineAlignedChildIndex="1"
+        android:background="#F00">
 
-        <TextView android:id="@+id/textview1"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/textview1"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="left"
-            android:text="@string/vertical_text_1"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_1" />
 
-        <TextView android:id="@+id/textview2"
-            android:background="#FF0000FF"
+        <TextView
+            android:id="@+id/textview2"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="center_horizontal"
-            android:text="@string/vertical_text_2"/>
+            android:background="#00F"
+            android:text="@string/vertical_text_2" />
 
-        <TextView android:id="@+id/textview3"
-            android:background="#FF00FF00"
+        <TextView
+            android:id="@+id/textview3"
             android:layout_width="wrap_content"
             android:layout_height="20dip"
             android:layout_gravity="right"
-            android:text="@string/vertical_text_3"/>
+            android:background="#0F0"
+            android:text="@string/vertical_text_3" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/vertical_with_divider"
+        android:layout_width="100px"
+        android:layout_height="100px"
+        android:orientation="vertical"
+        android:background="#FF0"
+        android:showDividers="middle"
+        android:divider="@drawable/linear_layout_divider_red"
+        android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+        <View
+            android:id="@+id/child1"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#00F" />
+
+        <View
+            android:id="@+id/child2"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="0.5"
+            android:background="#0F0" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/horizontal_with_divider"
+        android:layout_width="100px"
+        android:layout_height="100px"
+        android:orientation="horizontal"
+        android:background="#FF0"
+        android:showDividers="middle"
+        android:divider="@drawable/linear_layout_divider_red"
+        android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+        <View
+            android:id="@+id/child1"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="0.5"
+            android:background="#00F" />
+
+        <View
+            android:id="@+id/child2"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="0.5"
+            android:background="#0F0" />
+
     </LinearLayout>
 
 </LinearLayout>
diff --git a/tests/tests/widget/res/layout/numberpicker_layout.xml b/tests/tests/widget/res/layout/numberpicker_layout.xml
new file mode 100644
index 0000000..2e370d8
--- /dev/null
+++ b/tests/tests/widget/res/layout/numberpicker_layout.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <NumberPicker
+        android:id="@+id/number_picker"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/radiobutton_layout.xml b/tests/tests/widget/res/layout/radiobutton_layout.xml
new file mode 100644
index 0000000..23c1839
--- /dev/null
+++ b/tests/tests/widget/res/layout/radiobutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <RadioButton
+        android:id="@+id/radio_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/searchview_layout.xml b/tests/tests/widget/res/layout/searchview_layout.xml
new file mode 100644
index 0000000..b8705e0
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <SearchView
+        android:id="@+id/search_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <SearchView
+        android:id="@+id/search_view_with_defaults"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:maxWidth="@dimen/search_view_max_width"
+        android:iconifiedByDefault="false"
+        android:queryHint="@string/search_query_hint"
+        android:inputType="textCapCharacters"
+        android:imeOptions="actionDone" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/searchview_suggestion_item.xml b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
new file mode 100644
index 0000000..91f02f5
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/search_view_suggestion_row_height"
+    android:textAppearance="?android:attr/textAppearanceListItemSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/tests/tests/widget/res/layout/simple_spinner_item_layout.xml b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
new file mode 100644
index 0000000..512b138
--- /dev/null
+++ b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    style="?android:attr/spinnerItemStyle"
+    android:singleLine="true"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:ellipsize="marquee"
+    android:textAlignment="inherit"/>
diff --git a/tests/tests/widget/res/layout/spinner_layout.xml b/tests/tests/widget/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..43a6411
--- /dev/null
+++ b/tests/tests/widget/res/layout/spinner_layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true">
+
+    <LinearLayout
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <Spinner
+            android:id="@+id/spinner_dropdown_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:spinnerMode="dropdown"
+            android:prompt="@string/text_view_hello" />
+
+        <Spinner
+            android:id="@+id/spinner_dialog_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:spinnerMode="dialog"
+            android:prompt="@string/text_view_hello" />
+
+    </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/switch_layout.xml b/tests/tests/widget/res/layout/switch_layout.xml
index 12e10d2..880c6df 100644
--- a/tests/tests/widget/res/layout/switch_layout.xml
+++ b/tests/tests/widget/res/layout/switch_layout.xml
@@ -15,11 +15,31 @@
   ~ limitations under the License
   -->
 
-<Switch xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/switch_view"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <Switch
+        android:id="@+id/switch1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:thumbTint="@android:color/white"
         android:thumbTintMode="src_over"
         android:trackTint="@android:color/black"
         android:trackTintMode="src_atop" />
+
+    <Switch
+        android:id="@+id/switch2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:thumb="@drawable/icon_blue"
+        android:track="@drawable/red_translucent_fill" />
+
+    <Switch
+        android:id="@+id/switch3"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/values/dimens.xml b/tests/tests/widget/res/values/dimens.xml
index 3690039..447abc3 100644
--- a/tests/tests/widget/res/values/dimens.xml
+++ b/tests/tests/widget/res/values/dimens.xml
@@ -15,4 +15,25 @@
 -->
 <resources>
     <dimen name="popup_row_height">48dp</dimen>
+
+    <dimen name="switch_padding">24dp</dimen>
+    <dimen name="switch_thumb_text_padding">12dp</dimen>
+    <dimen name="switch_min_width">160dp</dimen>
+    <dimen name="switch_min_width2">200dp</dimen>
+
+    <dimen name="autocomplete_textview_dropdown_height">120dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_width">160dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_offset_h">24dp</dimen>
+    <dimen name="autocomplete_textview_dropdown_offset_v">32dp</dimen>
+
+    <dimen name="spinner_dropdown_width">200dp</dimen>
+    <dimen name="spinner_dropdown_offset_h">64dp</dimen>
+    <dimen name="spinner_dropdown_offset_v">48dp</dimen>
+
+    <dimen name="search_view_max_width">160dp</dimen>
+    <dimen name="search_view_max_width2">200dp</dimen>
+    <dimen name="search_view_suggestion_row_height">48dp</dimen>
+
+    <dimen name="linear_layout_divider_size">10px</dimen>
+    <dimen name="linear_layout_divider_padding">8px</dimen>
 </resources>
\ No newline at end of file
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
index 63ceffa..5c954b8 100644
--- a/tests/tests/widget/res/values/strings.xml
+++ b/tests/tests/widget/res/values/strings.xml
@@ -193,4 +193,6 @@
     <string name="toolbar_subtitle">Toolbar subtitle</string>
     <string name="toolbar_navigation">Toolbar navigation</string>
     <string name="toolbar_logo">Toolbar logo</string>
+
+    <string name="search_query_hint">query hint</string>
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
new file mode 100644
index 0000000..1b58b63
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ActionMenuView;
+
+/**
+ * A minimal application for {@link ActionMenuView} test.
+ */
+public class ActionMenuViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.actionmenuview_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
new file mode 100644
index 0000000..6de7c39
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ActionMenuView;
+import android.widget.Toolbar;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class ActionMenuViewTest
+        extends ActivityInstrumentationTestCase2<ActionMenuViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private ActionMenuViewCtsActivity mActivity;
+    private ActionMenuView mActionMenuView;
+
+    public ActionMenuViewTest() {
+        super("android.widget.cts", ActionMenuViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mActionMenuView = (ActionMenuView) mActivity.findViewById(R.id.action_menu_view);
+    }
+
+    public void testConstructor() {
+        new ActionMenuView(mActivity);
+
+        new ActionMenuView(mActivity, null);
+    }
+
+    public void testMenuContent() {
+        final Menu menu = mActionMenuView.getMenu();
+        assertNotNull(menu);
+
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, menu));
+
+        assertEquals(6, menu.size());
+        assertEquals(R.id.action_highlight, menu.getItem(0).getItemId());
+        assertEquals(R.id.action_edit, menu.getItem(1).getItemId());
+        assertEquals(R.id.action_delete, menu.getItem(2).getItemId());
+        assertEquals(R.id.action_ignore, menu.getItem(3).getItemId());
+        assertEquals(R.id.action_share, menu.getItem(4).getItemId());
+        assertEquals(R.id.action_print, menu.getItem(5).getItemId());
+
+        ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+                mock(ActionMenuView.OnMenuItemClickListener.class);
+        mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+        menu.performIdentifierAction(R.id.action_highlight, 0);
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_highlight));
+
+        menu.performIdentifierAction(R.id.action_share, 0);
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_share));
+    }
+
+    public void testMenuOverflowShowHide() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to show overflow menu and check that it's showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to hide the overflow menu and check that it's not showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.hideOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+    }
+
+    public void testMenuOverflowSubmenu() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+        // Ask to show overflow menu and check that it's showing
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+        // Register a mock menu item click listener on the toolbar
+        ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+                mock(ActionMenuView.OnMenuItemClickListener.class);
+        mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+        final Menu menu = mActionMenuView.getMenu();
+
+        // Ask to "perform" the share action and check that the menu click listener has
+        // been notified
+        mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+        verify(menuItemClickListener, times(1)).onMenuItemClick(
+                menu.findItem(R.id.action_share));
+
+        // Ask to dismiss all the popups and check that we're not showing the overflow menu
+        mInstrumentation.runOnMainSync(() -> mActionMenuView.dismissPopupMenus());
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mActionMenuView.isOverflowMenuShowing());
+    }
+
+    public void testMenuOverflowIcon() {
+        // Inflate menu and check that we're not showing overflow menu yet
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.getMenuInflater().inflate(
+                        R.menu.toolbar_menu, mActionMenuView.getMenu()));
+
+        final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mActionMenuView,
+                () -> mActionMenuView.setOverflowIcon(overflowIcon));
+
+        final Drawable toolbarOverflowIcon = mActionMenuView.getOverflowIcon();
+        TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
+                toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
+                true, Color.RED, 1, false);
+    }
+
+    public void testPopupTheme() {
+        mInstrumentation.runOnMainSync(() -> {
+                mActivity.getMenuInflater().inflate(R.menu.toolbar_menu, mActionMenuView.getMenu());
+                mActionMenuView.setPopupTheme(R.style.ToolbarPopupTheme_Test);
+        });
+        assertEquals(R.style.ToolbarPopupTheme_Test, mActionMenuView.getPopupTheme());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index eb22d6b..5a8454fe 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -16,21 +16,22 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.UiModeManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.cts.util.PollingCheck;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.KeyCharacterMap;
@@ -40,37 +41,30 @@
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.AutoCompleteTextView;
+import android.widget.AutoCompleteTextView.Validator;
 import android.widget.Filter;
 import android.widget.Filterable;
-import android.widget.AutoCompleteTextView.Validator;
+import android.widget.cts.util.TestUtils;
+import org.xmlpull.v1.XmlPullParser;
 
-import java.io.IOException;
+import static org.mockito.Mockito.*;
 
+@MediumTest
 public class AutoCompleteTextViewTest extends
         ActivityInstrumentationTestCase2<AutoCompleteCtsActivity> {
+    private final static String[] WORDS =
+            new String[] { "testOne", "testTwo", "testThree", "testFour" };
+    private final static String STRING_TEST = "To be tested";
+    private final static String STRING_VALIDATED = "String Validated";
+    private final static String STRING_CHECK = "To be checked";
 
-    /**
-     * Instantiates a new text view test.
-     */
-    public AutoCompleteTextViewTest() {
-        super("android.widget.cts", AutoCompleteCtsActivity.class);
-    }
-
-    /** The m activity. */
     private Activity mActivity;
-
-    /** The m instrumentation. */
     private Instrumentation mInstrumentation;
     private AutoCompleteTextView mAutoCompleteTextView;
     private boolean mNumeric = false;
-    ArrayAdapter<String> mAdapter;
-    private final String[] WORDS = new String[] { "testOne", "testTwo", "testThree", "testFour" };
-    boolean isOnFilterComplete = false;
-    final String STRING_TEST = "To be tested";
-    final String STRING_VALIDATED = "String Validated";
-    final String STRING_CHECK = "To be checked";
-    final String STRING_APPEND = "and be appended";
-    Validator mValidator = new Validator() {
+    private ArrayAdapter<String> mAdapter;
+
+    private final Validator mValidator = new Validator() {
         public CharSequence fixText(CharSequence invalidText) {
             return STRING_VALIDATED;
         }
@@ -80,6 +74,36 @@
         }
     };
 
+    protected class MyTextWatcher implements TextWatcher {
+        private CharSequence mExpectedAfter;
+
+        public MyTextWatcher(CharSequence expectedAfter) {
+            mExpectedAfter = expectedAfter;
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            assertEquals(mExpectedAfter.toString(), s.toString());
+            // This watcher is expected to be notified in the middle of completion
+            assertTrue(mAutoCompleteTextView.isPerformingCompletion());
+        }
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    }
+
+    /**
+     * Instantiates a new text view test.
+     */
+    public AutoCompleteTextViewTest() {
+        super("android.widget.cts", AutoCompleteCtsActivity.class);
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -89,12 +113,8 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return mActivity.hasWindowFocus();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
+
         mInstrumentation = getInstrumentation();
         mAutoCompleteTextView = (AutoCompleteTextView) mActivity
                 .findViewById(R.id.autocompletetv_edit);
@@ -116,20 +136,26 @@
     public void testConstructor() {
         XmlPullParser parser;
 
-        // new the AutoCompleteTextView instance
         new AutoCompleteTextView(mActivity);
+        new AutoCompleteTextView(mActivity, null);
+        new AutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_AutoCompleteTextView);
+
+        final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+        popupTheme.applyStyle(android.R.style.Theme_Material, true);
+        new AutoCompleteTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_AutoCompleteTextView, popupTheme);
 
         // new the AutoCompleteTextView instance
         parser = mActivity.getResources().getXml(R.layout.simple_dropdown_item_1line);
         AttributeSet attributeSet = Xml.asAttributeSet(parser);
         new AutoCompleteTextView(mActivity, attributeSet);
-        new AutoCompleteTextView(mActivity, null);
 
         // new the AutoCompleteTextView instance
         parser = mActivity.getResources().getXml(R.layout.framelayout_layout);
         attributeSet = Xml.asAttributeSet(parser);
         new AutoCompleteTextView(mActivity, attributeSet, 0);
-        new AutoCompleteTextView(mActivity, null, 0);
         // Test constructor with null Context, in fact, previous two functions will
         // finally invoke this version.
         try {
@@ -145,38 +171,39 @@
         new AutoCompleteTextView(mActivity, null, -1);
     }
 
-    public void testEnoughToFilter() throws Throwable {
+    public void testEnoughToFilter() {
         mAutoCompleteTextView.setThreshold(3);
         assertEquals(3, mAutoCompleteTextView.getThreshold());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                String testString = "TryToTest";
-                mAutoCompleteTextView.setText(testString);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("TryToTest"));
         mInstrumentation.waitForIdleSync();
         assertTrue(mAutoCompleteTextView.enoughToFilter());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                String testString = "No";
-                mAutoCompleteTextView.setText(testString);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("No"));
         mInstrumentation.waitForIdleSync();
         assertFalse(mAutoCompleteTextView.enoughToFilter());
     }
 
-    @UiThreadTest
     public void testAccessAdapter() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+        assertNull(mAutoCompleteTextView.getAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+        assertSame(mAdapter, mAutoCompleteTextView.getAdapter());
+
+        // Re-set adapter to null
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+        assertNull(mAutoCompleteTextView.getAdapter());
+    }
+
+    @UiThreadTest
+    public void testAccessFilter() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
         // Set Threshold to 4 characters
         autoCompleteTextView.setThreshold(4);
 
-        ArrayAdapter<String> adapter = null;
-        autoCompleteTextView.setAdapter(adapter);
+        autoCompleteTextView.setAdapter(null);
         assertNull(autoCompleteTextView.getAdapter());
         assertNull(autoCompleteTextView.getFilter());
 
@@ -187,49 +214,51 @@
         assertSame(filter, autoCompleteTextView.getFilter());
 
         // Re-set adapter to null
-        autoCompleteTextView.setAdapter(adapter);
+        autoCompleteTextView.setAdapter(null);
         assertNull(autoCompleteTextView.getAdapter());
         assertNull(autoCompleteTextView.getFilter());
     }
 
-    @SuppressWarnings("deprecation")
     public void testAccessItemClickListener() {
-        final MockOnItemClickListener testOnItemClickListener = new MockOnItemClickListener();
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
 
         // To ensure null listener
         mAutoCompleteTextView.setOnItemClickListener(null);
         assertNull(mAutoCompleteTextView.getItemClickListener());
         assertNull(mAutoCompleteTextView.getOnItemClickListener());
 
-        assertNotNull(testOnItemClickListener);
-        mAutoCompleteTextView.setOnItemClickListener(testOnItemClickListener);
-        assertSame(testOnItemClickListener, mAutoCompleteTextView.getItemClickListener());
-        assertSame(testOnItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+        mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+        assertSame(mockItemClickListener, mAutoCompleteTextView.getItemClickListener());
+        assertSame(mockItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+        verifyZeroInteractions(mockItemClickListener);
 
         // re-clear listener by setOnItemClickListener
         mAutoCompleteTextView.setOnItemClickListener(null);
         assertNull(mAutoCompleteTextView.getItemClickListener());
         assertNull(mAutoCompleteTextView.getOnItemClickListener());
+        verifyZeroInteractions(mockItemClickListener);
     }
 
-    @SuppressWarnings("deprecation")
     public void testAccessItemSelectedListener() {
-        MockOnItemSelectedListener testOnItemSelectedListener = new MockOnItemSelectedListener();
+        final AdapterView.OnItemSelectedListener mockItemSelectedListener =
+                mock(AdapterView.OnItemSelectedListener.class);
 
         // To ensure null listener
         mAutoCompleteTextView.setOnItemSelectedListener(null);
         assertNull(mAutoCompleteTextView.getItemSelectedListener());
         assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
 
-        assertNotNull(testOnItemSelectedListener);
-        mAutoCompleteTextView.setOnItemSelectedListener(testOnItemSelectedListener);
-        assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
-        assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+        mAutoCompleteTextView.setOnItemSelectedListener(mockItemSelectedListener);
+        assertSame(mockItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
+        assertSame(mockItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+        verifyZeroInteractions(mockItemSelectedListener);
 
         //re-clear listener by setOnItemClickListener
         mAutoCompleteTextView.setOnItemSelectedListener(null);
         assertNull(mAutoCompleteTextView.getItemSelectedListener());
         assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
+        verifyZeroInteractions(mockItemSelectedListener);
     }
 
     @UiThreadTest
@@ -247,73 +276,130 @@
 
     @UiThreadTest
     public void testOnTextChanged() {
-        MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+        final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+        mAutoCompleteTextView.addTextChangedListener(mockTextWatcher);
+        verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+                anyInt(), anyInt(), anyInt());
 
-        assertFalse(autoCompleteTextView.isOnTextChanged());
-        assertEquals("", autoCompleteTextView.getLastChangeText());
-        assertEquals("", autoCompleteTextView.getText().toString());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(0, autoCompleteTextView.getBefore());
-        assertEquals(0, autoCompleteTextView.getAfter());
-
-        autoCompleteTextView.setText(STRING_TEST);
-        assertEquals(STRING_TEST, autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
-        assertEquals(STRING_TEST, autoCompleteTextView.getLastChangeText());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(0, autoCompleteTextView.getBefore());
-        assertEquals(STRING_TEST.length(), autoCompleteTextView.getAfter());
+        mAutoCompleteTextView.setText(STRING_TEST);
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_TEST),
+                eq(0), eq(0), eq(STRING_TEST.length()));
 
         // Test replacing text.
-        autoCompleteTextView.resetStatus();
-        autoCompleteTextView.setText(STRING_CHECK);
-        assertEquals(STRING_CHECK, autoCompleteTextView.getText().toString());
-        assertEquals(STRING_CHECK, autoCompleteTextView.getLastChangeText());
-        assertEquals(0, autoCompleteTextView.getStart());
-        assertEquals(STRING_TEST.length(), autoCompleteTextView.getBefore());
-        assertEquals(STRING_CHECK.length(), autoCompleteTextView.getAfter());
+        mAutoCompleteTextView.setText(STRING_CHECK);
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_CHECK),
+                eq(0), eq(STRING_TEST.length()), eq(STRING_CHECK.length()));
     }
 
-    @UiThreadTest
-    public void testPopupWindow() throws XmlPullParserException, IOException {
-        assertFalse(mAutoCompleteTextView.isPopupShowing());
-        mAutoCompleteTextView.showDropDown();
-        assertTrue(mAutoCompleteTextView.isPopupShowing());
+    public void testPopupWindow() {
+        final AutoCompleteTextView.OnDismissListener mockDismissListener =
+                mock(AutoCompleteTextView.OnDismissListener.class);
+        mAutoCompleteTextView.setOnDismissListener(mockDismissListener);
 
-        mAutoCompleteTextView.dismissDropDown();
         assertFalse(mAutoCompleteTextView.isPopupShowing());
-
-        mAutoCompleteTextView.showDropDown();
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockDismissListener);
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+        verify(mockDismissListener, times(1)).onDismiss();
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verify(mockDismissListener, times(1)).onDismiss();
 
         final MockValidator validator = new MockValidator();
         mAutoCompleteTextView.setValidator(validator);
-        mAutoCompleteTextView.requestFocus();
-        mAutoCompleteTextView.showDropDown();
-        assertTrue(mAutoCompleteTextView.isPopupShowing());
-        mAutoCompleteTextView.setText(STRING_TEST);
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
+            mAutoCompleteTextView.setText(STRING_TEST);
+        });
         assertEquals(STRING_TEST, mAutoCompleteTextView.getText().toString());
+
         // clearFocus will trigger onFocusChanged, and onFocusChanged will validate the text.
-        mAutoCompleteTextView.clearFocus();
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.clearFocus());
         assertFalse(mAutoCompleteTextView.isPopupShowing());
         assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString());
+        verify(mockDismissListener, times(2)).onDismiss();
+
+        verifyNoMoreInteractions(mockDismissListener);
+    }
+
+    public void testDropDownMetrics() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_width);
+        final int dropDownHeight =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_height);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_v);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setDropDownWidth(dropDownWidth);
+            mAutoCompleteTextView.setDropDownHeight(dropDownHeight);
+            mAutoCompleteTextView.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mAutoCompleteTextView.setDropDownVerticalOffset(dropDownOffsetVertical);
+
+            mAutoCompleteTextView.showDropDown();
+        });
+
+        assertEquals(dropDownWidth, mAutoCompleteTextView.getDropDownWidth());
+        assertEquals(dropDownHeight, mAutoCompleteTextView.getDropDownHeight());
+        assertEquals(dropDownOffsetHorizontal, mAutoCompleteTextView.getDropDownHorizontalOffset());
+        assertEquals(dropDownOffsetVertical, mAutoCompleteTextView.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownBackground() {
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setDropDownBackgroundResource(R.drawable.blue_fill);
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        Drawable dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.BLUE, 1, true);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.dismissDropDown();
+            mAutoCompleteTextView.setDropDownBackgroundDrawable(
+                    mActivity.getDrawable(R.drawable.yellow_fill));
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.YELLOW, 1, true);
     }
 
     @UiThreadTest
     public void testReplaceText() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+        final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+        autoCompleteTextView.addTextChangedListener(mockTextWatcher);
+        verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+                anyInt(), anyInt(), anyInt());
 
-        assertEquals("", autoCompleteTextView.getText().toString());
-        assertFalse(autoCompleteTextView.isOnTextChanged());
         autoCompleteTextView.replaceText("Text");
         assertEquals("Text", autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Text"),
+                eq(0), eq(0), eq("Text".length()));
 
-        autoCompleteTextView.resetStatus();
-        assertFalse(autoCompleteTextView.isOnTextChanged());
         autoCompleteTextView.replaceText("Another");
         assertEquals("Another", autoCompleteTextView.getText().toString());
-        assertTrue(autoCompleteTextView.isOnTextChanged());
+        verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Another"),
+                eq(0), eq("Text".length()), eq("Another".length()));
     }
 
     @UiThreadTest
@@ -342,21 +428,17 @@
     }
 
     public void testGetThreshold() {
-        final AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) mActivity
-                .findViewById(R.id.autocompletetv_edit);
-        assertNotNull(autoCompleteTextView);
-
-        assertEquals(1, autoCompleteTextView.getThreshold());
-        autoCompleteTextView.setThreshold(3);
-        assertEquals(3, autoCompleteTextView.getThreshold());
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(3);
+        assertEquals(3, mAutoCompleteTextView.getThreshold());
 
         // Test negative value input
-        autoCompleteTextView.setThreshold(-5);
-        assertEquals(1, autoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(-5);
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
 
         // Test zero
-        autoCompleteTextView.setThreshold(0);
-        assertEquals(1, autoCompleteTextView.getThreshold());
+        mAutoCompleteTextView.setThreshold(0);
+        assertEquals(1, mAutoCompleteTextView.getThreshold());
     }
 
     public void testAccessValidater() {
@@ -371,7 +453,7 @@
         assertNull(mAutoCompleteTextView.getValidator());
     }
 
-    public void testOnFilterComplete() throws Throwable {
+    public void testOnFilterComplete() {
         // Set Threshold to 4 characters
         mAutoCompleteTextView.setThreshold(4);
 
@@ -384,22 +466,15 @@
         }
 
         // Test the filter if the input string is not long enough to threshold
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.setText("");
                 mAutoCompleteTextView.requestFocus();
-            }
         });
         mInstrumentation.sendStringSync(testString);
 
         // onFilterComplete will close the popup.
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
 
         if (mNumeric) {
             // "that" in case of 12-key(NUMERIC) keyboard
@@ -408,20 +483,13 @@
             testString = "that";
         }
         mInstrumentation.sendStringSync(testString);
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return !mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
 
         // Test the expected filter matching scene
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setFocusable(true);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.setText("");
-            }
         });
         if (mNumeric) {
             // "test" in case of 12-key(NUMERIC) keyboard
@@ -431,20 +499,14 @@
         }
         assertTrue(mAutoCompleteTextView.hasFocus());
         assertTrue(mAutoCompleteTextView.hasWindowFocus());
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return mAutoCompleteTextView.isPopupShowing();
-            }
-        }.run();
+        PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing());
     }
 
-    public void testPerformFiltering() throws Throwable {
+    public void testPerformFiltering() {
         if (isTvMode()) {
             return;
         }
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.setValidator(mValidator);
 
@@ -452,7 +514,6 @@
                 mAutoCompleteTextView.setFocusable(true);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.showDropDown();
-            }
         });
         mInstrumentation.waitForIdleSync();
         assertTrue(mAutoCompleteTextView.isPopupShowing());
@@ -461,11 +522,9 @@
         // KeyBack will close the popup.
         assertFalse(mAutoCompleteTextView.isPopupShowing());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.dismissDropDown();
                 mAutoCompleteTextView.setText(STRING_TEST);
-            }
         });
         mInstrumentation.waitForIdleSync();
 
@@ -478,12 +537,10 @@
                 android.R.layout.simple_dropdown_item_1line, WORDS);
 
         // Set Threshold to 4 charactersonKeyDown
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setAdapter(adapter);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.setText("");
-            }
         });
         mInstrumentation.waitForIdleSync();
         // Create and get the filter.
@@ -495,38 +552,27 @@
         if (mNumeric) {
             // "numeric" in case of 12-key(NUMERIC) keyboard
             mInstrumentation.sendStringSync("6688633777444222");
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return "numeric".equals(filter.getResult());
-                }
-            }.run();
+            PollingCheck.waitFor(() -> "numeric".equals(filter.getResult()));
         } else {
-            Thread.sleep(200);
+            SystemClock.sleep(200);
             mInstrumentation.sendStringSync(STRING_TEST);
-            new PollingCheck() {
-                @Override
-                protected boolean check() {
-                    return STRING_TEST.equals(filter.getResult());
-                }
-            }.run();
+            PollingCheck.waitFor(() -> STRING_TEST.equals(filter.getResult()));
         }
     }
 
-    public void testPerformCompletion() throws Throwable {
+    public void testPerformCompletionWithDPad() {
         if (isTvMode()) {
             return;
         }
-        final MockOnItemClickListener listener = new MockOnItemClickListener();
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.setOnItemClickListener(listener);
-                mAutoCompleteTextView.setAdapter(mAdapter);
-                mAutoCompleteTextView.requestFocus();
-                mAutoCompleteTextView.showDropDown();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
         });
         mInstrumentation.waitForIdleSync();
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
@@ -535,54 +581,112 @@
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
         mInstrumentation.waitForIdleSync();
-        assertTrue(listener.isOnItemClicked());
-
+        verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(0), eq(0L));
         assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
 
-        // re-set 'clicked' flag to false
-        listener.clearItemClickedStatus();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.showDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         mInstrumentation.waitForIdleSync();
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
-        assertTrue(listener.isOnItemClicked());
+        verify(mockItemClickListener, times(2)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(0), eq(0L));
         assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        listener.clearItemClickedStatus();
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.showDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         // Test normal key code.
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
-        assertFalse(listener.isOnItemClicked());
+        verifyNoMoreInteractions(mockItemClickListener);
         assertNotSame("", mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
-        listener.clearItemClickedStatus();
-
         // Test the method on the scene of popup is closed.
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-               mAutoCompleteTextView.dismissDropDown();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
 
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
-        assertFalse(listener.isOnItemClicked());
+        verifyNoMoreInteractions(mockItemClickListener);
         assertNotSame("", mAutoCompleteTextView.getText().toString());
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
     }
 
+    public void testPerformCompletionExplicit() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+        // Create a custom watcher that checks isPerformingCompletion to return true
+        // in the "middle" of the performCompletion processing. We also spy on this watcher
+        // to make sure that its onTextChanged is invoked.
+        final TextWatcher myTextWatcher = new MyTextWatcher(WORDS[1]);
+        final TextWatcher spyTextWatcher = spy(myTextWatcher);
+        mAutoCompleteTextView.addTextChangedListener(spyTextWatcher);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+            mAutoCompleteTextView.requestFocus();
+            mAutoCompleteTextView.showDropDown();
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.performCompletion());
+        verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+                eq(1), eq(1L));
+        assertEquals(WORDS[1], mAutoCompleteTextView.getText().toString());
+        assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        verify(spyTextWatcher, atLeastOnce()).onTextChanged(TestUtils.sameCharSequence(WORDS[1]),
+                eq(0), eq(0), eq(WORDS[1].length()));
+        verifyNoMoreInteractions(mockItemClickListener);
+    }
+
+    public void testSetTextWithCompletion() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", true));
+        mInstrumentation.waitForIdleSync();
+
+        assertTrue(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockItemClickListener);
+    }
+
+    public void testSetTextWithNoCompletion() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+            mAutoCompleteTextView.setAdapter(mAdapter);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+        mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", false));
+        mInstrumentation.waitForIdleSync();
+
+        assertFalse(mAutoCompleteTextView.isPopupShowing());
+        verifyZeroInteractions(mockItemClickListener);
+    }
+
     @UiThreadTest
     public void testPerformValidation() {
         final CharSequence text = "this";
@@ -596,41 +700,27 @@
         mAutoCompleteTextView.setValidator(null);
     }
 
-    public void testSetCompletionHint() {
+    public void testAccessCompletionHint() {
         mAutoCompleteTextView.setCompletionHint("TEST HINT");
+        assertEquals("TEST HINT", mAutoCompleteTextView.getCompletionHint());
+
+        mAutoCompleteTextView.setCompletionHint(null);
+        assertNull(mAutoCompleteTextView.getCompletionHint());
     }
 
-    public void testOnAttachedToWindow() {
-        // implement details, do not test
-    }
+    public void testAccessListSelection() {
+        final AdapterView.OnItemClickListener mockItemClickListener =
+                mock(AdapterView.OnItemClickListener.class);
 
-    public void testOnCommitCompletion() {
-        // implement details, do not test
-    }
-
-    public void testOnDetachedFromWindow() {
-        // implement details, do not test
-    }
-
-    public void testOnKeyPreIme() {
-        // implement details, do not test
-    }
-
-    public void testAccessListSelection() throws Throwable {
-        final MockOnItemClickListener listener = new MockOnItemClickListener();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mAutoCompleteTextView.setOnItemClickListener(listener);
+        mInstrumentation.runOnMainSync(() -> {
+                mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
                 mAutoCompleteTextView.setAdapter(mAdapter);
                 mAutoCompleteTextView.requestFocus();
                 mAutoCompleteTextView.showDropDown();
-            }
         });
         mInstrumentation.waitForIdleSync();
 
-        runTestOnUiThread(new Runnable() {
-            public void run() {
+        mInstrumentation.runOnMainSync(() -> {
                 mAutoCompleteTextView.setListSelection(1);
                 assertEquals(1, mAutoCompleteTextView.getListSelection());
 
@@ -639,7 +729,6 @@
 
                 mAutoCompleteTextView.clearListSelection();
                 assertEquals(2, mAutoCompleteTextView.getListSelection());
-            }
         });
         mInstrumentation.waitForIdleSync();
     }
@@ -660,75 +749,25 @@
         assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, mAutoCompleteTextView.getDropDownWidth());
     }
 
-    private static class MockOnItemClickListener implements AdapterView.OnItemClickListener {
-        private boolean mOnItemClickedFlag = false;
-
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            mOnItemClickedFlag = true;
-            return;
-        }
-
-        public boolean isOnItemClicked() {
-            return mOnItemClickedFlag;
-        }
-
-        public void clearItemClickedStatus() {
-            mOnItemClickedFlag = false;
-        }
-    }
-
-    private static class MockOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            return;
-        }
-
-        public void onNothingSelected(AdapterView<?> parent) {
-            return;
-        }
-    }
-
     private class MockValidator implements AutoCompleteTextView.Validator {
         public CharSequence fixText(CharSequence invalidText) {
             return STRING_VALIDATED;
         }
 
         public boolean isValid(CharSequence text) {
-            if (text == STRING_TEST) {
-                return true;
-            }
-            return false;
+            return (text == STRING_TEST);
         }
     }
 
-    private static class MockAutoCompleteTextView extends AutoCompleteTextView {
-        private boolean mOnTextChangedFlag = false;
-        private boolean mOnFilterCompleteFlag = false;
-        private String lastChangeText = "";
-        private int mStart = 0;
-        private int mBefore = 0;
-        private int mAfter = 0;
-
-        public void resetStatus() {
-            mOnTextChangedFlag = false;
-            mOnFilterCompleteFlag = false;
-            mStart = 0;
-            mBefore = 0;
-            mAfter = 0;
-        }
-
+    protected static class MockAutoCompleteTextView extends AutoCompleteTextView {
         public MockAutoCompleteTextView(Context context) {
             super(context);
-            resetStatus();
         }
 
         public MockAutoCompleteTextView(Context context, AttributeSet attrs) {
             super(context, attrs);
         }
 
-        protected MockAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
-            super(context, attrs, defStyle);
-        }
-
         @Override
         protected CharSequence convertSelectionToString(Object selectedItem) {
             return super.convertSelectionToString(selectedItem);
@@ -745,16 +784,6 @@
         }
 
         @Override
-        protected void onTextChanged(CharSequence text, int start, int before, int after) {
-            super.onTextChanged(text, start, before, after);
-            mOnTextChangedFlag = true;
-            lastChangeText = text.toString();
-            mStart = start;
-            mBefore = before;
-            mAfter = after;
-        }
-
-        @Override
         protected void performFiltering(CharSequence text, int keyCode) {
             super.performFiltering(text, keyCode);
         }
@@ -768,36 +797,6 @@
         protected boolean setFrame(int l, int t, int r, int b) {
             return super.setFrame(l, t, r, b);
         }
-
-        @Override
-        public void onFilterComplete(int count) {
-            super.onFilterComplete(count);
-            mOnFilterCompleteFlag = true;
-        }
-
-        protected boolean isOnTextChanged() {
-            return mOnTextChangedFlag;
-        }
-
-        protected String getLastChangeText() {
-            return lastChangeText;
-        }
-
-        protected boolean isOnFilterComplete() {
-            return mOnFilterCompleteFlag;
-        }
-
-        protected int getStart() {
-            return mStart;
-        }
-
-        protected int getBefore() {
-            return mBefore;
-        }
-
-        protected int getAfter() {
-            return mAfter;
-        }
     }
 
     private static class MockFilter extends Filter {
diff --git a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
index 31ad341..283a515 100644
--- a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
@@ -18,14 +18,22 @@
 
 import android.annotation.ColorInt;
 import android.app.Instrumentation;
+import android.graphics.Rect;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
 import android.widget.CalendarView;
+import android.widget.ScrollView;
 import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 
+import static org.mockito.Mockito.*;
+
 @MediumTest
 public class CalendarViewTest extends ActivityInstrumentationTestCase2<CalendarViewCtsActivity> {
     private CalendarViewCtsActivity mActivity;
@@ -103,6 +111,64 @@
         assertEquals(mCalendarViewMaterial.getMaxDate(), maxDate);
     }
 
+    private void verifyOnDateChangeListener(CalendarView calendarView,
+            boolean onlyAllowOneChangeEvent) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        final CalendarView.OnDateChangeListener mockDateChangeListener =
+                mock(CalendarView.OnDateChangeListener.class);
+        calendarView.setOnDateChangeListener(mockDateChangeListener);
+
+        // Go back to September 2008
+        final Calendar calendar = new GregorianCalendar();
+        calendar.set(Calendar.YEAR, 2008);
+        calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+        calendar.set(Calendar.DAY_OF_MONTH, 16);
+        instrumentation.runOnMainSync(
+                () -> calendarView.setDate(calendar.getTime().getTime(), false, true));
+        instrumentation.waitForIdleSync();
+
+        // Get bounds of 09/23/2008
+        calendar.set(Calendar.DAY_OF_MONTH, 23);
+        final Rect dayBounds = new Rect();
+        final boolean getDayBoundsSuccess = calendarView.getBoundsForDate(
+                calendar.getTime().getTime(), dayBounds);
+        assertTrue(getDayBoundsSuccess);
+
+        if (onlyAllowOneChangeEvent) {
+            verifyZeroInteractions(mockDateChangeListener);
+        }
+
+        // Use instrumentation to emulate a tap on 09/23/2008
+        ViewTestUtils.emulateTapOnScreen(instrumentation, calendarView,
+                dayBounds.left + dayBounds.width() / 2,
+                dayBounds.top + dayBounds.height() / 2);
+
+        verify(mockDateChangeListener, times(1)).onSelectedDayChange(calendarView,
+                2008, Calendar.SEPTEMBER, 23);
+        if (onlyAllowOneChangeEvent) {
+            verifyNoMoreInteractions(mockDateChangeListener);
+        }
+    }
+
+    public void testOnDateChangeListenerHolo() {
+        // Scroll the Holo calendar view all the way up so it's fully visible
+        final ScrollView scroller = (ScrollView) mActivity.findViewById(R.id.scroller);
+        final ViewGroup container = (ViewGroup) scroller.findViewById(R.id.container);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> scroller.scrollTo(0, container.getHeight()));
+        // Note that in pre-Material world we are "allowing" the CalendarView to notify
+        // the date change listener on multiple occasions. This is the old behavior of the widget.
+        verifyOnDateChangeListener(mCalendarViewHolo, false);
+    }
+
+    public void testOnDateChangeListenerMaterial() {
+        // Note that in Material world only "real" date change events are allowed to be reported
+        // to our listener. This is the new behavior of the widget.
+        verifyOnDateChangeListener(mCalendarViewMaterial, true);
+    }
+
     public void testAppearanceMaterial() {
         // The logic in this method is performed on a Material-styled CalendarView and
         // non-deprecated attributes / visual appearance APIs
@@ -118,12 +184,12 @@
 
         // Change the visual appearance of the widget
         instrumentation.runOnMainSync(() -> {
-            mCalendarViewMaterial.setFirstDayOfWeek(3);
+            mCalendarViewMaterial.setFirstDayOfWeek(Calendar.TUESDAY);
             mCalendarViewMaterial.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
             mCalendarViewMaterial.setWeekDayTextAppearance(R.style.TextAppearance_WithColorMagenta);
         });
 
-        assertEquals(3, mCalendarViewMaterial.getFirstDayOfWeek());
+        assertEquals(Calendar.TUESDAY, mCalendarViewMaterial.getFirstDayOfWeek());
         assertEquals(R.style.TextAppearance_WithColorBlue,
                 mCalendarViewMaterial.getDateTextAppearance());
         assertEquals(R.style.TextAppearance_WithColorMagenta,
@@ -166,7 +232,7 @@
                 mActivity.getColor(R.color.calendarview_week_separatorline_new);
 
         instrumentation.runOnMainSync(() -> {
-            mCalendarViewHolo.setFirstDayOfWeek(1);
+            mCalendarViewHolo.setFirstDayOfWeek(Calendar.SUNDAY);
             mCalendarViewHolo.setShownWeekCount(4);
             mCalendarViewHolo.setShowWeekNumber(true);
             mCalendarViewHolo.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
@@ -178,7 +244,7 @@
             mCalendarViewHolo.setWeekSeparatorLineColor(newWeekSeparatorLineColor);
         });
 
-        assertEquals(1, mCalendarViewHolo.getFirstDayOfWeek());
+        assertEquals(Calendar.SUNDAY, mCalendarViewHolo.getFirstDayOfWeek());
         assertEquals(4, mCalendarViewHolo.getShownWeekCount());
         assertTrue(mCalendarViewHolo.getShowWeekNumber());
         assertEquals(R.style.TextAppearance_WithColorBlue,
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
new file mode 100644
index 0000000..9ad0b23
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.CheckBox;
+
+/**
+ * A minimal application for {@link CheckBox} test.
+ */
+public class CheckBoxCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.checkbox_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
index b3a6e67..083ae96 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
@@ -16,24 +16,41 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.widget.CheckBox;
+import android.widget.cts.util.ViewTestUtils;
 
-public class CheckBoxTest extends AndroidTestCase {
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class CheckBoxTest extends ActivityInstrumentationTestCase2<CheckBoxCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private CheckBox mCheckBox;
+
+    public CheckBoxTest() {
+        super("android.widget.cts", CheckBoxCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mCheckBox = (CheckBox) mActivity.findViewById(R.id.check_box);
+    }
+
     public void testConstructor() {
-        XmlPullParser parser = mContext.getResources().getXml(R.layout.checkbox_layout);
-        AttributeSet mAttrSet = Xml.asAttributeSet(parser);
-
-        new CheckBox(mContext, mAttrSet, 0);
-        new CheckBox(mContext, mAttrSet);
-        new CheckBox(mContext);
+        new CheckBox(mActivity);
+        new CheckBox(mActivity, null);
+        new CheckBox(mActivity, null, android.R.attr.checkboxStyle);
+        new CheckBox(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CompoundButton_CheckBox);
 
         try {
             new CheckBox(null, null, -1);
@@ -56,4 +73,109 @@
             // expected, test success.
         }
     }
+
+    public void testText() {
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.hello_world), mCheckBox.getText()));
+
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setText("new text"));
+        assertTrue(TextUtils.equals("new text", mCheckBox.getText()));
+
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setText(R.string.text_name));
+        assertTrue(TextUtils.equals(mActivity.getString(R.string.text_name), mCheckBox.getText()));
+    }
+
+    public void testAccessChecked() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // not checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+        verifyZeroInteractions(mockCheckedChangeListener);
+        assertFalse(mCheckBox.isChecked());
+
+        // not checked -> checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // checked -> checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaApi() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // toggle to checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // toggle to not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaEmulatedTap() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // tap to checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // tap to not checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaPerformClick() {
+        final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(CheckBox.OnCheckedChangeListener.class);
+        mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mCheckBox.isChecked());
+
+        // click to checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+        assertTrue(mCheckBox.isChecked());
+
+        // click to not checked
+        mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+        assertFalse(mCheckBox.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
index 52bef54..066697a 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
@@ -16,13 +16,12 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.CheckedTextView;
 
 /**
- * A minimal application for CheckedTextView test.
+ * A minimal application for {@link CheckedTextView} test.
  */
 public class CheckedTextViewCtsActivity extends Activity {
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
index 039ca70..0240d61 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
@@ -16,17 +16,17 @@
 
 package android.widget.cts;
 
-import android.os.Parcelable;
-import android.widget.cts.R;
-
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.StateSet;
 import android.view.View;
@@ -35,14 +35,19 @@
 import android.widget.CheckedTextView;
 import android.widget.ListAdapter;
 import android.widget.ListView;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 import java.util.Arrays;
 
+@SmallTest
 public class CheckedTextViewTest extends
         ActivityInstrumentationTestCase2<CheckedTextViewCtsActivity> {
-    private Resources mResources;
-    private Activity mActivity;
     private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private ListView mListView;
+    private CheckedTextView mCheckedTextView;
+    private Parcelable mState;
 
     public CheckedTextViewTest() {
         super("android.widget.cts", CheckedTextViewCtsActivity.class);
@@ -51,32 +56,36 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mActivity = getActivity();
+
         mInstrumentation = getInstrumentation();
-        mResources = mActivity.getResources();
+        mActivity = getActivity();
+        mListView = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+        mCheckedTextView = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
     }
 
     public void testConstructor() {
-        new MockCheckedTextView(mActivity, null, 0);
-        new MockCheckedTextView(mActivity, null);
-        new MockCheckedTextView(mActivity);
+        new CheckedTextView(mActivity);
+        new CheckedTextView(mActivity, null);
+        new CheckedTextView(mActivity, null, android.R.attr.checkedTextViewStyle);
+        new CheckedTextView(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CheckedTextView);
 
         try {
-            new MockCheckedTextView(null, null, -1);
+            new CheckedTextView(null, null, -1);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
         }
 
         try {
-            new MockCheckedTextView(null, null);
+            new CheckedTextView(null, null);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
         }
 
         try {
-            new MockCheckedTextView(null);
+            new CheckedTextView(null);
             fail("Should throw NullPointerException.");
         } catch (NullPointerException e) {
             // expected, test success.
@@ -84,35 +93,29 @@
     }
 
     public void testChecked() {
-        final ListView lv = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setAdapter(new CheckedTextViewAdapter());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setAdapter(new CheckedTextViewAdapter());
-
-                lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-                lv.setItemChecked(1, true);
-            }
+            mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+            mListView.setItemChecked(1, true);
         });
         mInstrumentation.waitForIdleSync();
 
-        assertEquals(1, lv.getCheckedItemPosition());
-        assertTrue(lv.isItemChecked(1));
-        assertFalse(lv.isItemChecked(0));
+        assertEquals(1, mListView.getCheckedItemPosition());
+        assertTrue(mListView.isItemChecked(1));
+        assertFalse(mListView.isItemChecked(0));
 
-        ListAdapter adapter = lv.getAdapter();
-        CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
-        CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
-        CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
+        final ListAdapter adapter = mListView.getAdapter();
+        final CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
+        final CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
+        final CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
         assertFalse(view0.isChecked());
         assertTrue(view1.isChecked());
         assertFalse(view2.isChecked());
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-                lv.setItemChecked(2, true);
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+            mListView.setItemChecked(2, true);
         });
         mInstrumentation.waitForIdleSync();
         assertFalse(view0.isChecked());
@@ -128,184 +131,219 @@
     }
 
     public void testToggle() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        assertFalse(checkedTextView.isChecked());
+        assertFalse(mCheckedTextView.isChecked());
 
-        checkedTextView.toggle();
-        assertTrue(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+        assertTrue(mCheckedTextView.isChecked());
 
-        checkedTextView.toggle();
-        assertFalse(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+        assertFalse(mCheckedTextView.isChecked());
 
-        checkedTextView.setChecked(true);
-        checkedTextView.toggle();
-        assertFalse(checkedTextView.isChecked());
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setChecked(true);
+            mCheckedTextView.toggle();
+        });
+        assertFalse(mCheckedTextView.isChecked());
     }
 
     public void testDrawableStateChanged() {
         MockCheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
 
-        checkedTextView.reset();
         assertFalse(checkedTextView.hasDrawableStateChanged());
         checkedTextView.refreshDrawableState();
         assertTrue(checkedTextView.hasDrawableStateChanged());
     }
 
     public void testSetPadding() {
-        final CheckedTextView lv
-                = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
-        assertNotNull(lv);
-
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setPadding(1, 2, 3, 4);
-                lv.requestLayout();
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setPadding(1, 2, 3, 4);
+            mListView.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
-        int origTop = lv.getPaddingTop();
-        int origBottom = lv.getPaddingBottom();
-        int origLeft = lv.getPaddingLeft();
-        int origRight = lv.getPaddingRight();
 
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                lv.setPadding(10, 20, 30, 40);
-                lv.requestLayout();
-            }
+        final int origTop = mListView.getPaddingTop();
+        final int origBottom = mListView.getPaddingBottom();
+        final int origLeft = mListView.getPaddingLeft();
+        final int origRight = mListView.getPaddingRight();
+
+        mInstrumentation.runOnMainSync(() -> {
+            mListView.setPadding(10, 20, 30, 40);
+            mListView.requestLayout();
         });
         mInstrumentation.waitForIdleSync();
-        assertTrue(origTop < lv.getPaddingTop());
-        assertTrue(origBottom < lv.getPaddingBottom());
-        assertTrue(origLeft < lv.getPaddingLeft());
-        assertTrue(origRight < lv.getPaddingRight());
+
+        assertTrue(origTop < mListView.getPaddingTop());
+        assertTrue(origBottom < mListView.getPaddingBottom());
+        assertTrue(origLeft < mListView.getPaddingLeft());
+        assertTrue(origRight < mListView.getPaddingRight());
     }
 
     private void cleanUpForceLayoutFlags(View view) {
         if (view != null) {
-            view.layout(0, 0, 0, 0);
+            mInstrumentation.runOnMainSync(() -> view.layout(0, 0, 0, 0));
             assertFalse(view.isLayoutRequested());
         }
     }
 
     public void testSetCheckMarkDrawableByDrawable() {
-        CheckedTextView checkedTextView;
         int basePaddingRight = 10;
 
         // set drawable when checkedTextView is GONE
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setVisibility(View.GONE);
-        Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setVisibility(View.GONE));
+        final Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
         firstDrawable.setVisible(true, false);
         assertEquals(StateSet.WILD_CARD, firstDrawable.getState());
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(firstDrawable);
-        assertEquals(firstDrawable.getIntrinsicWidth(), checkedTextView.getPaddingRight());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(firstDrawable));
+        assertEquals(firstDrawable.getIntrinsicWidth(), mCheckedTextView.getPaddingRight());
         assertFalse(firstDrawable.isVisible());
-        assertTrue(Arrays.equals(checkedTextView.getDrawableState(), firstDrawable.getState()));
-        assertTrue(checkedTextView.isLayoutRequested());
+        assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), firstDrawable.getState()));
+        assertTrue(mCheckedTextView.isLayoutRequested());
+
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
 
         // update drawable when checkedTextView is VISIBLE
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setVisibility(View.VISIBLE);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setVisibility(View.VISIBLE);
+            mCheckedTextView.setPadding(0, 0, basePaddingRight, 0);
+        });
+        final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
         secondDrawable.setVisible(true, false);
         assertEquals(StateSet.WILD_CARD, secondDrawable.getState());
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(secondDrawable);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
         assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
+                mCheckedTextView.getPaddingRight());
         assertTrue(secondDrawable.isVisible());
-        assertTrue(Arrays.equals(checkedTextView.getDrawableState(), secondDrawable.getState()));
-        assertTrue(checkedTextView.isLayoutRequested());
+        assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), secondDrawable.getState()));
+        assertTrue(mCheckedTextView.isLayoutRequested());
 
-        cleanUpForceLayoutFlags(checkedTextView);
-        checkedTextView.setCheckMarkDrawable(null);
-        assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+        cleanUpForceLayoutFlags(mCheckedTextView);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
+        assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
     }
 
     public void testSetCheckMarkDrawableById() {
-        CheckedTextView checkedTextView;
         int basePaddingRight = 10;
 
         // set drawable
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
-        cleanUpForceLayoutFlags(checkedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+        Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
         assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
 
         // set the same drawable again
-        cleanUpForceLayoutFlags(checkedTextView);
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        cleanUpForceLayoutFlags(mCheckedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
         assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertFalse(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertFalse(mCheckedTextView.isLayoutRequested());
 
         // update drawable
-        Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
-        checkedTextView.setCheckMarkDrawable(secondDrawable);
+        final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
         assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
-                checkedTextView.getPaddingRight());
-        assertTrue(checkedTextView.isLayoutRequested());
+                mCheckedTextView.getPaddingRight());
+        assertTrue(mCheckedTextView.isLayoutRequested());
+
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
 
         // resId is 0
-        checkedTextView = new MockCheckedTextView(mActivity);
-        checkedTextView.setPadding(0, 0, basePaddingRight, 0);
-        cleanUpForceLayoutFlags(checkedTextView);
+        mInstrumentation.runOnMainSync(
+                () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
-        checkedTextView.setCheckMarkDrawable(0);
-        assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
-        assertFalse(checkedTextView.isLayoutRequested());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(0));
+        assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+        assertFalse(mCheckedTextView.isLayoutRequested());
     }
 
     public void testSetCheckMarkByMixedTypes() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        cleanUpForceLayoutFlags(checkedTextView);
+        cleanUpForceLayoutFlags(mCheckedTextView);
 
         // Specifically test for b/22626247 (AOSP issue 180455).
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
-        checkedTextView.setCheckMarkDrawable(null);
-        checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
-        assertNotNull(checkedTextView.getCheckMarkDrawable());
+        mInstrumentation.runOnMainSync(() -> {
+            mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+            mCheckedTextView.setCheckMarkDrawable(null);
+            mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+        });
+        assertNotNull(mCheckedTextView.getCheckMarkDrawable());
     }
 
     public void testAccessInstanceState() {
-        CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
-        Parcelable state;
+        assertFalse(mCheckedTextView.isChecked());
+        assertFalse(mCheckedTextView.getFreezesText());
 
-        assertFalse(checkedTextView.isChecked());
-        assertFalse(checkedTextView.getFreezesText());
+        mInstrumentation.runOnMainSync(() -> mState = mCheckedTextView.onSaveInstanceState());
+        assertNotNull(mState);
+        assertFalse(mCheckedTextView.getFreezesText());
 
-        state = checkedTextView.onSaveInstanceState();
-        assertNotNull(state);
-        assertFalse(checkedTextView.getFreezesText());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
 
-        checkedTextView.setChecked(true);
-
-        checkedTextView.onRestoreInstanceState(state);
-        assertFalse(checkedTextView.isChecked());
-        assertTrue(checkedTextView.isLayoutRequested());
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.onRestoreInstanceState(mState));
+        assertFalse(mCheckedTextView.isChecked());
+        assertTrue(mCheckedTextView.isLayoutRequested());
     }
 
-    public void testOnDraw() {
-        // Do not test. Implementation details.
-    }
+    public void testCheckMarkTinting() {
+        mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_red));
 
-    public void testOnCreateDrawableState() {
-        // Do not test. Implementation details.
+        Drawable checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Initial state is red", checkMark,
+                checkMark.getBounds().width(), checkMark.getBounds().height(), false,
+                Color.RED, 1, true);
+
+        // With SRC_IN we're expecting the translucent tint color to "take over" the
+        // original red checkmark.
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView, () -> {
+            mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_IN);
+            mCheckedTextView.setCheckMarkTintList(ColorStateList.valueOf(0x8000FF00));
+        });
+
+        assertEquals(PorterDuff.Mode.SRC_IN, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                0x8000FF00, 1, true);
+
+        // With SRC_OVER we're expecting the translucent tint color to be drawn on top
+        // of the original red checkmark, creating a composite color fill as the result.
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_OVER));
+
+        assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green over full red", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x8000FF00, Color.RED), 1, true);
+
+        // Switch to a different color for the underlying checkmark and verify that the
+        // currently configured tinting (50% green overlay) is still respected
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+                () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_yellow));
+        assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+        assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+        checkMark = mCheckedTextView.getCheckMarkDrawable();
+        TestUtils.assertAllPixelsOfColor("Expected 50% green over full yellow", checkMark,
+                checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x8000FF00, Color.YELLOW), 1, true);
     }
 
     private static final class MockCheckedTextView extends CheckedTextView {
-        private boolean mHasRefreshDrawableState = false;
         private boolean mHasDrawableStateChanged = false;
 
         public MockCheckedTextView(Context context) {
@@ -320,10 +358,6 @@
             super(context, attrs, defStyle);
         }
 
-        public static int[] getSuperViewStateSet() {
-            return ENABLED_STATE_SET;
-        }
-
         @Override
         protected void drawableStateChanged() {
             super.drawableStateChanged();
@@ -340,24 +374,9 @@
             super.onDraw(canvas);
         }
 
-        @Override
-        public void refreshDrawableState() {
-            mHasRefreshDrawableState = true;
-            super.refreshDrawableState();
-        }
-
-        public boolean hasRefreshDrawableState() {
-            return mHasRefreshDrawableState;
-        }
-
         public boolean hasDrawableStateChanged() {
             return mHasDrawableStateChanged;
         }
-
-        public void reset() {
-            mHasRefreshDrawableState = false;
-            mHasDrawableStateChanged = false;
-        }
     }
 
     private class CheckedTextViewAdapter extends BaseAdapter {
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
new file mode 100644
index 0000000..81e6e69
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.DatePicker;
+
+/**
+ * A minimal application for {@link DatePicker} test.
+ */
+public class DatePickerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.datepicker_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
index c48f684..f2d4c88 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
@@ -16,120 +16,223 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
+import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
-import android.content.res.XmlResourceParser;
 import android.os.Parcelable;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
-import android.util.AttributeSet;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.util.SparseArray;
-import android.util.Xml;
 import android.view.View;
 import android.widget.DatePicker;
-import android.widget.cts.util.XmlUtils;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import static org.mockito.Mockito.*;
 
 /**
  * Test {@link DatePicker}.
  */
-public class DatePickerTest extends InstrumentationTestCase {
+@MediumTest
+public class DatePickerTest extends ActivityInstrumentationTestCase2<DatePickerCtsActivity> {
+    private Activity mActivity;
+    private DatePicker mDatePickerSpinnerMode;
+    private DatePicker mDatePickerCalendarMode;
 
-    private Context mContext;
+    public DatePickerTest() {
+        super("android.widget.cts", DatePickerCtsActivity.class);
+    }
 
     @Override
-    public void setUp() {
-        mContext = getInstrumentation().getTargetContext();
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        mDatePickerSpinnerMode = (DatePicker) mActivity.findViewById(R.id.date_picker_spinner_mode);
+        mDatePickerCalendarMode =
+                (DatePicker) mActivity.findViewById(R.id.date_picker_calendar_mode);
     }
 
-    @UiThreadTest
     public void testConstructor() {
-        new DatePicker(mContext);
+        new DatePicker(mActivity);
 
-        new DatePicker(mContext, null);
+        new DatePicker(mActivity, null);
 
-        new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout));
+        new DatePicker(mActivity, null, android.R.attr.datePickerStyle);
 
-        new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout), 0);
-
-        // Test constructor with null Context, in fact, previous two functions will finally invoke
-        // this version.
-        try {
-            // Test with null Context
-            new DatePicker(null, getAttributeSet(R.layout.datepicker_layout), 0);
-            fail("should throw NullPointerException");
-        } catch (Exception e) {
-        }
+        new DatePicker(mActivity, null, 0, android.R.style.Widget_Material_Light_DatePicker);
     }
 
-    @UiThreadTest
     public void testSetEnabled() {
-        MockDatePicker datePicker = createDatePicker();
+        final Instrumentation instrumentation = getInstrumentation();
 
-        assertTrue(datePicker.isEnabled());
+        assertTrue(mDatePickerCalendarMode.isEnabled());
 
-        datePicker.setEnabled(false);
-        assertFalse(datePicker.isEnabled());
+        instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(false));
+        assertFalse(mDatePickerCalendarMode.isEnabled());
 
-        datePicker.setEnabled(true);
-        assertTrue(datePicker.isEnabled());
+        instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(true));
+        assertTrue(mDatePickerCalendarMode.isEnabled());
     }
 
-    @UiThreadTest
+    private void verifyInit(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final DatePicker.OnDateChangedListener mockDateChangeListener =
+                mock(DatePicker.OnDateChangedListener.class);
+
+        instrumentation.runOnMainSync(
+                () -> datePicker.init(2000, 10, 15, mockDateChangeListener));
+        assertEquals(2000, datePicker.getYear());
+        assertEquals(10, datePicker.getMonth());
+        assertEquals(15, datePicker.getDayOfMonth());
+
+        verifyZeroInteractions(mockDateChangeListener);
+    }
+
     public void testInit() {
-        MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
-        DatePicker datePicker = createDatePicker();
+        verifyInit(mDatePickerSpinnerMode);
+        verifyInit(mDatePickerCalendarMode);
+    }
 
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        datePicker.init(2000, 10, 15, onDateChangedListener);
+    private void verifyAccessDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final DatePicker.OnDateChangedListener mockDateChangeListener =
+                mock(DatePicker.OnDateChangedListener.class);
+
+        instrumentation.runOnMainSync(() -> datePicker.init(2000, 10, 15, mockDateChangeListener));
         assertEquals(2000, datePicker.getYear());
         assertEquals(10, datePicker.getMonth());
         assertEquals(15, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener, never()).onDateChanged(any(DatePicker.class), anyInt(),
+                anyInt(), anyInt());
+
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
+        assertEquals(1989, datePicker.getYear());
+        assertEquals(9, datePicker.getMonth());
+        assertEquals(19, datePicker.getDayOfMonth());
+        verify(mockDateChangeListener, times(1)).onDateChanged(datePicker, 1989, 9, 19);
+
+        verifyNoMoreInteractions(mockDateChangeListener);
     }
 
-    @UiThreadTest
     public void testAccessDate() {
-        DatePicker datePicker = createDatePicker();
+        verifyAccessDate(mDatePickerSpinnerMode);
+        verifyAccessDate(mDatePickerCalendarMode);
+    }
 
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
-        datePicker.init(2000, 10, 15, onDateChangedListener);
-        assertEquals(2000, datePicker.getYear());
-        assertEquals(10, datePicker.getMonth());
-        assertEquals(15, datePicker.getDayOfMonth());
+    private void verifyUpdateDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
 
-        datePicker.updateDate(1989, 9, 19);
+        instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
         assertEquals(1989, datePicker.getYear());
         assertEquals(9, datePicker.getMonth());
         assertEquals(19, datePicker.getDayOfMonth());
     }
 
-    @UiThreadTest
     public void testUpdateDate() {
-        DatePicker datePicker = createDatePicker();
+        verifyUpdateDate(mDatePickerSpinnerMode);
+        verifyUpdateDate(mDatePickerCalendarMode);
+    }
 
-        // Test normal input values
-        /* The month display uses 1-12 but our internal state stores it
-         * 0-11 so add one when setting the display.
-         */
-        datePicker.updateDate(1989, 9, 19);
-        assertEquals(1989, datePicker.getYear());
-        assertEquals(9, datePicker.getMonth());
-        assertEquals(19, datePicker.getDayOfMonth());
+    private void verifyMinMaxDate(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Use a range of minus/plus one year as min/max dates
+        final Calendar minCalendar = new GregorianCalendar();
+        minCalendar.set(Calendar.YEAR, minCalendar.get(Calendar.YEAR) - 1);
+        final Calendar maxCalendar = new GregorianCalendar();
+        maxCalendar.set(Calendar.YEAR, maxCalendar.get(Calendar.YEAR) + 1);
+
+        final long minDate = minCalendar.getTime().getTime();
+        final long maxDate = maxCalendar.getTime().getTime();
+
+        instrumentation.runOnMainSync(() -> {
+            datePicker.setMinDate(minDate);
+            datePicker.setMaxDate(maxDate);
+        });
+
+        assertEquals(datePicker.getMinDate(), minDate);
+        assertEquals(datePicker.getMaxDate(), maxDate);
+    }
+
+    public void testMinMaxDate() {
+        verifyMinMaxDate(mDatePickerSpinnerMode);
+        verifyMinMaxDate(mDatePickerCalendarMode);
+    }
+
+    private void verifyFirstDayOfWeek(DatePicker datePicker) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.TUESDAY));
+        assertEquals(Calendar.TUESDAY, datePicker.getFirstDayOfWeek());
+
+        instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.SUNDAY));
+        assertEquals(Calendar.SUNDAY, datePicker.getFirstDayOfWeek());
+    }
+
+    public void testFirstDayOfWeek() {
+        verifyFirstDayOfWeek(mDatePickerSpinnerMode);
+        verifyFirstDayOfWeek(mDatePickerCalendarMode);
+    }
+
+    public void testCalendarViewInSpinnerMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        assertNotNull(mDatePickerSpinnerMode.getCalendarView());
+
+        // Update the DatePicker and test that its CalendarView is synced to the same date
+        final Calendar calendar = new GregorianCalendar();
+        calendar.set(Calendar.YEAR, 2008);
+        calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+        calendar.set(Calendar.DAY_OF_MONTH, 23);
+        instrumentation.runOnMainSync(
+                () -> mDatePickerSpinnerMode.updateDate(
+                        calendar.get(Calendar.YEAR),
+                        calendar.get(Calendar.MONTH),
+                        calendar.get(Calendar.DAY_OF_MONTH)));
+
+        final Calendar calendarFromSpinner = new GregorianCalendar();
+        final long timeFromSpinnerCalendar = mDatePickerSpinnerMode.getCalendarView().getDate();
+        calendarFromSpinner.setTimeInMillis(timeFromSpinnerCalendar);
+
+        assertEquals(calendar.get(Calendar.YEAR), calendarFromSpinner.get(Calendar.YEAR));
+        assertEquals(calendar.get(Calendar.MONTH), calendarFromSpinner.get(Calendar.MONTH));
+        assertEquals(calendar.get(Calendar.DAY_OF_MONTH),
+                calendarFromSpinner.get(Calendar.DAY_OF_MONTH));
+    }
+
+    public void testPartsVisibilityInSpinnerMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(false));
+        assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(false));
+        assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+        assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(true));
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+        instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(true));
+        assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+        assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
     }
 
     @UiThreadTest
-    public void testOnSaveInstanceState() {
-        MockDatePicker datePicker = createDatePicker();
+    public void testAccessInstanceState() {
+        MockDatePicker datePicker = new MockDatePicker(mActivity);
 
         datePicker.updateDate(2008, 9, 10);
         SparseArray<Parcelable> container = new SparseArray<Parcelable>();
 
-        // Test onSaveHierarchyState
+        // Test saveHierarchyState -> onSaveInstanceState path
         assertEquals(View.NO_ID, datePicker.getId());
         datePicker.setId(99);
         assertFalse(datePicker.hasCalledOnSaveInstanceState());
@@ -137,43 +240,23 @@
         assertEquals(1, datePicker.getChildCount());
         assertTrue(datePicker.hasCalledOnSaveInstanceState());
 
-        // Test dispatchRestoreInstanceState
-        datePicker = createDatePicker();
+        // Test dispatchRestoreInstanceState -> onRestoreInstanceState path
+        datePicker = new MockDatePicker(mActivity);
         datePicker.setId(99);
         assertFalse(datePicker.hasCalledOnRestoreInstanceState());
         datePicker.dispatchRestoreInstanceState(container);
         assertEquals(2008, datePicker.getYear());
         assertEquals(9, datePicker.getMonth());
         assertEquals(10, datePicker.getDayOfMonth());
-
-        // Test onRestoreInstanceState
         assertTrue(datePicker.hasCalledOnRestoreInstanceState());
     }
 
-    private AttributeSet getAttributeSet(int resourceId) {
-        final XmlResourceParser parser = mContext.getResources().getXml(resourceId);
-        try {
-            XmlUtils.beginDocument(parser, "RelativeLayout");
-        } catch (Exception e) {
-            fail("Found unexpected loading process error before invoking generateLayoutParams.");
-        }
-        final AttributeSet attr = Xml.asAttributeSet(parser);
-        assertNotNull(attr);
-        return attr;
-    }
-
-    private MockDatePicker createDatePicker() {
-        MockDatePicker datePicker = new MockDatePicker(mContext,
-                getAttributeSet(R.layout.datepicker_layout));
-        return datePicker;
-    }
-
     private class MockDatePicker extends DatePicker {
         private boolean mCalledOnSaveInstanceState = false;
         private boolean mCalledOnRestoreInstanceState = false;
 
-        public MockDatePicker(Context context, AttributeSet attrs) {
-            super(context, attrs);
+        public MockDatePicker(Context context) {
+            super(context);
         }
 
         @Override
@@ -201,10 +284,4 @@
             return mCalledOnRestoreInstanceState;
         }
     }
-
-    private class MockOnDateChangedListener implements DatePicker.OnDateChangedListener {
-        public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
-
-        }
-    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
new file mode 100644
index 0000000..5f91950
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ImageButton;
+
+/**
+ * A minimal application for {@link ImageButton} test.
+ */
+public class ImageButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.imagebutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
index 05c0e3f..f1eab1e 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
@@ -16,27 +16,39 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.ImageButton;
+import android.widget.cts.util.TestUtils;
 
-public class ImageButtonTest extends AndroidTestCase {
+@SmallTest
+public class ImageButtonTest extends ActivityInstrumentationTestCase2<ImageButtonCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private ImageButton mImageButton;
+
+    public ImageButtonTest() {
+        super("android.widget.cts", ImageButtonCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mImageButton = (ImageButton) mActivity.findViewById(R.id.image_button);
+    }
+
     public void testConstructor() {
-        XmlPullParser parser = getContext().getResources().getXml(R.layout.imagebutton_test);
-        AttributeSet attrs = Xml.asAttributeSet(parser);
-        assertNotNull(attrs);
-
-        new ImageButton(getContext());
-
-        new ImageButton(getContext(), attrs);
-
-        new ImageButton(getContext(), attrs, 0);
+        new ImageButton(mActivity);
+        new ImageButton(mActivity, null);
+        new ImageButton(mActivity, null, android.R.attr.imageButtonStyle);
+        new ImageButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton);
 
         try {
             new ImageButton(null);
@@ -57,7 +69,23 @@
         }
     }
 
-    public void testOnSetAlpha() {
-        // Do not test, it's controlled by View. Implementation details.
+    public void testImageSource() {
+        Drawable imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("Default source is red", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.RED, 1, false);
+
+        mInstrumentation.runOnMainSync(() -> mImageButton.setImageResource(R.drawable.icon_green));
+        imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("New source is green", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.GREEN, 1, false);
+
+        mInstrumentation.runOnMainSync(
+                () -> mImageButton.setImageDrawable(mActivity.getDrawable(R.drawable.icon_yellow)));
+        imageButtonDrawable = mImageButton.getDrawable();
+        TestUtils.assertAllPixelsOfColor("New source is yellow", imageButtonDrawable,
+                imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+                true, Color.YELLOW, 1, false);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 4d0903a..24878ce 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -16,15 +16,20 @@
 
 package android.widget.cts;
 
-import org.xmlpull.v1.XmlPullParser;
-
+import android.annotation.ColorInt;
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
 import android.util.Xml;
+import android.view.Gravity;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
@@ -34,7 +39,10 @@
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.ListView;
 import android.widget.TextView;
-import android.widget.cts.R;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import org.xmlpull.v1.XmlPullParser;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -42,6 +50,7 @@
 /**
  * Test {@link LinearLayout}.
  */
+@SmallTest
 public class LinearLayoutTest extends ActivityInstrumentationTestCase<LinearLayoutCtsActivity> {
     private Context mContext;
     private Activity mActivity;
@@ -152,9 +161,9 @@
      */
     public void testAccessWeightSum() {
         LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
-        TextView weight02 = (TextView) mActivity.findViewById(R.id.weight_0_2);
-        TextView weight05 = (TextView) mActivity.findViewById(R.id.weight_0_5);
-        TextView weight03 = (TextView) mActivity.findViewById(R.id.weight_0_3);
+        TextView weight02 = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView weight05 = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView weight03 = (TextView) parent.findViewById(R.id.weight_0_3);
 
         assertNotNull(parent);
         assertNotNull(weight02);
@@ -399,6 +408,182 @@
         assertEquals(parent.getWidth(), rightView.getRight());
     }
 
+    public void testVerticalCenterGravityOnHorizontalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+        TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        int originalLeftViewRight = leftView.getRight();
+        int originalCenterViewLeft = centerView.getLeft();
+        int originalCenterViewRight = centerView.getRight();
+        int originalRightViewLeft = rightView.getLeft();
+
+        instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.CENTER_VERTICAL));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.CENTER_VERTICAL, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+        ViewAsserts.assertVerticalCenterAligned(parent, leftView);
+        ViewAsserts.assertVerticalCenterAligned(parent, centerView);
+        ViewAsserts.assertVerticalCenterAligned(parent, rightView);
+
+        final int parentHeight = parent.getHeight();
+
+        int verticalOffset = (parentHeight - leftView.getHeight()) / 2;
+        assertEquals(verticalOffset, leftView.getTop());
+        assertEquals(verticalOffset + leftView.getHeight(), leftView.getBottom());
+        assertEquals(0, leftView.getLeft());
+        assertEquals(originalLeftViewRight, leftView.getRight());
+
+        verticalOffset = (parentHeight - centerView.getHeight()) / 2;
+        assertEquals(verticalOffset, centerView.getTop());
+        assertEquals(verticalOffset + centerView.getHeight(), centerView.getBottom());
+        assertEquals(originalCenterViewLeft, centerView.getLeft());
+        assertEquals(originalCenterViewRight, centerView.getRight());
+
+        verticalOffset = (parentHeight - rightView.getHeight()) / 2;
+        assertEquals(verticalOffset, rightView.getTop());
+        assertEquals(verticalOffset + rightView.getHeight(), rightView.getBottom());
+        assertEquals(originalRightViewLeft, rightView.getLeft());
+        assertEquals(parent.getWidth(), rightView.getRight());
+    }
+
+    public void testBottomGravityOnHorizontalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+        TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+        TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        int originalLeftViewRight = leftView.getRight();
+        int originalCenterViewLeft = centerView.getLeft();
+        int originalCenterViewRight = centerView.getRight();
+        int originalRightViewLeft = rightView.getLeft();
+
+        instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.BOTTOM));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.BOTTOM, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+        ViewAsserts.assertBottomAligned(parent, leftView);
+        ViewAsserts.assertBottomAligned(parent, centerView);
+        ViewAsserts.assertBottomAligned(parent, rightView);
+
+        final int parentHeight = parent.getHeight();
+
+        assertEquals(parentHeight - leftView.getHeight(), leftView.getTop());
+        assertEquals(parentHeight, leftView.getBottom());
+        assertEquals(0, leftView.getLeft());
+        assertEquals(originalLeftViewRight, leftView.getRight());
+
+        assertEquals(parentHeight - centerView.getHeight(), centerView.getTop());
+        assertEquals(parentHeight, centerView.getBottom());
+        assertEquals(originalCenterViewLeft, centerView.getLeft());
+        assertEquals(originalCenterViewRight, centerView.getRight());
+
+        assertEquals(parentHeight - rightView.getHeight(), rightView.getTop());
+        assertEquals(parentHeight, rightView.getBottom());
+        assertEquals(originalRightViewLeft, rightView.getLeft());
+        assertEquals(parent.getWidth(), rightView.getRight());
+    }
+
+    public void testHorizontalCenterGravityOnVerticalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+        TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+        TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final int parentWidth = parent.getHeight();
+
+        int originalTopViewBottom = topView.getBottom();
+        int originalCenterViewTop = centerView.getTop();
+        int originalCenterViewBottom = centerView.getBottom();
+        int originalBottomViewTop = bottomView.getTop();
+
+        instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.CENTER_HORIZONTAL,
+                parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+        ViewAsserts.assertHorizontalCenterAligned(parent, topView);
+        ViewAsserts.assertHorizontalCenterAligned(parent, centerView);
+        ViewAsserts.assertHorizontalCenterAligned(parent, bottomView);
+
+        int horizontalOffset = (parentWidth - topView.getWidth()) / 2;
+        assertEquals(0, topView.getTop());
+        assertEquals(originalTopViewBottom, topView.getBottom());
+        assertEquals(horizontalOffset, topView.getLeft());
+        assertEquals(horizontalOffset + topView.getWidth(), topView.getRight());
+
+        horizontalOffset = (parentWidth - centerView.getWidth()) / 2;
+        assertEquals(originalCenterViewTop, centerView.getTop());
+        assertEquals(originalCenterViewBottom, centerView.getBottom());
+        assertEquals(horizontalOffset, centerView.getLeft());
+        assertEquals(horizontalOffset + centerView.getWidth(), centerView.getRight());
+
+        horizontalOffset = (parentWidth - bottomView.getWidth()) / 2;
+        assertEquals(originalBottomViewTop, bottomView.getTop());
+        assertEquals(parent.getHeight(), bottomView.getBottom());
+        assertEquals(horizontalOffset, bottomView.getLeft());
+        assertEquals(horizontalOffset + bottomView.getWidth(), bottomView.getRight());
+    }
+
+    public void testRightGravityOnVerticalLayout() {
+        final Instrumentation instrumentation = getInstrumentation();
+        LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+        TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+        TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+        TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final int parentWidth = parent.getHeight();
+
+        int originalTopViewBottom = topView.getBottom();
+        int originalCenterViewTop = centerView.getTop();
+        int originalCenterViewBottom = centerView.getBottom();
+        int originalBottomViewTop = bottomView.getTop();
+
+        instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.RIGHT));
+        instrumentation.waitForIdleSync();
+
+        assertEquals(Gravity.RIGHT,
+                parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+        ViewAsserts.assertRightAligned(parent, topView);
+        ViewAsserts.assertRightAligned(parent, centerView);
+        ViewAsserts.assertRightAligned(parent, bottomView);
+
+        assertEquals(0, topView.getTop());
+        assertEquals(originalTopViewBottom, topView.getBottom());
+        assertEquals(parentWidth - topView.getWidth(), topView.getLeft());
+        assertEquals(parentWidth, topView.getRight());
+
+        assertEquals(originalCenterViewTop, centerView.getTop());
+        assertEquals(originalCenterViewBottom, centerView.getBottom());
+        assertEquals(parentWidth - centerView.getWidth(), centerView.getLeft());
+        assertEquals(parentWidth, centerView.getRight());
+
+        assertEquals(originalBottomViewTop, bottomView.getTop());
+        assertEquals(parent.getHeight(), bottomView.getBottom());
+        assertEquals(parentWidth - bottomView.getWidth(), bottomView.getLeft());
+        assertEquals(parentWidth, bottomView.getRight());
+    }
+
     private void checkBounds(final ViewGroup viewGroup, final View view,
             final CountDownLatch countDownLatch, final int left, final int top,
             final int width, final int height) {
@@ -471,6 +656,523 @@
         countDownLatch3.await(500, TimeUnit.MILLISECONDS);
     }
 
+    private void verifyVisualsOfVerticalLayoutWithDivider(LinearLayout parent,
+            int expectedDividerPositionMask,
+            int expectedDividerSize, @ColorInt int expectedDividerColor,
+            int expectedDividerPadding) {
+        final int parentWidth = parent.getWidth();
+        final int parentHeight = parent.getHeight();
+
+        final boolean expectingTopDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+        final boolean expectingMiddleDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+        final boolean expectingBottomDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+        final int expectedDividerCount = (expectingTopDivider ? 1 : 0)
+                + (expectingMiddleDivider ? 1 : 0) + (expectingBottomDivider ? 1 : 0);
+
+        final int expectedChildHeight =
+                (parentHeight - expectedDividerCount * expectedDividerSize) / 2;
+
+        final int expectedTopChildTop = expectingTopDivider ? expectedDividerSize : 0;
+        TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+                new Rect(0, expectedTopChildTop, parentWidth,
+                        expectedTopChildTop + expectedChildHeight),
+                Color.BLUE, 1, true);
+
+        final int expectedBottomChildBottom =
+                expectingBottomDivider ? parentHeight - expectedDividerSize : parentHeight;
+        TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+                new Rect(0, expectedBottomChildBottom - expectedChildHeight, parentWidth,
+                        expectedBottomChildBottom),
+                Color.GREEN, 1, true);
+
+        if (expectedDividerSize == 0) {
+            return;
+        }
+
+        // Do we expect top divider?
+        if (expectingTopDivider) {
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, 0, parentWidth - expectedDividerPadding,
+                            expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor("Region of left padding of top divider is yellow",
+                    parent,
+                    new Rect(0, 0, expectedDividerPadding, expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor("Region of right padding of top divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, 0, parentWidth,
+                            expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect middle divider?
+        if (expectingMiddleDivider) {
+            final int expectedMiddleDividerTop = expectedTopChildTop + expectedChildHeight;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of middle divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, expectedMiddleDividerTop,
+                            parentWidth - expectedDividerPadding,
+                            expectedMiddleDividerTop + expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left padding of middle divider is yellow",
+                    parent,
+                    new Rect(0, expectedMiddleDividerTop, expectedDividerPadding,
+                            expectedMiddleDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right padding of middle divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, expectedMiddleDividerTop,
+                            parentWidth, expectedMiddleDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect bottom divider?
+        if (expectingBottomDivider) {
+            final int expectedBottomDividerTop = expectedBottomChildBottom;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedDividerPadding, expectedBottomDividerTop,
+                            parentWidth - expectedDividerPadding,
+                            expectedBottomDividerTop + expectedDividerSize),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left padding of bottom divider is yellow",
+                    parent,
+                    new Rect(0, expectedBottomDividerTop, expectedDividerPadding,
+                            expectedBottomDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right padding of bottom divider is yellow",
+                    parent,
+                    new Rect(parentWidth - expectedDividerPadding, expectedBottomDividerTop,
+                            parentWidth, expectedBottomDividerTop + expectedDividerSize),
+                    Color.YELLOW, 1, true);
+        }
+    }
+
+    /**
+     * layout of vertical LinearLayout.
+     * -----------------------------------
+     * | ------------------------------- |
+     * | |            child1           | |
+     * | ------------------------------- |
+     * | - - - - - - divider - - - - - - |
+     * | ------------------------------- |
+     * | |            child2           | |
+     * | ------------------------------- |
+     * -----------------------------------
+     *
+     * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+     * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+     * visibility, drawable and paddings of the divider and verify the overall visuals of the
+     * container.
+     */
+    public void testDividersInVerticalLayout() {
+        final LinearLayout parent =
+                (LinearLayout) mActivity.findViewById(R.id.vertical_with_divider);
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        final Resources res = mActivity.getResources();
+        final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+        final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        final Drawable dividerDrawable = parent.getDividerDrawable();
+        TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                false, Color.RED, 1, true);
+
+        // Test the initial visuals of the entire parent
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the divider to magenta
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.MAGENTA, dividerPadding);
+
+        // Change the divider to null (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(null));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                0, Color.TRANSPARENT, 0);
+
+        // Change the divider back to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the padding to half the original size
+        final int halfPadding = dividerPadding / 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(halfPadding));
+        assertEquals(halfPadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, halfPadding);
+
+        // Change the padding to twice the original size
+        final int doublePadding = dividerPadding * 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(doublePadding));
+        assertEquals(doublePadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, doublePadding);
+
+        // And back to the original padding
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(dividerPadding));
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Set show dividers to NONE (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+                0, Color.TRANSPARENT, 0);
+
+        // Show only top divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show only bottom divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top and middle dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show middle and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show top, middle and bottom dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                                | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfVerticalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+    }
+
+    private void verifyVisualsOfHorizontalLayoutWithDivider(LinearLayout parent,
+            int expectedDividerPositionMask,
+            int expectedDividerSize, @ColorInt int expectedDividerColor,
+            int expectedDividerPadding) {
+        final int parentWidth = parent.getWidth();
+        final int parentHeight = parent.getHeight();
+
+        final boolean expectingLeftDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+        final boolean expectingMiddleDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+        final boolean expectingRightDivider =
+                (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+        final int expectedDividerCount = (expectingLeftDivider ? 1 : 0)
+                + (expectingMiddleDivider ? 1 : 0) + (expectingRightDivider ? 1 : 0);
+
+        final int expectedChildWidth =
+                (parentWidth - expectedDividerCount * expectedDividerSize) / 2;
+
+        final int expectedLeftChildLeft = expectingLeftDivider ? expectedDividerSize : 0;
+        TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+                new Rect(expectedLeftChildLeft, 0,
+                        expectedLeftChildLeft + expectedChildWidth, parentHeight),
+                Color.BLUE, 1, true);
+
+        final int expectedRightChildRight =
+                expectingRightDivider ? parentWidth - expectedDividerSize : parentWidth;
+        TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+                new Rect(expectedRightChildRight - expectedChildWidth, 0, expectedRightChildRight,
+                        parentHeight),
+                Color.GREEN, 1, true);
+
+        if (expectedDividerSize == 0) {
+            return;
+        }
+
+        // Do we expect left divider?
+        if (expectingLeftDivider) {
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of left divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(0, expectedDividerPadding, expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of left divider is yellow",
+                    parent,
+                    new Rect(0, 0, expectedDividerSize, expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of left divider is yellow",
+                    parent,
+                    new Rect(0, parentHeight - expectedDividerPadding, expectedDividerSize,
+                            parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect middle divider?
+        if (expectingMiddleDivider) {
+            final int expectedMiddleDividerLeft = expectedLeftChildLeft + expectedChildWidth;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of middle divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, expectedDividerPadding,
+                            expectedMiddleDividerLeft + expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of middle divider is yellow",
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, 0,
+                            expectedMiddleDividerLeft + expectedDividerSize,
+                            expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of middle divider is yellow",
+                    parent,
+                    new Rect(expectedMiddleDividerLeft, parentHeight - expectedDividerPadding,
+                            expectedMiddleDividerLeft + expectedDividerSize, parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+
+        // Do we expect right divider?
+        if (expectingRightDivider) {
+            final int expectedRightDividerLeft = expectedRightChildRight;
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of right divider is " +
+                            TestUtils.formatColorToHex(expectedDividerColor),
+                    parent,
+                    new Rect(expectedRightDividerLeft, expectedDividerPadding,
+                            expectedRightDividerLeft + expectedDividerSize,
+                            parentHeight - expectedDividerPadding),
+                    expectedDividerColor, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of top padding of right divider is yellow",
+                    parent,
+                    new Rect(expectedRightDividerLeft, 0,
+                            expectedRightDividerLeft + expectedDividerSize,
+                            expectedDividerPadding),
+                    Color.YELLOW, 1, true);
+            TestUtils.assertRegionPixelsOfColor(
+                    "Region of bottom padding of right divider is yellow",
+                    parent,
+                    new Rect(expectedRightDividerLeft, parentHeight - expectedDividerPadding,
+                            expectedRightDividerLeft + expectedDividerSize, parentHeight),
+                    Color.YELLOW, 1, true);
+        }
+    }
+
+    /**
+     * layout of horizontal LinearLayout.
+     * -----------------------------------
+     * | ------------  |  -------------  |
+     * | |          |     |           |  |
+     * | |          |  d  |           |  |
+     * | |          |  i  |           |  |
+     * | |          |  v  |           |  |
+     * | |  child1  |  i  |  child2   |  |
+     * | |          |  d  |           |  |
+     * | |          |  e  |           |  |
+     * | |          |  r  |           |  |
+     * | |          |     |           |  |
+     * | ------------  |  -------------  |
+     * -----------------------------------
+     *
+     * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+     * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+     * visibility, drawable and paddings of the divider and verify the overall visuals of the
+     * container.
+     */
+    public void testDividersInHorizontalLayout() {
+        final LinearLayout parent =
+                (LinearLayout) mActivity.findViewById(R.id.horizontal_with_divider);
+
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+        instrumentation.waitForIdleSync();
+
+        final Resources res = mActivity.getResources();
+        final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+        final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        final Drawable dividerDrawable = parent.getDividerDrawable();
+        TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+                false, Color.RED, 1, true);
+
+        // Test the initial visuals of the entire parent
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the divider to magenta
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.MAGENTA, dividerPadding);
+
+        // Change the divider to null (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(null));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                0, Color.TRANSPARENT, 0);
+
+        // Change the divider back to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerDrawable(
+                        mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Change the padding to half the original size
+        final int halfPadding = dividerPadding / 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(halfPadding));
+        assertEquals(halfPadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, halfPadding);
+
+        // Change the padding to twice the original size
+        final int doublePadding = dividerPadding * 2;
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(doublePadding));
+        assertEquals(doublePadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, doublePadding);
+
+        // And back to the original padding
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setDividerPadding(dividerPadding));
+        assertEquals(dividerPadding, parent.getDividerPadding());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Set show dividers to NONE (no divider effectively)
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+                0, Color.TRANSPARENT, 0);
+
+        // Show only left divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show only right divider
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left and middle dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+        assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show middle and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+
+        // Show left, middle and right dividers
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+                () -> parent.setShowDividers(
+                        LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                                | LinearLayout.SHOW_DIVIDER_END));
+        assertEquals(
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                parent.getShowDividers());
+        verifyVisualsOfHorizontalLayoutWithDivider(parent,
+                LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+                        | LinearLayout.SHOW_DIVIDER_END,
+                dividerSize, Color.RED, dividerPadding);
+    }
+
     private class MockListView extends ListView {
         private final static int DEFAULT_CHILD_BASE_LINE = 1;
 
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index b50f8c9..8182e91 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -372,17 +372,6 @@
         // Make sure that the modality of the popup window is set up correctly
         assertEquals("Popup window modality", setupAsModal, mPopupWindow.isModal());
 
-        // Determine the location of the popup on the screen so that we can emulate
-        // a tap outside of its bounds to dismiss it
-        final int[] popupOnScreenXY = new int[2];
-        final Rect rect = new Rect();
-        mPopupWindow.getListView().getLocationOnScreen(popupOnScreenXY);
-        mPopupWindow.getBackground().getPadding(rect);
-
-        int emulatedTapX = popupOnScreenXY[0] - rect.left - 20;
-        int emulatedTapY = popupOnScreenXY[1] + mPopupWindow.getListView().getHeight() +
-                rect.top + rect.bottom + 20;
-
         // The logic below uses Instrumentation to emulate a tap outside the bounds of the
         // displayed list popup window. This tap is then treated by the framework to be "split" as
         // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
@@ -392,29 +381,12 @@
         // of Instrumentation is necessary here since Espresso's actions operate at the level
         // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
         // that would require emulation of two separate sequences as well.
-
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventDown);
-
-        // Inject MOVE event
-        long moveTime = SystemClock.uptimeMillis();
-        MotionEvent eventMove = MotionEvent.obtain(
-                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventMove);
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
-        instrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        instrumentation.waitForIdleSync();
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        final ListView popupListView = mPopupWindow.getListView();
+        final Rect rect = new Rect();
+        mPopupWindow.getBackground().getPadding(rect);
+        ViewTestUtils.emulateTapOnScreen(instrumentation, popupListView,
+                -rect.left - 20, popupListView.getHeight() + rect.top + rect.bottom + 20);
 
         // At this point our popup should not be showing and should have notified its
         // dismiss listener
@@ -668,40 +640,6 @@
         verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
     }
 
-    /**
-     * Emulates a drag-down gestures by injecting ACTION events with {@link Instrumentation}.
-     */
-    private void emulateDragDownGesture(int emulatedX, int emulatedStartY, int swipeAmount) {
-        // The logic below uses Instrumentation to emulate a swipe / drag gesture to bring up
-        // the popup content.
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedX, emulatedStartY, 1);
-        mInstrumentation.sendPointerSync(eventDown);
-
-        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
-        for (int i = 0; i < 10; i++) {
-            long moveTime = SystemClock.uptimeMillis();
-            final int moveY = emulatedStartY + swipeAmount * i / 10;
-            MotionEvent eventMove = MotionEvent.obtain(
-                    moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedX, moveY, 1);
-            mInstrumentation.sendPointerSync(eventMove);
-            // sleep for a bit to emulate a 200ms swipe
-            SystemClock.sleep(20);
-        }
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedX, emulatedStartY + swipeAmount, 1);
-        mInstrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        mInstrumentation.waitForIdleSync();
-    }
-
     public void testCreateOnDragListener() throws Throwable {
         // In this test we want precise control over the height of the popup content since
         // we need to know by how much to swipe down to end the emulated gesture over the
@@ -738,7 +676,8 @@
         int swipeAmount = 2 * popupRowHeight;
 
         // Emulate drag-down gesture with a sequence of motion events
-        emulateDragDownGesture(emulatedX, emulatedStartY, swipeAmount);
+        ViewTestUtils.emulateDragGesture(getInstrumentation(), emulatedX, emulatedStartY,
+                0, swipeAmount);
 
         // We expect the swipe / drag gesture to result in clicking the second item in our list.
         verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
@@ -952,7 +891,8 @@
             if (mHasItemSelectedListener) {
                 mOnItemSelectedListener = mock(AdapterView.OnItemSelectedListener.class);
                 mPopupWindow.setOnItemSelectedListener(mOnItemSelectedListener);
-                mPopupWindow.setListSelector(mActivity.getDrawable(R.drawable.red_fill));
+                mPopupWindow.setListSelector(
+                        mActivity.getDrawable(R.drawable.red_translucent_fill));
             }
 
             if (mHasDismissListener) {
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
new file mode 100644
index 0000000..f93a1da
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.NumberPicker;
+
+/**
+ * A minimal application for {@link NumberPicker} test.
+ */
+public class NumberPickerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.numberpicker_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
new file mode 100644
index 0000000..a7945e3
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * 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.widget.cts;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.NumberPicker;
+import android.widget.cts.util.ViewTestUtils;
+import org.mockito.InOrder;
+
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class NumberPickerTest extends ActivityInstrumentationTestCase2<NumberPickerCtsActivity> {
+    private static final String[] NUMBER_NAMES3 = {"One", "Two", "Three"};
+    private static final String[] NUMBER_NAMES_ALT3 = {"Three", "Four", "Five"};
+    private static final String[] NUMBER_NAMES5 = {"One", "Two", "Three", "Four", "Five"};
+
+    private Instrumentation mInstrumentation;
+    private NumberPickerCtsActivity mActivity;
+    private NumberPicker mNumberPicker;
+
+    public NumberPickerTest() {
+        super("android.widget.cts", NumberPickerCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mNumberPicker = (NumberPicker) mActivity.findViewById(R.id.number_picker);
+    }
+
+    @UiThreadTest
+    public void testConstructor() {
+        new NumberPicker(mActivity);
+
+        new NumberPicker(mActivity, null);
+
+        new NumberPicker(mActivity, null, android.R.attr.numberPickerStyle);
+
+        new NumberPicker(mActivity, null, 0, android.R.style.Widget_Material_Light_NumberPicker);
+    }
+
+    private void verifyDisplayedValues(String[] expected) {
+        final String[] displayedValues = mNumberPicker.getDisplayedValues();
+        assertEquals(expected.length, displayedValues.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], displayedValues[i]);
+        }
+    }
+
+    public void testSetDisplayedValuesRangeMatch() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(12);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(12, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES3);
+
+        // Set a different displayed values array, but still matching the min/max range
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(12, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES_ALT3);
+
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(24);
+            mNumberPicker.setMaxValue(26);
+        });
+
+        assertEquals(24, mNumberPicker.getMinValue());
+        assertEquals(26, mNumberPicker.getMaxValue());
+        verifyDisplayedValues(NUMBER_NAMES_ALT3);
+    }
+
+    public void testSetDisplayedValuesRangeMismatch() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(14);
+        });
+        assertEquals(10, mNumberPicker.getMinValue());
+        assertEquals(14, mNumberPicker.getMaxValue());
+
+        // Try setting too few displayed entries
+        mInstrumentation.runOnMainSync(() -> {
+            try {
+                // This is expected to fail since the displayed values only has three entries,
+                // while the min/max range has five.
+                mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+                fail("The size of the displayed values array must be equal to min/max range!");
+            } catch (Exception e) {
+                // We are expecting to catch an exception. Set displayed values to an array that
+                // matches the min/max range.
+                mNumberPicker.setDisplayedValues(NUMBER_NAMES5);
+            }
+        });
+    }
+
+    public void testSelectionDisplayedValueFromDisplayedValues() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(1);
+            mNumberPicker.setMaxValue(3);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Switch to a different displayed values array
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+    public void testSelectionDisplayedValueFromFormatter() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(0);
+            mNumberPicker.setMaxValue(4);
+            mNumberPicker.setFormatter((int value) -> "entry " + value);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+        assertTrue(TextUtils.equals("entry 0",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("entry 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals("entry 2",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals("entry 3",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(4));
+        assertTrue(TextUtils.equals("entry 4",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Switch to a different formatter
+        mInstrumentation.runOnMainSync(
+                () -> mNumberPicker.setFormatter((int value) -> "row " + value));
+        // Check that the currently selected value has new displayed value
+        assertTrue(TextUtils.equals("row 4",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // and check a couple more values for the new formatting
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+        assertTrue(TextUtils.equals("row 0",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("row 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+
+    public void testSelectionDisplayedValuePrecedence() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(1);
+            mNumberPicker.setMaxValue(3);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+            mNumberPicker.setFormatter((int value) -> "entry " + value);
+        });
+
+        // According to the widget documentation, displayed values take precedence over formatter
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Set displayed values to null and test that the widget is using the formatter
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(null));
+        assertTrue(TextUtils.equals("entry 3",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals("entry 1",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+        assertTrue(TextUtils.equals("entry 2",
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        // Set a different displayed values array and test that it's taking precedence
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+        assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+                mNumberPicker.getDisplayedValueForCurrentSelection()));
+    }
+
+    public void testAccessValue() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(20);
+            mNumberPicker.setMaxValue(22);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(21));
+        assertEquals(21, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(20));
+        assertEquals(20, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(22));
+        assertEquals(22, mNumberPicker.getValue());
+
+        // Check trying to set value out of min/max range
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(10));
+        assertEquals(20, mNumberPicker.getValue());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(100));
+        assertEquals(22, mNumberPicker.getValue());
+
+        // Since all changes to value are via API calls, we should have no interactions /
+        // callbacks on our listener.
+        verifyZeroInteractions(mockValueChangeListener);
+    }
+
+    public void testInteractionWithSwipeDown() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(6);
+            mNumberPicker.setMaxValue(8);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        final NumberPicker.OnScrollListener mockScrollListener =
+                mock(NumberPicker.OnScrollListener.class);
+        mNumberPicker.setOnScrollListener(mockScrollListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(7));
+        assertEquals(7, mNumberPicker.getValue());
+
+        // Swipe down across our number picker
+        final int[] numberPickerLocationOnScreen = new int[2];
+        mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+        ViewTestUtils.emulateDragGesture(mInstrumentation,
+                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                numberPickerLocationOnScreen[1] + 1,
+                0,
+                mNumberPicker.getHeight() - 2);
+
+        // At this point we expect that the drag-down gesture has selected the value
+        // that was "above" the previously selected one, and that our value change listener
+        // has been notified of that change exactly once.
+        assertEquals(6, mNumberPicker.getValue());
+        verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 7, 6);
+        verifyNoMoreInteractions(mockValueChangeListener);
+
+        // We expect that our scroll listener will be called with specific state changes.
+        InOrder inOrder = inOrder(mockScrollListener);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+        verifyNoMoreInteractions(mockScrollListener);
+    }
+
+    public void testInteractionWithSwipeUp() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(10);
+            mNumberPicker.setMaxValue(12);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+        });
+
+        final NumberPicker.OnValueChangeListener mockValueChangeListener =
+                mock(NumberPicker.OnValueChangeListener.class);
+        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+        final NumberPicker.OnScrollListener mockScrollListener =
+                mock(NumberPicker.OnScrollListener.class);
+        mNumberPicker.setOnScrollListener(mockScrollListener);
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(11));
+        assertEquals(11, mNumberPicker.getValue());
+
+        // Swipe up across our number picker
+        final int[] numberPickerLocationOnScreen = new int[2];
+        mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+        ViewTestUtils.emulateDragGesture(mInstrumentation,
+                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
+                0,
+                - (mNumberPicker.getHeight() - 2));
+
+        // At this point we expect that the drag-up gesture has selected the value
+        // that was "below" the previously selected one, and that our value change listener
+        // has been notified of that change exactly once.
+        assertEquals(12, mNumberPicker.getValue());
+        verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 11, 12);
+        verifyNoMoreInteractions(mockValueChangeListener);
+
+        // We expect that our scroll listener will be called with specific state changes.
+        InOrder inOrder = inOrder(mockScrollListener);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+        inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+                NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+        verifyNoMoreInteractions(mockScrollListener);
+    }
+
+    public void testAccessWrapSelectorValue() {
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(100);
+            mNumberPicker.setMaxValue(200);
+        });
+        // As specified in the Javadocs of NumberPicker.setWrapSelectorWheel, when min/max
+        // range is larger than what the widget is showing, the selector wheel is enabled.
+        assertTrue(mNumberPicker.getWrapSelectorWheel());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(false));
+        assertFalse(mNumberPicker.getWrapSelectorWheel());
+
+        mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(true));
+        assertTrue(mNumberPicker.getWrapSelectorWheel());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index ee38448..aa37127 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -30,6 +30,7 @@
 import android.view.View;
 import android.widget.EditText;
 import android.widget.PopupMenu;
+import android.widget.cts.util.ViewTestUtils;
 
 import static org.mockito.Mockito.*;
 
@@ -183,15 +184,7 @@
         runTestOnUiThread(() -> mBuilder.show());
         mInstrumentation.waitForIdleSync();
 
-        // Determine the location of the anchor on the screen so that we can emulate
-        // a tap outside of the popup bounds to dismiss the popup
-        final int[] anchorOnScreenXY = new int[2];
-        mBuilder.mAnchor.getLocationOnScreen(anchorOnScreenXY);
-
-        int emulatedTapX = anchorOnScreenXY[0] + 10;
-        int emulatedTapY = anchorOnScreenXY[1] - 20;
-
-        // The logic below uses Instrumentation to emulate a tap outside the bounds of the
+        // The call below uses Instrumentation to emulate a tap outside the bounds of the
         // displayed popup menu. This tap is then treated by the framework to be "split" as
         // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
         // view root if the popup is not modal.
@@ -200,27 +193,7 @@
         // of Instrumentation is necessary here since Espresso's actions operate at the level
         // of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
         // that would require emulation of two separate sequences as well.
-
-        // Inject DOWN event
-        long downTime = SystemClock.uptimeMillis();
-        MotionEvent eventDown = MotionEvent.obtain(
-                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventDown);
-
-        // Inject MOVE event
-        long moveTime = SystemClock.uptimeMillis();
-        MotionEvent eventMove = MotionEvent.obtain(
-                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventMove);
-
-        // Inject UP event
-        long upTime = SystemClock.uptimeMillis();
-        MotionEvent eventUp = MotionEvent.obtain(
-                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
-        mInstrumentation.sendPointerSync(eventUp);
-
-        // Wait for the system to process all events in the queue
-        mInstrumentation.waitForIdleSync();
+        ViewTestUtils.emulateTapOnScreen(mInstrumentation, mBuilder.mAnchor, 10, -20);
 
         // At this point our popup should have notified its dismiss listener
         verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 96b37d3..80e5691 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -20,12 +20,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
 import android.transition.TransitionValues;
@@ -51,6 +53,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+@SmallTest
 public class PopupWindowTest extends
         ActivityInstrumentationTestCase2<PopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
@@ -84,6 +87,8 @@
 
         new PopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
 
+        new PopupWindow(mActivity, null, 0, android.R.style.Widget_Material_Light_PopupWindow);
+
         mPopupWindow = new PopupWindow();
         assertEquals(0, mPopupWindow.getWidth());
         assertEquals(0, mPopupWindow.getHeight());
@@ -575,6 +580,8 @@
         // Do not attach within the decor; we will be measuring location
         // with regard to screen coordinates.
         mPopupWindow.setAttachedInDecor(false);
+        assertFalse(mPopupWindow.isAttachedInDecor());
+
         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
 
         final int xOff = 10;
@@ -656,42 +663,73 @@
 
     public void testGetMaxAvailableHeight() {
         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        final Point point = new Point();
+        getDisplay().getSize(point);
+        final int displayHeight = point.y;
 
         View anchorView = mActivity.findViewById(R.id.anchor_upper);
-        int avaliable = getDisplay().getHeight() - anchorView.getHeight();
+        int available = displayHeight - anchorView.getHeight();
         int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
+        int maxAvailableHeightIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, 0, true);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
+        assertTrue(maxAvailableHeightIgnoringBottomDecoration >= maxAvailableHeight);
+        assertTrue(maxAvailableHeightIgnoringBottomDecoration <= available);
+
         int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
         assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
+
         maxAvailableHeightWithOffset =
                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
         maxAvailableHeightWithOffset =
                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
         maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
         assertTrue(maxAvailableHeightWithOffset > 0);
-        assertTrue(maxAvailableHeightWithOffset <= avaliable);
+        assertTrue(maxAvailableHeightWithOffset <= available);
+
+        int maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, 2, true);
+        assertEquals(maxAvailableHeightIgnoringBottomDecoration - 2,
+                maxAvailableHeightWithOffsetIgnoringBottomDecoration);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+        maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+                mPopupWindow.getMaxAvailableHeight(anchorView, -1, true);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+        assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
 
         anchorView = mActivity.findViewById(R.id.anchor_lower);
         // On some devices the view might actually have larger size than the physical display
         // due to chin and content will be laid out as if outside of the display. We need to use
         // larger from the display height and the main view height.
-        avaliable = Math.max(getDisplay().getHeight(),
+        available = Math.max(displayHeight,
                 mActivity.findViewById(android.R.id.content).getHeight()) - anchorView.getHeight();
         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
 
         anchorView = mActivity.findViewById(R.id.anchor_middle_left);
-        avaliable = getDisplay().getHeight() - anchorView.getHeight()
+        available = displayHeight - anchorView.getHeight()
                 - mActivity.findViewById(R.id.anchor_upper).getHeight();
         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
         assertTrue(maxAvailableHeight > 0);
-        assertTrue(maxAvailableHeight <= avaliable);
+        assertTrue(maxAvailableHeight <= available);
     }
 
     @UiThreadTest
@@ -815,6 +853,7 @@
         mInstrumentation.waitForIdleSync();
         // Do not update if it is not shown
         assertFalse(mPopupWindow.isShowing());
+        assertFalse(mPopupWindow.isAttachedInDecor());
         assertEquals(100, mPopupWindow.getWidth());
         assertEquals(100, mPopupWindow.getHeight());
 
@@ -822,6 +861,14 @@
         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
 
         // update if it is not shown
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(80, 80));
+
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mPopupWindow.isShowing());
+        assertEquals(80, mPopupWindow.getWidth());
+        assertEquals(80, mPopupWindow.getHeight());
+
+        // update if it is not shown
         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
 
         mInstrumentation.waitForIdleSync();
@@ -1061,6 +1108,61 @@
         assertEquals(LayoutParams.MATCH_PARENT, p.height);
     }
 
+    public void testAccessElevation() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(2.0f));
+
+        showPopup();
+        assertEquals(2.0f, mPopupWindow.getElevation());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(4.0f));
+        showPopup();
+        assertEquals(4.0f, mPopupWindow.getElevation());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(10.0f));
+        showPopup();
+        assertEquals(10.0f, mPopupWindow.getElevation());
+    }
+
+    public void testAccessSoftInputMode() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow.setSoftInputMode(
+                        WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE));
+
+        showPopup();
+        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
+                mPopupWindow.getSoftInputMode());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow.setSoftInputMode(
+                        WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN));
+        showPopup();
+        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN,
+                mPopupWindow.getSoftInputMode());
+    }
+
+    public void testAccessSplitTouchEnabled() {
+        mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+
+        showPopup();
+        assertTrue(mPopupWindow.isSplitTouchEnabled());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(false));
+        showPopup();
+        assertFalse(mPopupWindow.isSplitTouchEnabled());
+
+        dismissPopup();
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+        showPopup();
+        assertTrue(mPopupWindow.isSplitTouchEnabled());
+    }
+
     private static class BaseTransition extends Transition {
         @Override
         public void captureStartValues(TransitionValues transitionValues) {}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
new file mode 100644
index 0000000..442d5f7
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RadioButton;
+
+/**
+ * A minimal application for {@link RadioButton} test.
+ */
+public class RadioButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.radiobutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index eb9387b..f98a45e 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -16,6 +16,12 @@
 
 package android.widget.cts;
 
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.CheckBox;
 import android.widget.cts.R;
 
 
@@ -24,59 +30,154 @@
 import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.widget.RadioButton;
+import android.widget.cts.util.ViewTestUtils;
 
-/**
- * Test {@link RadioButton}.
- */
-public class RadioButtonTest extends InstrumentationTestCase {
-    private Context mContext;
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class RadioButtonTest extends ActivityInstrumentationTestCase2<RadioButtonCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private RadioButton mRadioButton;
+
+    public RadioButtonTest() {
+        super("android.widget.cts", RadioButtonCtsActivity.class);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mContext = getInstrumentation().getTargetContext();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mRadioButton = (RadioButton) mActivity.findViewById(R.id.radio_button);
     }
 
     public void testConstructor() {
-        AttributeSet attrs = mContext.getResources().getLayout(R.layout.radiogroup_1);
-        assertNotNull(attrs);
+        new RadioButton(mActivity);
+        new RadioButton(mActivity, null);
+        new RadioButton(mActivity, null, android.R.attr.radioButtonStyle);
+        new RadioButton(mActivity, null, 0,
+                android.R.style.Widget_Material_Light_CompoundButton_RadioButton);
 
-        new RadioButton(mContext);
         try {
             new RadioButton(null);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
 
-        new RadioButton(mContext, attrs);
         try {
-            new RadioButton(null, attrs);
+            new RadioButton(null, null);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
-        new RadioButton(mContext, null);
-
-        new RadioButton(mContext, attrs, 0);
         try {
-            new RadioButton(null, attrs, 0);
+            new RadioButton(null, null, 0);
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
-        new RadioButton(mContext, null, 0);
-        new RadioButton(mContext, attrs, Integer.MAX_VALUE);
-        new RadioButton(mContext, attrs, Integer.MIN_VALUE);
     }
 
-    @UiThreadTest
-    public void testToggle() {
-        RadioButton button = new RadioButton(mContext);
-        assertFalse(button.isChecked());
+    public void testText() {
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.hello_world), mRadioButton.getText()));
 
-        button.toggle();
-        assertTrue(button.isChecked());
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setText("new text"));
+        assertTrue(TextUtils.equals("new text", mRadioButton.getText()));
 
-        // Can't be toggled if it is checked
-        button.toggle();
-        assertTrue(button.isChecked());
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setText(R.string.text_name));
+        assertTrue(TextUtils.equals(
+                mActivity.getString(R.string.text_name), mRadioButton.getText()));
+    }
+
+    public void testAccessChecked() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // not checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+        verifyZeroInteractions(mockCheckedChangeListener);
+        assertFalse(mRadioButton.isChecked());
+
+        // not checked -> checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // checked -> checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // checked -> not checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, false);
+        assertFalse(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaApi() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // toggle to checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // try toggle to not checked - this should leave the radio button in checked state
+        mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaEmulatedTap() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // tap to checked
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // tap to not checked - this should leave the radio button in checked state
+        ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
+    }
+
+    public void testToggleViaPerformClick() {
+        final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+                mock(RadioButton.OnCheckedChangeListener.class);
+        mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+        verifyZeroInteractions(mockCheckedChangeListener);
+
+        assertFalse(mRadioButton.isChecked());
+
+        // click to checked
+        mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+        assertTrue(mRadioButton.isChecked());
+
+        // click to not checked - this should leave the radio button in checked state
+        mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+        assertTrue(mRadioButton.isChecked());
+
+        verifyNoMoreInteractions(mockCheckedChangeListener);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
index 2f3be6f..dfff694 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.app.Instrumentation;
 import android.widget.cts.R;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -43,6 +44,7 @@
  */
 public class RelativeLayoutTest extends
         ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
+    private Instrumentation mInstrumentation;
     private Activity mActivity;
 
     public RelativeLayoutTest() {
@@ -52,6 +54,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
     }
 
@@ -86,27 +90,19 @@
         ViewAsserts.assertRightAligned(relativeLayout, view13);
 
         relativeLayout.setIgnoreGravity(R.id.relative_view13);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.requestLayout();
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+        mInstrumentation.waitForIdleSync();
         ViewAsserts.assertRightAligned(relativeLayout, view12);
         ViewAsserts.assertLeftAligned(relativeLayout, view13);
 
         relativeLayout.setIgnoreGravity(0);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.requestLayout();
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+        mInstrumentation.waitForIdleSync();
         ViewAsserts.assertRightAligned(relativeLayout, view12);
         ViewAsserts.assertRightAligned(relativeLayout, view13);
     }
 
-    public void testSetGravity() {
+    public void testAccessGravity() {
         final RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
                 R.id.relative_sublayout_gravity);
 
@@ -120,48 +116,38 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // -- BOTTOM && RIGHT
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM | Gravity.RIGHT, relativeLayout.getGravity());
         ViewAsserts.assertRightAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertRightAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // -- BOTTOM
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.BOTTOM);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.BOTTOM));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM | Gravity.START, relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertLeftAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // CENTER_HORIZONTAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_HORIZONTAL | Gravity.TOP,
+                relativeLayout.getGravity());
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
         assertEquals(view11.getTop(), view10.getBottom());
 
         // CENTER_VERTICAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setGravity(Gravity.CENTER_VERTICAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_VERTICAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_VERTICAL | Gravity.START, relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         int topSpace = view10.getTop();
         int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -184,24 +170,20 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // RIGHT
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setHorizontalGravity(Gravity.RIGHT);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setHorizontalGravity(Gravity.RIGHT));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.RIGHT, Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertRightAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertRightAligned(relativeLayout, view11);
         assertEquals(view11.getTop(), view10.getBottom());
 
         // CENTER_HORIZONTAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_HORIZONTAL,
+                Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
         ViewAsserts.assertTopAligned(relativeLayout, view10);
         ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
@@ -222,24 +204,20 @@
         assertEquals(view11.getTop(), view10.getBottom());
 
         // BOTTOM
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setVerticalGravity(Gravity.BOTTOM);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> relativeLayout.setVerticalGravity(Gravity.BOTTOM));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.BOTTOM, Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         assertEquals(view11.getTop(), view10.getBottom());
         ViewAsserts.assertLeftAligned(relativeLayout, view11);
         ViewAsserts.assertBottomAligned(relativeLayout, view11);
 
         // CENTER_VERTICAL
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(Gravity.CENTER_VERTICAL,
+                Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
         ViewAsserts.assertLeftAligned(relativeLayout, view10);
         int topSpace = view10.getTop();
         int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -352,12 +330,9 @@
      * Tests to prevent regressions in baseline alignment.
      */
     public void testBaselineAlignment() {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mActivity.setContentView(R.layout.relative_layout_baseline);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        mInstrumentation.runOnMainSync(
+                () -> mActivity.setContentView(R.layout.relative_layout_baseline));
+        mInstrumentation.waitForIdleSync();
 
         View button = mActivity.findViewById(R.id.button1);
         assertTrue(button.getHeight() > 0);
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
new file mode 100644
index 0000000..5da8a32
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.SearchView;
+
+/**
+ * A minimal application for {@link SearchView} test.
+ */
+public class SearchViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.searchview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewTest.java b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
new file mode 100644
index 0000000..4c8cd8c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.res.Resources;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.view.inputmethod.EditorInfo;
+import android.widget.SearchView;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView}.
+ */
+@MediumTest
+public class SearchViewTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private SearchView mSearchView;
+
+    public SearchViewTest() {
+        super("android.widget.cts", SearchViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+    }
+
+    @UiThreadTest
+    public void testConstructor() {
+        new SearchView(mActivity);
+
+        new SearchView(mActivity, null);
+
+        new SearchView(mActivity, null, android.R.attr.searchViewStyle);
+
+        new SearchView(mActivity, null, 0, android.R.style.Widget_Material_Light_SearchView);
+    }
+
+    @UiThreadTest
+    public void testAttributesFromXml() {
+        SearchView searchViewWithAttributes =
+                (SearchView) mActivity.findViewById(R.id.search_view_with_defaults);
+        assertEquals(mActivity.getString(R.string.search_query_hint),
+                searchViewWithAttributes.getQueryHint());
+        assertFalse(searchViewWithAttributes.isIconfiedByDefault());
+        assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS | EditorInfo.TYPE_CLASS_TEXT,
+                searchViewWithAttributes.getInputType());
+        assertEquals(EditorInfo.IME_ACTION_DONE, searchViewWithAttributes.getImeOptions());
+        assertEquals(mActivity.getResources().getDimensionPixelSize(R.dimen.search_view_max_width),
+                searchViewWithAttributes.getMaxWidth());
+    }
+
+    public void testAccessIconified() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        assertTrue(mSearchView.isIconified());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testAccessIconifiedByDefault() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(true));
+        assertTrue(mSearchView.isIconfiedByDefault());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(false));
+        assertFalse(mSearchView.isIconfiedByDefault());
+    }
+
+    public void testDenyIconifyingNonInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(false);
+            mSearchView.setIconified(false);
+        });
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Since our search view is marked with iconifiedByDefault=false, call to setIconified
+        // with true us going to be ignored, as detailed in the class-level documentation of
+        // SearchView.
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testDenyIconifyingInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(true);
+            mSearchView.setIconified(false);
+        });
+
+        final SearchView.OnCloseListener mockDenyCloseListener =
+                mock(SearchView.OnCloseListener.class);
+        when(mockDenyCloseListener.onClose()).thenReturn(Boolean.TRUE);
+        mSearchView.setOnCloseListener(mockDenyCloseListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Our mock listener is configured to return true from its onClose, thereby preventing
+        // the iconify request to be completed. Check that the listener was called and that the
+        // search view is not iconified.
+        verify(mockDenyCloseListener, times(1)).onClose();
+        assertFalse(mSearchView.isIconified());
+    }
+
+    public void testAllowIconifyingInconifiableView() {
+        mInstrumentation.runOnMainSync(() -> {
+            mSearchView.setIconifiedByDefault(true);
+            mSearchView.setIconified(false);
+        });
+
+        final SearchView.OnCloseListener mockAllowCloseListener =
+                mock(SearchView.OnCloseListener.class);
+        when(mockAllowCloseListener.onClose()).thenReturn(Boolean.FALSE);
+        mSearchView.setOnCloseListener(mockAllowCloseListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+        mInstrumentation.waitForIdleSync();
+
+        // Our mock listener is configured to return false from its onClose, thereby allowing
+        // the iconify request to be completed. Check that the listener was called and that the
+        // search view is not iconified.
+        verify(mockAllowCloseListener, times(1)).onClose();
+        assertTrue(mSearchView.isIconified());
+    }
+
+    public void testAccessMaxWidth() {
+        final Resources res = mActivity.getResources();
+        final int maxWidth1 = res.getDimensionPixelSize(R.dimen.search_view_max_width);
+        final int maxWidth2 = res.getDimensionPixelSize(R.dimen.search_view_max_width2);
+
+        // Set search view to not be iconified before running max-width tests
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth1));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(maxWidth1, mSearchView.getMaxWidth());
+        assertTrue(mSearchView.getWidth() <= maxWidth1);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth2));
+        mInstrumentation.waitForIdleSync();
+        assertEquals(maxWidth2, mSearchView.getMaxWidth());
+        assertTrue(mSearchView.getWidth() <= maxWidth2);
+    }
+
+    public void testAccessQuery() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                mock(SearchView.OnQueryTextListener.class);
+        when(mockQueryTextListener.onQueryTextSubmit(anyString())).thenReturn(Boolean.TRUE);
+        mSearchView.setOnQueryTextListener(mockQueryTextListener);
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("alpha", false));
+        assertTrue(TextUtils.equals("alpha", mSearchView.getQuery()));
+        // Since we passed false as the second parameter to setQuery, our query text listener
+        // should have been invoked only with text change
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("alpha");
+        verify(mockQueryTextListener, never()).onQueryTextSubmit(anyString());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("beta", true));
+        assertTrue(TextUtils.equals("beta", mSearchView.getQuery()));
+        // Since we passed true as the second parameter to setQuery, our query text listener
+        // should have been invoked on both callbacks
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("beta");
+        verify(mockQueryTextListener, times(1)).onQueryTextSubmit("beta");
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("gamma", true));
+        assertTrue(TextUtils.equals("gamma", mSearchView.getQuery()));
+        // Since we passed true as the second parameter to setQuery, our query text listener
+        // should have been invoked on both callbacks
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("gamma");
+        verify(mockQueryTextListener, times(1)).onQueryTextSubmit("gamma");
+
+        verifyNoMoreInteractions(mockQueryTextListener);
+    }
+
+    public void testAccessQueryHint() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 1"));
+        assertTrue(TextUtils.equals("hint 1", mSearchView.getQueryHint()));
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 2"));
+        assertTrue(TextUtils.equals("hint 2", mSearchView.getQueryHint()));
+    }
+
+    public void testAccessInputType() {
+        mInstrumentation.runOnMainSync(() ->
+                mSearchView.setInputType(InputType.TYPE_CLASS_NUMBER
+                    | InputType.TYPE_NUMBER_FLAG_DECIMAL
+                    | InputType.TYPE_NUMBER_FLAG_SIGNED));
+        assertEquals(InputType.TYPE_CLASS_NUMBER
+                | InputType.TYPE_NUMBER_FLAG_DECIMAL
+                | InputType.TYPE_NUMBER_FLAG_SIGNED, mSearchView.getInputType());
+
+        mInstrumentation.runOnMainSync(() ->
+                mSearchView.setInputType(InputType.TYPE_CLASS_TEXT
+                        | InputType.TYPE_TEXT_FLAG_CAP_WORDS));
+        assertEquals(InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_FLAG_CAP_WORDS, mSearchView.getInputType());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setInputType(InputType.TYPE_CLASS_PHONE));
+        assertEquals(InputType.TYPE_CLASS_PHONE, mSearchView.getInputType());
+    }
+
+    public void testAccessImeOptions() {
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_GO));
+        assertEquals(EditorInfo.IME_ACTION_GO, mSearchView.getImeOptions());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_DONE));
+        assertEquals(EditorInfo.IME_ACTION_DONE, mSearchView.getImeOptions());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_NULL));
+        assertEquals(EditorInfo.IME_NULL, mSearchView.getImeOptions());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
new file mode 100644
index 0000000..5b8dbfc
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.BaseColumns;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.widget.CursorAdapter;
+import android.widget.SearchView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView} with {@link Cursor}-backed suggestions adapter.
+ */
+@MediumTest
+public class SearchView_CursorTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private SearchView mSearchView;
+
+    private static final String TEXT_COLUMN_NAME = "text";
+    private String[] mTextContent;
+
+    private CursorAdapter mSuggestionsAdapter;
+
+    protected class MyQueryTextListener implements SearchView.OnQueryTextListener {
+        @Override
+        public boolean onQueryTextSubmit(String s) {
+            return false;
+        }
+
+        @Override
+        public boolean onQueryTextChange(String s) {
+            if (mSuggestionsAdapter == null) {
+                return false;
+            }
+
+            final MatrixCursor c = new MatrixCursor(
+                    new String[] { BaseColumns._ID, TEXT_COLUMN_NAME} );
+            for (int i = 0; i < mTextContent.length; i++) {
+                if (mTextContent[i].toLowerCase().startsWith(s.toLowerCase())) {
+                    c.addRow(new Object[]{i, mTextContent[i]});
+                }
+            }
+            mSuggestionsAdapter.swapCursor(c);
+            return false;
+        }
+    }
+
+    protected class MySuggestionListener implements SearchView.OnSuggestionListener {
+        @Override
+        public boolean onSuggestionSelect(int position) {
+            return false;
+        }
+
+        @Override
+        public boolean onSuggestionClick(int position) {
+            if (mSuggestionsAdapter != null) {
+                final Cursor cursor = mSuggestionsAdapter.getCursor();
+                if (cursor != null) {
+                    cursor.moveToPosition(position);
+                    mSearchView.setQuery(cursor.getString(1), false);
+                }
+            }
+            return false;
+        }
+    }
+
+    public SearchView_CursorTest() {
+        super("android.widget.cts", SearchViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
+        mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+
+        // Local test data for the tests
+        mTextContent = new String[] { "Akon", "Bono", "Ciara", "Dido", "Diplo" };
+
+        mInstrumentation.runOnMainSync(() -> {
+            // Use an adapter with our custom layout for each entry. The adapter "maps"
+            // the content of the text column of our cursor to the @id/text1 view in the
+            // layout.
+            mSuggestionsAdapter = new SimpleCursorAdapter(
+                    mActivity,
+                    R.layout.searchview_suggestion_item,
+                    null,
+                    new String[] { TEXT_COLUMN_NAME },
+                    new int[] { android.R.id.text1 },
+                    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
+            mSearchView.setSuggestionsAdapter(mSuggestionsAdapter);
+        });
+    }
+
+    public void testSuggestionFiltering() {
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                spy(new MyQueryTextListener());
+        when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    mSearchView.setIconifiedByDefault(false);
+                    mSearchView.setOnQueryTextListener(mockQueryTextListener);
+                    mSearchView.requestFocus();
+                });
+
+        assertTrue(mSearchView.hasFocus());
+        assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Bon", false));
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Bon");
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+    }
+
+    public void testSuggestionSelection() {
+        final SearchView.OnSuggestionListener mockSuggestionListener =
+                spy(new MySuggestionListener());
+        when(mockSuggestionListener.onSuggestionClick(anyInt())).thenCallRealMethod();
+
+        final SearchView.OnQueryTextListener mockQueryTextListener =
+                spy(new MyQueryTextListener());
+        when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+        mInstrumentation.runOnMainSync(() -> {
+                    mSearchView.setIconifiedByDefault(false);
+                    mSearchView.setOnQueryTextListener(mockQueryTextListener);
+                    mSearchView.setOnSuggestionListener(mockSuggestionListener);
+                    mSearchView.requestFocus();
+                });
+
+        assertTrue(mSearchView.hasFocus());
+        assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+        mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+        mInstrumentation.waitForIdleSync();
+        verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+
+        // Emulate click on the first suggestion - which should be Dido
+        final int suggestionRowHeight = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.search_view_suggestion_row_height);
+        ViewTestUtils.emulateTapOnScreen(mInstrumentation, mSearchView, mSearchView.getWidth() / 2,
+                mSearchView.getHeight() + suggestionRowHeight / 2);
+
+        // At this point we expect the click on the first suggestion to have activated a sequence
+        // of events that ends up in our suggestion listener that sets the full suggestion text
+        // as the current query. Some parts of this sequence of events are asynchronous, and those
+        // are not "caught" by Instrumentation.waitForIdleSync - which is in general not a very
+        // reliable way to wait for everything to be completed. As such, we are using our own
+        // polling check mechanism to wait until the search view's query is the fully completed
+        // suggestion for Dido. This check will time out and fail after a few seconds if anything
+        // goes wrong during the processing of the emulated tap and the code never gets to our
+        // suggestion listener
+        PollingCheck.waitFor(() -> TextUtils.equals("Dido", mSearchView.getQuery()));
+
+        // Just to be sure, verify that our spy suggestion listener was called
+        verify(mockSuggestionListener, times(1)).onSuggestionClick(0);
+        verifyNoMoreInteractions(mockSuggestionListener);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
new file mode 100644
index 0000000..16fb30e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Spinner;
+
+/**
+ * A minimal application for {@link Spinner} test.
+ */
+public class SpinnerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.spinner_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index eea1e3e..d76888f 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -16,101 +16,133 @@
 
 package android.widget.cts;
 
-import android.widget.cts.R;
-
-
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.content.Context;
+import android.app.Instrumentation;
+import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.Spinner;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.mock;
 
 /**
  * Test {@link Spinner}.
  */
-public class SpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
-    private Context mTargetContext;
+@MediumTest
+public class SpinnerTest extends ActivityInstrumentationTestCase2<SpinnerCtsActivity> {
+    private Activity mActivity;
+    private Spinner mSpinnerDialogMode;
+    private Spinner mSpinnerDropdownMode;
 
     public SpinnerTest() {
-        super("android.widget.cts", RelativeLayoutCtsActivity.class);
+        super("android.widget.cts", SpinnerCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mTargetContext = getInstrumentation().getTargetContext();
+
+        mActivity = getActivity();
+        mSpinnerDialogMode = (Spinner) mActivity.findViewById(R.id.spinner_dialog_mode);
+        mSpinnerDropdownMode = (Spinner) mActivity.findViewById(R.id.spinner_dropdown_mode);
     }
 
-    @UiThreadTest
     public void testConstructor() {
-        new Spinner(mTargetContext);
+        new Spinner(mActivity);
 
-        new Spinner(mTargetContext, null);
+        new Spinner(mActivity, null);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle);
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle);
 
-        new Spinner(mTargetContext, Spinner.MODE_DIALOG);
+        new Spinner(mActivity, Spinner.MODE_DIALOG);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle,
+        new Spinner(mActivity, Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DIALOG);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DROPDOWN);
+
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
                 Spinner.MODE_DIALOG);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
-                Spinner.MODE_DIALOG);
+        new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
+                Spinner.MODE_DROPDOWN);
 
-        new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
-                Spinner.MODE_DIALOG, mTargetContext.getTheme());
+        final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+        popupTheme.applyStyle(android.R.style.Theme_Material, true);
 
-        Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-        assertEquals(mTargetContext.getString(R.string.text_view_hello), spinner.getPrompt());
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG,
+                popupTheme);
+
+        new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DROPDOWN,
+                popupTheme);
     }
 
-    @UiThreadTest
-    public void testGetBaseline() {
-        Spinner spinner = new Spinner(mTargetContext);
-
+    private void verifyGetBaseline(Spinner spinner) {
         assertEquals(-1, spinner.getBaseline());
 
-        spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mTargetContext,
-                android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        spinner.setAdapter(adapter);
-        assertTrue(spinner.getBaseline() > 0);
+        getInstrumentation().runOnMainSync(() -> {
+            spinner.setAdapter(adapter);
+            assertTrue(spinner.getBaseline() > 0);
+        });
     }
 
-    @UiThreadTest
-    public void testSetOnItemClickListener() {
-        Spinner spinner = new Spinner(mTargetContext);
+    public void testGetBaseline() {
+        verifyGetBaseline(mSpinnerDialogMode);
+        verifyGetBaseline(mSpinnerDropdownMode);
+    }
 
+    private void verifySetOnItemClickListener(Spinner spinner) {
         try {
             spinner.setOnItemClickListener(null);
             fail("Should throw RuntimeException");
         } catch (RuntimeException e) {
         }
+
+        try {
+            spinner.setOnItemClickListener(mock(Spinner.OnItemClickListener.class));
+            fail("Should throw RuntimeException");
+        } catch (RuntimeException e) {
+        }
     }
 
-    @UiThreadTest
+    public void testSetOnItemClickListener() {
+        verifySetOnItemClickListener(mSpinnerDialogMode);
+        verifySetOnItemClickListener(mSpinnerDropdownMode);
+    }
+
+    private void verifyPerformClick(Spinner spinner) {
+        getInstrumentation().runOnMainSync(() -> assertTrue(spinner.performClick()));
+    }
+
     public void testPerformClick() {
-        final Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-
-        assertTrue(spinner.performClick());
-
-        // TODO: no description for the expected result for this method in its javadoc, issue?
-        // Or do UI check?
+        verifyPerformClick(mSpinnerDialogMode);
+        verifyPerformClick(mSpinnerDropdownMode);
     }
 
-    @UiThreadTest
-    public void testOnClick() {
-        Spinner spinner = new Spinner(mTargetContext);
+    private void verifyOnClick(Spinner spinner) {
         // normal value
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         AlertDialog alertDialog = builder.show();
         assertTrue(alertDialog.isShowing());
+
         spinner.onClick(alertDialog, 10);
         assertEquals(10, spinner.getSelectedItemPosition());
         assertFalse(alertDialog.isShowing());
@@ -125,32 +157,42 @@
         Dialog dialog = new Dialog(getActivity());
         dialog.show();
         assertTrue(dialog.isShowing());
+
         spinner.onClick(dialog, -10);
         assertEquals(-10, spinner.getSelectedItemPosition());
         assertFalse(dialog.isShowing());
     }
 
     @UiThreadTest
-    public void testAccessPrompt() {
+    public void testOnClick() {
+        verifyOnClick(mSpinnerDialogMode);
+        verifyOnClick(mSpinnerDropdownMode);
+    }
+
+    private void verifyAccessPrompt(Spinner spinner) {
+        final String initialPrompt = mActivity.getString(R.string.text_view_hello);
+        assertEquals(initialPrompt, spinner.getPrompt());
+
+        final Instrumentation instrumentation = getInstrumentation();
         final String promptText = "prompt text";
 
-        Spinner spinner = new Spinner(mTargetContext);
-
-        spinner.setPrompt(promptText);
+        instrumentation.runOnMainSync(() -> spinner.setPrompt(promptText));
         assertEquals(promptText, spinner.getPrompt());
 
         spinner.setPrompt(null);
         assertNull(spinner.getPrompt());
-
-        // TODO: find the dialog and get its title to assert whether setPrompt() takes effect?
     }
 
-    @UiThreadTest
-    public void testSetPromptId() {
-        Spinner spinner = new Spinner(mTargetContext);
+    public void testAccessPrompt() {
+        verifyAccessPrompt(mSpinnerDialogMode);
+        verifyAccessPrompt(mSpinnerDropdownMode);
+    }
 
-        spinner.setPromptId(R.string.hello_world);
-        assertEquals(mTargetContext.getString(R.string.hello_world), spinner.getPrompt());
+    private void verifySetPromptId(Spinner spinner) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        instrumentation.runOnMainSync(() -> spinner.setPromptId(R.string.hello_world));
+        assertEquals(mActivity.getString(R.string.hello_world), spinner.getPrompt());
 
         try {
             spinner.setPromptId(-1);
@@ -165,23 +207,209 @@
         } catch (NotFoundException e) {
             // issue 1695243, not clear what is supposed to happen if promptId is exceptional.
         }
+    }
 
-        // TODO: find the dialog and get its title to assert whether setPromptId() takes effect?
+    public void testSetPromptId() {
+        verifySetPromptId(mSpinnerDialogMode);
+        verifySetPromptId(mSpinnerDropdownMode);
     }
 
     @UiThreadTest
     public void testGetPopupContext() {
-        Theme theme = mTargetContext.getResources().newTheme();
-        Spinner themeSpinner = new Spinner(mTargetContext, null,
+        Theme theme = mActivity.getResources().newTheme();
+        Spinner themeSpinner = new Spinner(mActivity, null,
                 android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG, theme);
-        assertNotSame(mTargetContext, themeSpinner.getPopupContext());
+        assertNotSame(mActivity, themeSpinner.getPopupContext());
         assertSame(theme, themeSpinner.getPopupContext().getTheme());
 
         ContextThemeWrapper context = (ContextThemeWrapper)themeSpinner.getPopupContext();
-        assertSame(mTargetContext, context.getBaseContext());
+        assertSame(mActivity, context.getBaseContext());
     }
 
-    public void testOnLayout() {
-        // onLayout() is implementation details, do NOT test
+    private void verifyGravity(Spinner spinner) {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Note that here we're using a custom layout for the spinner's selected item
+        // that doesn't span the whole width of the parent. That way we're exercising the
+        // relevant path in spinner's layout pass that handles the currently set gravity
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, R.layout.simple_spinner_item_layout);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> spinner.setAdapter(adapter));
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, spinner, () -> {
+            spinner.setSelection(1);
+            spinner.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
+            spinner.requestLayout();
+        });
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.LEFT));
+        assertEquals(Gravity.LEFT, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.CENTER_HORIZONTAL));
+        assertEquals(Gravity.CENTER_HORIZONTAL, spinner.getGravity());
+
+        instrumentation.runOnMainSync((() -> spinner.setGravity(Gravity.RIGHT)));
+        assertEquals(Gravity.RIGHT, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.START));
+        assertEquals(Gravity.START, spinner.getGravity());
+
+        instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.END));
+        assertEquals(Gravity.END, spinner.getGravity());
+    }
+
+    public void testGravity() {
+        verifyGravity(mSpinnerDialogMode);
+        verifyGravity(mSpinnerDropdownMode);
+    }
+
+    public void testDropDownMetricsDropdownMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+        instrumentation.runOnMainSync(() -> {
+            mSpinnerDropdownMode.setDropDownWidth(dropDownWidth);
+            mSpinnerDropdownMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mSpinnerDropdownMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+        });
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+
+        // And test its attributes
+        assertEquals(dropDownWidth, mSpinnerDropdownMode.getDropDownWidth());
+        // TODO: restore when b/28089349 is addressed
+        // assertEquals(dropDownOffsetHorizontal,
+        //      mSpinnerDropdownMode.getDropDownHorizontalOffset());
+        assertEquals(dropDownOffsetVertical, mSpinnerDropdownMode.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownMetricsDialogMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+        final Resources res = mActivity.getResources();
+        final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+        final int dropDownOffsetHorizontal =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+        final int dropDownOffsetVertical =
+                res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+        instrumentation.runOnMainSync(() -> {
+            // These are all expected to be no-ops
+            mSpinnerDialogMode.setDropDownWidth(dropDownWidth);
+            mSpinnerDialogMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+            mSpinnerDialogMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+        });
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+
+        // And test its attributes. Note that we are not testing the result of getDropDownWidth
+        // for this mode
+        assertEquals(0, mSpinnerDialogMode.getDropDownHorizontalOffset());
+        assertEquals(0, mSpinnerDialogMode.getDropDownVerticalOffset());
+    }
+
+    public void testDropDownBackgroundDropdownMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+        // Set blue background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDropdownMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+        // And test its fill
+        Drawable dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.BLUE, 1, true);
+
+        // Dismiss the popup with the emulated back key
+        instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        instrumentation.waitForIdleSync();
+        // Verify that we're not showing the popup
+        assertFalse(mSpinnerDropdownMode.isPopupShowing());
+
+        // Set yellow background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDropdownMode.setPopupBackgroundDrawable(
+                        mActivity.getDrawable(R.drawable.yellow_fill)));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDropdownMode.isPopupShowing());
+        // And test its fill
+        dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+        TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+                dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+                false, Color.YELLOW, 1, true);
+    }
+
+    public void testDropDownBackgroundDialogMode() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+                R.array.string, android.R.layout.simple_spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+        // Set blue background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDialogMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+        // And test that getPopupBackground returns null
+        assertNull(mSpinnerDialogMode.getPopupBackground());
+
+        // Dismiss the popup with the emulated back key
+        instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        instrumentation.waitForIdleSync();
+        // Verify that we're not showing the popup
+        assertFalse(mSpinnerDialogMode.isPopupShowing());
+
+        // Set yellow background on the popup
+        instrumentation.runOnMainSync(() ->
+                mSpinnerDialogMode.setPopupBackgroundDrawable(
+                        mActivity.getDrawable(R.drawable.yellow_fill)));
+
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+        // Verify that we're showing the popup
+        assertTrue(mSpinnerDialogMode.isPopupShowing());
+        // And test that getPopupBackground returns null
+        assertNull(mSpinnerDialogMode.getPopupBackground());
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchTest.java b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
index 216b17b..ef33015 100644
--- a/tests/tests/widget/src/android/widget/cts/SwitchTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
@@ -17,22 +17,28 @@
 package android.widget.cts;
 
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
 import android.widget.Switch;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
 
 /**
  * Test {@link Switch}.
  */
 @SmallTest
-public class SwitchTest extends ActivityInstrumentationTestCase<SwitchCtsActivity> {
+public class SwitchTest extends ActivityInstrumentationTestCase2<SwitchCtsActivity> {
     private Activity mActivity;
     private Switch mSwitch;
 
@@ -44,7 +50,10 @@
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        mSwitch = (Switch) mActivity.findViewById(R.id.switch_view);
+    }
+
+    private Switch findSwitchById(int id) {
+        return (Switch) mActivity.findViewById(id);
     }
 
     @UiThreadTest
@@ -60,6 +69,9 @@
 
     @UiThreadTest
     public void testAccessThumbTint() {
+        mSwitch = findSwitchById(R.id.switch1);
+
+        // These are the default set in layout XML
         assertEquals(Color.WHITE, mSwitch.getThumbTintList().getDefaultColor());
         assertEquals(Mode.SRC_OVER, mSwitch.getThumbTintMode());
 
@@ -73,6 +85,9 @@
 
     @UiThreadTest
     public void testAccessTrackTint() {
+        mSwitch = findSwitchById(R.id.switch1);
+
+        // These are the default set in layout XML
         assertEquals(Color.BLACK, mSwitch.getTrackTintList().getDefaultColor());
         assertEquals(Mode.SRC_ATOP, mSwitch.getTrackTintMode());
 
@@ -83,4 +98,175 @@
         assertSame(colors, mSwitch.getTrackTintList());
         assertEquals(Mode.XOR, mSwitch.getTrackTintMode());
     }
+
+    public void testAccessThumbDrawable() {
+        mSwitch = findSwitchById(R.id.switch2);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // This is the default set in layout XML
+        Drawable thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be blue", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.BLUE, 1, true);
+
+        // Change thumb drawable to red
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbDrawable(mActivity.getDrawable(R.drawable.icon_red)));
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be red", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.RED, 1, true);
+
+        // Change thumb drawable to green
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbResource(R.drawable.icon_green));
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be green", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                Color.GREEN, 1, true);
+
+        // Now tint the latest (green) thumb drawable with 50% blue SRC_OVER
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+            mSwitch.setThumbTintList(ColorStateList.valueOf(0x800000FF));
+            mSwitch.setThumbTintMode(Mode.SRC_OVER);
+        });
+        thumbDrawable = mSwitch.getThumbDrawable();
+        TestUtils.assertAllPixelsOfColor("Thumb drawable should be green / blue", thumbDrawable,
+                thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+                TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+    }
+
+    public void testAccessTrackDrawable() {
+        mSwitch = findSwitchById(R.id.switch2);
+        final Instrumentation instrumentation = getInstrumentation();
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+            () -> mSwitch.setTrackTintMode(Mode.DST));
+
+        // This is the default set in layout XML
+        Drawable trackDrawable = mSwitch.getTrackDrawable();
+        Rect trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be 50% red", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                0x80FF0000, 1, true);
+
+        // Change track drawable to blue
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTrackDrawable(mActivity.getDrawable(R.drawable.blue_fill)));
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be blue", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                Color.BLUE, 1, true);
+
+        // Change track drawable to green
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTrackResource(R.drawable.green_fill));
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be green", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                Color.GREEN, 1, true);
+
+        // Now tint the latest (green) track drawable with 50% blue SRC_OVER
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+            mSwitch.setTrackTintList(ColorStateList.valueOf(0x800000FF));
+            mSwitch.setTrackTintMode(Mode.SRC_OVER);
+        });
+        trackDrawable = mSwitch.getTrackDrawable();
+        trackDrawableBounds = trackDrawable.getBounds();
+        TestUtils.assertAllPixelsOfColor("Track drawable should be green / blue", trackDrawable,
+                trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+                TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+    }
+
+    public void testAccessText() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Run text-related tests on a Holo-themed switch, since under Material themes we
+        // are not showing texts by default.
+        mSwitch = new Switch(new ContextThemeWrapper(mActivity, android.R.style.Theme_Holo_Light));
+        instrumentation.runOnMainSync(
+                () -> ((ViewGroup) mActivity.findViewById(R.id.container)).addView(mSwitch));
+
+        // Set "on" text and verify it
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTextOn("Text on"));
+        assertEquals("Text on", mSwitch.getTextOn());
+
+        // Set "off" text and verify it
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setTextOff("Text off"));
+        assertEquals("Text off", mSwitch.getTextOff());
+
+        // Turn text display on
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setShowText(true));
+        assertTrue(mSwitch.getShowText());
+
+        // Use custom text appearance. Since we don't have APIs to query this facet of Switch,
+        // just test that it's not crashing.
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTextAppearance(mActivity, R.style.TextAppearance_WithColor));
+
+        // Use custom typeface. Since we don't have APIs to query this facet of Switch,
+        // just test that it's not crashing.
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTypeface(Typeface.MONOSPACE));
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchTypeface(Typeface.SERIF, Typeface.ITALIC));
+
+        // Set and verify padding between the thumb and the text
+        final int thumbTextPadding = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_thumb_text_padding);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setThumbTextPadding(thumbTextPadding));
+        assertEquals(thumbTextPadding, mSwitch.getThumbTextPadding());
+
+        // Set and verify padding between the switch and the text
+        final int switchPadding = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_padding);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchPadding(switchPadding));
+        assertEquals(switchPadding, mSwitch.getSwitchPadding());
+
+        // Turn text display off
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setShowText(false));
+        assertFalse(mSwitch.getShowText());
+    }
+
+    public void testAccessMinWidth() {
+        mSwitch = findSwitchById(R.id.switch3);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Set custom min width on the switch and verify that it's at least that wide
+        final int switchMinWidth = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_min_width);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchMinWidth(switchMinWidth));
+        assertEquals(switchMinWidth, mSwitch.getSwitchMinWidth());
+        assertTrue(mSwitch.getWidth() >= switchMinWidth);
+
+        // And set another (larger) min width
+        final int switchMinWidth2 = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.switch_min_width2);
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSwitchMinWidth(switchMinWidth2));
+        assertEquals(switchMinWidth2, mSwitch.getSwitchMinWidth());
+        assertTrue(mSwitch.getWidth() >= switchMinWidth2);
+    }
+
+    public void testAccessSplitTrack() {
+        mSwitch = findSwitchById(R.id.switch3);
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSplitTrack(true));
+        assertTrue(mSwitch.getSplitTrack());
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+                () -> mSwitch.setSplitTrack(false));
+        assertFalse(mSwitch.getSplitTrack());
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 4a709dd..437b4da 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -2672,6 +2672,54 @@
         }
     }
 
+    public void testTextViewInWeigthenedLayoutChangesWidthAfterSetText() {
+        final TextView textView = new TextView(getActivity());
+        textView.setEllipsize(TruncateAt.END);
+        textView.setSingleLine(true);
+        textView.setText("a");
+
+        TextView otherTextView = new TextView(getActivity());
+        otherTextView.setSingleLine(true);
+        otherTextView.setText("any");
+
+        final LinearLayout layout = new LinearLayout(mActivity);
+        layout.setOrientation(LinearLayout.HORIZONTAL);
+
+        // TextView under test has weight 1, and width 0
+        layout.addView(textView, new LinearLayout.LayoutParams(0,
+                ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
+
+        // other TextView has default weight
+        layout.addView(otherTextView, new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        // main layout params
+        layout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        int oldWidth = textView.getWidth();
+
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText("aaa");
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        assertTrue("TextView should have larger width after a longer text is set",
+                textView.getWidth() > oldWidth);
+    }
+
     public void testSetCursorVisible() {
         mTextView = new TextView(mActivity);
 
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
index 7f9690c..872e68c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -17,8 +17,6 @@
 package android.widget.cts;
 
 import android.app.Instrumentation;
-import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
@@ -27,7 +25,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.widget.ListPopupWindow;
 import android.widget.Toolbar;
 import android.widget.cts.util.TestUtils;
 import android.widget.cts.util.ViewTestUtils;
@@ -36,8 +33,9 @@
 
 @MediumTest
 public class ToolbarTest extends ActivityInstrumentationTestCase2<ToolbarCtsActivity> {
-    private Toolbar mMainToolbar;
+    private Instrumentation mInstrumentation;
     private ToolbarCtsActivity mActivity;
+    private Toolbar mMainToolbar;
 
     public ToolbarTest() {
         super("android.widget.cts", ToolbarCtsActivity.class);
@@ -46,6 +44,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        mInstrumentation = getInstrumentation();
         mActivity = getActivity();
         mMainToolbar = mActivity.getMainToolbar();
     }
@@ -67,45 +67,41 @@
         // of getTitle / getSubtitle, this logic follows the path of deferred layout
         // and invalidation of the TextViews that show the title / subtitle in the Toolbar.
 
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
         assertEquals(mActivity.getString(R.string.toolbar_title), mMainToolbar.getTitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle("New title"));
         assertEquals("New title", mMainToolbar.getTitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
         assertEquals(mActivity.getString(R.string.toolbar_subtitle), mMainToolbar.getSubtitle());
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle("New subtitle"));
         assertEquals("New subtitle", mMainToolbar.getSubtitle());
     }
 
     public void testTitleAndSubtitleAppearance() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitle(R.string.toolbar_title));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
 
         // Since there are no APIs to get reference to the underlying implementation of
         // title and subtitle, here we are testing that calling the relevant APIs doesn't crash
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitleTextColor(Color.RED));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitleTextColor(Color.BLUE));
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setTitleTextAppearance(
                         mActivity, R.style.TextAppearance_NotColors));
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setSubtitleTextAppearance(
                         mActivity, R.style.TextAppearance_WithColor));
     }
@@ -139,9 +135,7 @@
     }
 
     public void testMenuContent() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
 
         final Menu menu = mMainToolbar.getMenu();
@@ -170,34 +164,30 @@
     }
 
     public void testMenuOverflowShowHide() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        instrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
         assertFalse(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to show overflow menu and check that it's showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertTrue(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to hide the overflow menu and check that it's not showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertFalse(mMainToolbar.isOverflowMenuShowing());
     }
 
     public void testMenuOverflowSubmenu() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
         assertFalse(mMainToolbar.isOverflowMenuShowing());
 
         // Ask to show overflow menu and check that it's showing
-        instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+        mInstrumentation.waitForIdleSync();
         assertTrue(mMainToolbar.isOverflowMenuShowing());
 
         // Register a mock menu item click listener on the toolbar
@@ -209,162 +199,256 @@
 
         // Ask to "perform" the share action and check that the menu click listener has
         // been notified
-        instrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+        mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
         verify(menuItemClickListener, times(1)).onMenuItemClick(
                 menu.findItem(R.id.action_share));
 
         // Ask to dismiss all the popups and check that we're not showing the overflow menu
-        instrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
+        mInstrumentation.waitForIdleSync();
         assertFalse(mMainToolbar.isOverflowMenuShowing());
     }
 
     public void testMenuOverflowIcon() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we're not showing overflow menu yet
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
 
         final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setOverflowIcon(overflowIcon));
 
         final Drawable toolbarOverflowIcon = mMainToolbar.getOverflowIcon();
         TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
                 toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
-                true, 0XFFFF0000, 1, false);
+                true, Color.RED, 1, false);
     }
 
     public void testActionView() {
-        final Instrumentation instrumentation = getInstrumentation();
-
         // Inflate menu and check that we don't have an expanded action view
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
         assertFalse(mMainToolbar.hasExpandedActionView());
 
         // Expand search menu item's action view and verify that main toolbar has an expanded
         // action view
         final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
-        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        mInstrumentation.waitForIdleSync();
         assertTrue(searchMenuItem.isActionViewExpanded());
         assertTrue(mMainToolbar.hasExpandedActionView());
 
         // Collapse search menu item's action view and verify that main toolbar doesn't have an
         // expanded action view
-        instrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
+        mInstrumentation.waitForIdleSync();
         assertFalse(searchMenuItem.isActionViewExpanded());
         assertFalse(mMainToolbar.hasExpandedActionView());
 
         // Expand search menu item's action view again
-        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        mInstrumentation.waitForIdleSync();
         assertTrue(searchMenuItem.isActionViewExpanded());
         assertTrue(mMainToolbar.hasExpandedActionView());
 
         // Now collapse search menu item's action view via toolbar's API and verify that main
         // toolbar doesn't have an expanded action view
-        instrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
-        instrumentation.waitForIdleSync();
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
+        mInstrumentation.waitForIdleSync();
         assertFalse(searchMenuItem.isActionViewExpanded());
         assertFalse(mMainToolbar.hasExpandedActionView());
     }
 
     public void testNavigationConfiguration() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
         Drawable toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
         TestUtils.assertAllPixelsOfColor("Navigation icon is green", toolbarNavigationIcon,
                 toolbarNavigationIcon.getIntrinsicWidth(),
                 toolbarNavigationIcon.getIntrinsicHeight(),
-                true, 0xFF00FF00, 1, false);
+                true, Color.GREEN, 1, false);
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setNavigationIcon(mActivity.getDrawable(R.drawable.icon_blue)));
         toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
         TestUtils.assertAllPixelsOfColor("Navigation icon is blue", toolbarNavigationIcon,
                 toolbarNavigationIcon.getIntrinsicWidth(),
                 toolbarNavigationIcon.getIntrinsicHeight(),
-                true, 0xFF0000FF, 1, false);
+                true, Color.BLUE, 1, false);
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setNavigationContentDescription(R.string.toolbar_navigation));
         assertEquals(mActivity.getResources().getString(R.string.toolbar_navigation),
                 mMainToolbar.getNavigationContentDescription());
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setNavigationContentDescription("Navigation legend"));
         assertEquals("Navigation legend", mMainToolbar.getNavigationContentDescription());
     }
 
     public void testLogoConfiguration() {
-        final Instrumentation instrumentation = getInstrumentation();
-
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setLogo(R.drawable.icon_yellow));
         Drawable toolbarLogo = mMainToolbar.getLogo();
         TestUtils.assertAllPixelsOfColor("Logo is yellow", toolbarLogo,
                 toolbarLogo.getIntrinsicWidth(),
                 toolbarLogo.getIntrinsicHeight(),
-                true, 0xFFFFFF00, 1, false);
+                true, Color.YELLOW, 1, false);
 
-        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
                 () -> mMainToolbar.setLogo(mActivity.getDrawable(R.drawable.icon_red)));
         toolbarLogo = mMainToolbar.getLogo();
         TestUtils.assertAllPixelsOfColor("Logo is red", toolbarLogo,
                 toolbarLogo.getIntrinsicWidth(),
                 toolbarLogo.getIntrinsicHeight(),
-                true, 0xFFFF0000, 1, false);
+                true, Color.RED, 1, false);
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setLogoDescription(R.string.toolbar_logo));
         assertEquals(mActivity.getResources().getString(R.string.toolbar_logo),
                 mMainToolbar.getLogoDescription());
 
-        instrumentation.runOnMainSync(
+        mInstrumentation.runOnMainSync(
                 () -> mMainToolbar.setLogoDescription("Logo legend"));
         assertEquals("Logo legend", mMainToolbar.getLogoDescription());
     }
 
-    @UiThreadTest
     public void testContentInsetsLtr() {
-        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
 
-        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(20, mMainToolbar.getContentInsetStart());
         assertEquals(25, mMainToolbar.getContentInsetRight());
         assertEquals(25, mMainToolbar.getContentInsetEnd());
 
-        mMainToolbar.setContentInsetsRelative(40, 20);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
         assertEquals(40, mMainToolbar.getContentInsetLeft());
         assertEquals(40, mMainToolbar.getContentInsetStart());
         assertEquals(20, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
     }
 
-    @UiThreadTest
     public void testContentInsetsRtl() {
-        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
 
-        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(25, mMainToolbar.getContentInsetStart());
         assertEquals(25, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
 
-        mMainToolbar.setContentInsetsRelative(40, 20);
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
         assertEquals(20, mMainToolbar.getContentInsetLeft());
         assertEquals(40, mMainToolbar.getContentInsetStart());
         assertEquals(40, mMainToolbar.getContentInsetRight());
         assertEquals(20, mMainToolbar.getContentInsetEnd());
     }
 
+    public void testCurrentContentInsetsLtr() {
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+        assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we haven't configured the navigation icon itself, the current content insets
+        // should stay the same
+        assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we have configured the navigation icon, and the currently set start inset with
+        // navigation is bigger than currently set start content inset, we should be getting that
+        // bigger value now
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we haven't configured the menu content, the current content insets
+        // should stay the same
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we have configured the menu content, and the currently set start inset with
+        // navigation is bigger than currently set end content inset, we should be getting that
+        // bigger value now
+        assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+    }
+
+    public void testCurrentContentInsetsRtl() {
+        mInstrumentation.runOnMainSync(
+                () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we haven't configured the navigation icon itself, the current content insets
+        // should stay the same
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+        assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+        // Since we have configured the navigation icon, and the currently set start inset with
+        // navigation is bigger than currently set start content inset, we should be getting that
+        // bigger value now
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we haven't configured the menu content, the current content insets
+        // should stay the same
+        assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+        ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+                () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+        assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+        // Since we have configured the menu content, and the currently set start inset with
+        // navigation is bigger than currently set end content inset, we should be getting that
+        // bigger value now
+        assertEquals(35, mMainToolbar.getCurrentContentInsetLeft());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+        assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+        assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+    }
+
     @UiThreadTest
     public void testPopupTheme() {
         mMainToolbar.setPopupTheme(R.style.ToolbarPopupTheme_Test);
@@ -377,7 +461,7 @@
 
         verify(mockListener, never()).onClick(any(View.class));
 
-        getInstrumentation().runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
+        mInstrumentation.runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
         verify(mockListener, times(1)).onClick(any(View.class));
 
         verifyNoMoreInteractions(mockListener);
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
index 8d8f573..97d8df1 100644
--- a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
@@ -16,20 +16,25 @@
 
 package android.widget.cts.util;
 
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
 import android.util.Pair;
 import android.view.View;
 import android.view.ViewParent;
 import junit.framework.Assert;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.mockito.Matchers.argThat;
+
 public class TestUtils {
     /**
      * This method takes a view and returns a single bitmap that is the layered combination
@@ -100,7 +105,8 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified View are of the same specified color.
+     * Checks whether all the pixels in the specified of the {@link View} are
+     * filled with the specific color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -109,7 +115,26 @@
      */
     public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull View view,
             @ColorInt int color, int allowedComponentVariance, boolean throwExceptionIfFails) {
+        assertRegionPixelsOfColor(failMessagePrefix, view,
+                new Rect(0, 0, view.getWidth(), view.getHeight()),
+                color, allowedComponentVariance, throwExceptionIfFails);
+    }
+
+    /**
+     * Checks whether all the pixels in the specific rectangular region of the {@link View} are
+     * filled with the specific color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertRegionPixelsOfColor(String failMessagePrefix, @NonNull View view,
+            @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+            boolean throwExceptionIfFails) {
         // Create a bitmap
+        final int viewWidth = view.getWidth();
+        final int viewHeight = view.getHeight();
         Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
                 Bitmap.Config.ARGB_8888);
         // Create a canvas that wraps the bitmap
@@ -118,7 +143,7 @@
         view.draw(canvas);
 
         try {
-            assertAllPixelsOfColor(failMessagePrefix, bitmap, view.getWidth(), view.getHeight(),
+            assertAllPixelsOfColor(failMessagePrefix, bitmap, region,
                     color, allowedComponentVariance, throwExceptionIfFails);
         } finally {
             bitmap.recycle();
@@ -126,7 +151,8 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified drawable are of the same specified color.
+     * Checks whether all the pixels in the specified {@link Drawable} are filled with the specific
+     * color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -136,20 +162,25 @@
     public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
             int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
             int allowedComponentVariance, boolean throwExceptionIfFails) {
-            // Create a bitmap
-            Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
-                    Bitmap.Config.ARGB_8888);
-            // Create a canvas that wraps the bitmap
-            Canvas canvas = new Canvas(bitmap);
-            if (callSetBounds) {
-                // Configure the drawable to have bounds that match the passed size
-                drawable.setBounds(0, 0, drawableWidth, drawableHeight);
-            }
-            // And ask the drawable to draw itself to the canvas / bitmap
-            drawable.draw(canvas);
+        // Create a bitmap
+        Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
+                Bitmap.Config.ARGB_8888);
+        // Create a canvas that wraps the bitmap
+        Canvas canvas = new Canvas(bitmap);
+        if (callSetBounds) {
+            // Configure the drawable to have bounds that match the passed size
+            drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+        } else {
+            // Query the current bounds of the drawable for translation
+            Rect drawableBounds = drawable.getBounds();
+            canvas.translate(-drawableBounds.left, -drawableBounds.top);
+        }
+        // And ask the drawable to draw itself to the canvas / bitmap
+        drawable.draw(canvas);
 
         try {
-            assertAllPixelsOfColor(failMessagePrefix, bitmap, drawableWidth, drawableHeight, color,
+            assertAllPixelsOfColor(failMessagePrefix, bitmap,
+                    new Rect(0, 0, drawableWidth, drawableHeight), color,
                     allowedComponentVariance, throwExceptionIfFails);
         } finally {
             bitmap.recycle();
@@ -157,49 +188,39 @@
     }
 
     /**
-     * Checks whether all the pixels in the specified bitmap are of the same specified color.
+     * Checks whether all the pixels in the specific rectangular region of the bitmap are filled
+     * with the specific color.
      *
      * In case there is a color mismatch, the behavior of this method depends on the
      * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
      * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
      * <code>Assert.fail</code> with detailed description of the mismatch.
      */
-    public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
-            int bitmapWidth, int bitmapHeight, @ColorInt int color,
-            int allowedComponentVariance, boolean throwExceptionIfFails) {
-            int[] rowPixels = new int[bitmapWidth];
-        for (int row = 0; row < bitmapHeight; row++) {
+    private static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+            @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+            boolean throwExceptionIfFails) {
+        final int bitmapWidth = bitmap.getWidth();
+        final int bitmapHeight = bitmap.getHeight();
+        final int[] rowPixels = new int[bitmapWidth];
+
+        final int startRow = region.top;
+        final int endRow = region.bottom;
+        final int startColumn = region.left;
+        final int endColumn = region.right;
+
+        for (int row = startRow; row < endRow; row++) {
             bitmap.getPixels(rowPixels, 0, bitmapWidth, 0, row, bitmapWidth, 1);
-            for (int column = 0; column < bitmapWidth; column++) {
-                int sourceAlpha = Color.alpha(rowPixels[column]);
-                int sourceRed = Color.red(rowPixels[column]);
-                int sourceGreen = Color.green(rowPixels[column]);
-                int sourceBlue = Color.blue(rowPixels[column]);
-
-                int expectedAlpha = Color.alpha(color);
-                int expectedRed = Color.red(color);
-                int expectedGreen = Color.green(color);
-                int expectedBlue = Color.blue(color);
-
-                int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
-                int varianceRed = Math.abs(sourceRed - expectedRed);
-                int varianceGreen = Math.abs(sourceGreen - expectedGreen);
-                int varianceBlue = Math.abs(sourceBlue - expectedBlue);
-
-                boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
-                        && (varianceRed <= allowedComponentVariance)
-                        && (varianceGreen <= allowedComponentVariance)
-                        && (varianceBlue <= allowedComponentVariance);
-
-                if (!isColorMatch) {
+            for (int column = startColumn; column < endColumn; column++) {
+                @ColorInt int colorAtCurrPixel = rowPixels[column];
+                if (!areColorsTheSameWithTolerance(color, colorAtCurrPixel,
+                        allowedComponentVariance)) {
                     String mismatchDescription = failMessagePrefix
-                            + ": expected all drawable colors to be ["
-                            + expectedAlpha + "," + expectedRed + ","
-                            + expectedGreen + "," + expectedBlue
-                            + "] but at position (" + row + "," + column + ") out of ("
-                            + bitmapWidth + "," + bitmapHeight + ") found ["
-                            + sourceAlpha + "," + sourceRed + ","
-                            + sourceGreen + "," + sourceBlue + "]";
+                            + ": expected all bitmap colors in rectangle [l="
+                            + startColumn + ", t=" + startRow + ", r=" + endColumn
+                            + ", b=" + endRow + "] to be " + formatColorToHex(color)
+                            + " but at position (" + row + "," + column + ") out of ("
+                            + bitmapWidth + "," + bitmapHeight + ") found "
+                            + formatColorToHex(colorAtCurrPixel);
                     if (throwExceptionIfFails) {
                         throw new RuntimeException(mismatchDescription);
                     } else {
@@ -209,4 +230,115 @@
             }
         }
     }
+
+    /**
+     * Checks whether the center pixel in the specified bitmap is of the same specified color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertCenterPixelOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+            @ColorInt int color,
+            int allowedComponentVariance, boolean throwExceptionIfFails) {
+        final int centerX = bitmap.getWidth() / 2;
+        final int centerY = bitmap.getHeight() / 2;
+        final @ColorInt int colorAtCenterPixel = bitmap.getPixel(centerX, centerY);
+        if (!areColorsTheSameWithTolerance(color, colorAtCenterPixel,
+                allowedComponentVariance)) {
+            String mismatchDescription = failMessagePrefix
+                    + ": expected all drawable colors to be "
+                    + formatColorToHex(color)
+                    + " but at position (" + centerX + "," + centerY + ") out of ("
+                    + bitmap.getWidth() + "," + bitmap.getHeight() + ") found"
+                    + formatColorToHex(colorAtCenterPixel);
+            if (throwExceptionIfFails) {
+                throw new RuntimeException(mismatchDescription);
+            } else {
+                Assert.fail(mismatchDescription);
+            }
+        }
+    }
+
+    /**
+     * Formats the passed integer-packed color into the #AARRGGBB format.
+     */
+    public static String formatColorToHex(@ColorInt int color) {
+        return String.format("#%08X", (0xFFFFFFFF & color));
+    }
+
+    /**
+     * Compares two integer-packed colors to be equal, each component within the specified
+     * allowed variance. Returns <code>true</code> if the two colors are sufficiently equal
+     * and <code>false</code> otherwise.
+     */
+    private static boolean areColorsTheSameWithTolerance(@ColorInt int expectedColor,
+            @ColorInt int actualColor, int allowedComponentVariance) {
+        int sourceAlpha = Color.alpha(actualColor);
+        int sourceRed = Color.red(actualColor);
+        int sourceGreen = Color.green(actualColor);
+        int sourceBlue = Color.blue(actualColor);
+
+        int expectedAlpha = Color.alpha(expectedColor);
+        int expectedRed = Color.red(expectedColor);
+        int expectedGreen = Color.green(expectedColor);
+        int expectedBlue = Color.blue(expectedColor);
+
+        int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+        int varianceRed = Math.abs(sourceRed - expectedRed);
+        int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+        int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+        boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+                && (varianceRed <= allowedComponentVariance)
+                && (varianceGreen <= allowedComponentVariance)
+                && (varianceBlue <= allowedComponentVariance);
+
+        return isColorMatch;
+    }
+
+    /**
+     * Composite two potentially translucent colors over each other and returns the result.
+     */
+    public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+        int bgAlpha = Color.alpha(background);
+        int fgAlpha = Color.alpha(foreground);
+        int a = compositeAlpha(fgAlpha, bgAlpha);
+
+        int r = compositeComponent(Color.red(foreground), fgAlpha,
+                Color.red(background), bgAlpha, a);
+        int g = compositeComponent(Color.green(foreground), fgAlpha,
+                Color.green(background), bgAlpha, a);
+        int b = compositeComponent(Color.blue(foreground), fgAlpha,
+                Color.blue(background), bgAlpha, a);
+
+        return Color.argb(a, r, g, b);
+    }
+
+    private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+        return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+    }
+
+    private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+        if (a == 0) return 0;
+        return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+    }
+
+    public static CharSequence sameCharSequence(final CharSequence expected) {
+        return argThat(new BaseMatcher<CharSequence>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof CharSequence) {
+                    return expected.toString().compareTo(o.toString()) == 0;
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("doesn't match " + expected);
+            }
+        });
+    }
 }
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
index e9ef867..94389f0 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
@@ -16,14 +16,15 @@
 
 package android.widget.cts.util;
 
-import junit.framework.Assert;
-
 import android.app.Instrumentation;
+import android.os.SystemClock;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnDrawListener;
+import junit.framework.Assert;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -34,8 +35,8 @@
 public class ViewTestUtils {
 
     /**
-     * Runs the specified Runnable on the main thread and ensures that the
-     * specified View's tree is drawn before returning.
+     * Runs the specified Runnable on the main thread and ensures that the specified View's tree is
+     * drawn before returning.
      *
      * @param instrumentation the instrumentation used to run the test
      * @param view the view whose tree should be drawn before returning
@@ -72,4 +73,94 @@
             throw new RuntimeException(e);
         }
     }
-}
+
+    /**
+     * Emulates a tap in the center of the passed {@link View}.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param view the view to "tap"
+     */
+    public static void emulateTapOnViewCenter(Instrumentation instrumentation, View view) {
+        emulateTapOnScreen(instrumentation, view, view.getWidth() / 2, view.getHeight() / 2);
+    }
+
+    /**
+     * Emulates a tap on a point relative to the top-left corner of the passed {@link View}. Offset
+     * parameters are used to compute the final screen coordinates of the tap point.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param anchorView the anchor view to determine the tap location on the screen
+     * @param offsetX extra X offset for the tap
+     * @param offsetY extra Y offset for the tap
+     */
+    public static void emulateTapOnScreen(Instrumentation instrumentation, View anchorView,
+            int offsetX, int offsetY) {
+        // Use instrumentation to emulate a tap on the spinner to bring down its popup
+        final int[] viewOnScreenXY = new int[2];
+        anchorView.getLocationOnScreen(viewOnScreenXY);
+        int emulatedTapX = viewOnScreenXY[0] + offsetX;
+        int emulatedTapY = viewOnScreenXY[1] + offsetY;
+
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventDown);
+
+        // Inject MOVE event
+        long moveTime = SystemClock.uptimeMillis();
+        MotionEvent eventMove = MotionEvent.obtain(
+                moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventMove);
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+        instrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        instrumentation.waitForIdleSync();
+    }
+
+    /**
+     * Emulates a drag gesture across the screen.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param dragStartX Start X of the emulated drag gesture
+     * @param dragStartY Start Y of the emulated drag gesture
+     * @param dragAmountX X amount of the emulated drag gesture
+     * @param dragAmountY Y amount of the emulated drag gesture
+     */
+    public static void emulateDragGesture(Instrumentation instrumentation,
+            int dragStartX, int dragStartY, int dragAmountX, int dragAmountY) {
+        // Inject DOWN event
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, dragStartX, dragStartY, 1);
+        instrumentation.sendPointerSync(eventDown);
+
+        // Inject a sequence of MOVE events that emulate a "swipe down" gesture
+        final int moveEventCount = 20;
+        for (int i = 0; i < moveEventCount; i++) {
+            long moveTime = SystemClock.uptimeMillis();
+            final int moveX = dragStartX + dragAmountX * i / moveEventCount;
+            final int moveY = dragStartY + dragAmountY * i / moveEventCount;
+            MotionEvent eventMove = MotionEvent.obtain(
+                    moveTime, moveTime, MotionEvent.ACTION_MOVE, moveX, moveY, 1);
+            instrumentation.sendPointerSync(eventMove);
+            // sleep for a bit to emulate a 2-second swipe
+            SystemClock.sleep(2000 / moveEventCount);
+        }
+
+        // Inject UP event
+        long upTime = SystemClock.uptimeMillis();
+        MotionEvent eventUp = MotionEvent.obtain(
+                upTime, upTime, MotionEvent.ACTION_UP, dragStartX + dragAmountX,
+                dragStartY + dragAmountY, 1);
+        instrumentation.sendPointerSync(eventUp);
+
+        // Wait for the system to process all events in the queue
+        instrumentation.waitForIdleSync();
+    }
+}
\ No newline at end of file