Snap for 9333799 from 802b88d7a9c13eec38e0d0ed6535c242384895e6 to mainline-networking-release

Change-Id: Ie55c19eef5271317af0d951685fdb40877a824ee
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java
index 0b70c8b..eab62fe 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/SystemUtil.java
@@ -33,11 +33,9 @@
 
 import com.android.modules.utils.build.SdkLevel;
 
-import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.concurrent.Callable;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
@@ -400,4 +398,18 @@
             }
         }
     }
+
+    /**
+     * Use `wait-for-broadcast-barrier` on U+
+     * and `wait-for-broadcast-idle` on previous version
+     */
+    public static void waitForBroadcasts() {
+        String cmd;
+        if (SdkLevel.isAtLeastU()) {
+            cmd = "am wait-for-broadcast-barrier";
+        } else {
+            cmd = "am wait-for-broadcast-idle";
+        }
+        runShellCommand(cmd);
+    }
 }
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index 6b1f6fc..a3cec31 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -743,7 +743,8 @@
                 "Lcom/android/sdksandbox/ISdkSandboxService;",
                 "Lcom/android/sdksandbox/SandboxLatencyInfo-IA;",
                 "Lcom/android/sdksandbox/SandboxLatencyInfo;",
-                "Lcom/android/sdksandbox/IUnloadSdkCallback;"
+                "Lcom/android/sdksandbox/IUnloadSdkCallback;",
+                "Lcom/android/sdksandbox/IComputeSdkStorageCallback;"
             );
 
     private static final ImmutableMap<String, ImmutableSet<String>> FULL_APK_IN_APEX_BURNDOWN =
@@ -1044,7 +1045,7 @@
                         final Multimap<String, String> bcpOnlyDuplicates =
                                 Multimaps.filterKeys(filteredDuplicates,
                                     sBootclasspathJars::contains);
-                        if (!filteredDuplicates.isEmpty()) {
+                        if (!bcpOnlyDuplicates.isEmpty()) {
                             synchronized (perApkClasspathDuplicates) {
                                 perApkClasspathDuplicates.put(apk, bcpOnlyDuplicates);
                             }
diff --git a/hostsidetests/appsecurity/Android.bp b/hostsidetests/appsecurity/Android.bp
index ff1e122..de8c4e2 100644
--- a/hostsidetests/appsecurity/Android.bp
+++ b/hostsidetests/appsecurity/Android.bp
@@ -32,6 +32,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/media/app/MediaMetricsTest/AndroidManifest.xml b/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml
index 78b5954..a55d689 100644
--- a/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml
+++ b/hostsidetests/media/app/MediaMetricsTest/AndroidManifest.xml
@@ -19,6 +19,7 @@
      android:targetSandboxVersion="2">
 
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-sdk android:minSdkVersion="30"/>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
index a3fe0a4..8c91c5b 100644
--- a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
+++ b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
@@ -34,14 +34,23 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.provider.DeviceConfig;
+import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.SystemUtil;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
 public class MediaMetricsAtomHostSideTests {
+    private static final String TAG = "MediaMetricsAtomHostSideTests";
     private static final String MEDIA_METRICS_MODE = "media_metrics_mode";
     private static final String PLAYER_METRICS_APP_ALLOWLIST = "player_metrics_app_allowlist";
     private static final String PLAYER_METRICS_APP_BLOCKLIST = "player_metrics_app_blocklist";
@@ -87,7 +96,7 @@
     @Test
     public void testPlaybackStateEvent_default() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackStateEvent e =
@@ -100,7 +109,7 @@
     @Test
     public void testPlaybackStateEvent() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackStateEvent e =
@@ -116,7 +125,7 @@
     @Test
     public void testPlaybackErrorEvent_default() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackErrorEvent e =
@@ -130,7 +139,7 @@
     @Test
     public void testPlaybackErrorEvent() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackErrorEvent e =
@@ -148,7 +157,7 @@
     @Test
     public void testTrackChangeEvent_default() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         TrackChangeEvent e =
@@ -160,7 +169,7 @@
     @Test
     public void testTrackChangeEvent_text() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         TrackChangeEvent e =
@@ -182,7 +191,7 @@
     @Test
     public void testTrackChangeEvent_audio() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         TrackChangeEvent e =
@@ -206,7 +215,7 @@
     @Test
     public void testTrackChangeEvent_video() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         TrackChangeEvent e =
@@ -232,7 +241,7 @@
     @Test
     public void testNetworkEvent_default() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         NetworkEvent e =
@@ -244,7 +253,7 @@
     @Test
     public void testNetworkEvent() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         NetworkEvent e =
@@ -260,7 +269,7 @@
     @Test
     public void testPlaybackMetrics_default() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackMetrics e =
@@ -272,7 +281,7 @@
     @Test
     public void testPlaybackMetrics() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackMetrics e =
@@ -301,10 +310,10 @@
 
     @Test
     public void testSessionId() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
 
-        try(PlaybackSession s = manager.createPlaybackSession()) {
+        try (PlaybackSession s = manager.createPlaybackSession()) {
             LogSessionId idObj = s.getSessionId();
             assertThat(idObj).isNotEqualTo(null);
             assertThat(idObj.getStringId().length()).isGreaterThan(0);
@@ -313,10 +322,10 @@
 
     @Test
     public void testRecordingSession() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
 
-        try(RecordingSession s = manager.createRecordingSession()) {
+        try (RecordingSession s = manager.createRecordingSession()) {
             assertThat(s).isNotEqualTo(null);
             LogSessionId idObj = s.getSessionId();
             assertThat(idObj).isNotEqualTo(null);
@@ -326,7 +335,7 @@
 
     @Test
     public void testEditingSession() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
 
         try (EditingSession s = manager.createEditingSession()) {
@@ -339,7 +348,7 @@
 
     @Test
     public void testTranscodingSession() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
 
         try (TranscodingSession s = manager.createTranscodingSession()) {
@@ -352,7 +361,7 @@
 
     @Test
     public void testBundleSession() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
 
         try (BundleSession s = manager.createBundleSession()) {
@@ -366,12 +375,12 @@
     @Test
     public void testBundleSessionPlaybackStateEvent() throws Exception {
         turnOnForTesting();
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         BundleSession s = manager.createBundleSession();
         PersistableBundle b = new PersistableBundle();
         b.putInt(BundleSession.KEY_STATSD_ATOM, 322);
-                // eventually want these keys from within the service side.
+        // eventually want these keys from within the service side.
         b.putString("playbackstateevent-sessionid", s.getSessionId().getStringId());
         b.putInt("playbackstateevent-state", PlaybackStateEvent.STATE_JOINING_FOREGROUND);
         b.putLong("playbackstateevent-lifetime", 1763L);
@@ -390,7 +399,7 @@
                             .build());
         });
         Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackStateEvent e =
@@ -400,6 +409,7 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportPlaybackStateEvent(e);
+        writeSessionIdToFile(s.getSessionId().getStringId());
         resetProperties();
     }
 
@@ -414,7 +424,7 @@
                             .build());
         });
         Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackMetrics e =
@@ -438,6 +448,7 @@
                         .addExperimentId(123)
                         .build();
         s.reportPlaybackMetrics(e);
+        writeSessionIdToFile(s.getSessionId().getStringId());
         resetProperties();
     }
 
@@ -452,7 +463,7 @@
                             .build());
         });
         Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackStateEvent e =
@@ -462,6 +473,7 @@
                         .setMetricsBundle(new Bundle())
                         .build();
         s.reportPlaybackStateEvent(e);
+        writeSessionIdToFile(s.getSessionId().getStringId());
         resetProperties();
     }
 
@@ -476,7 +488,7 @@
                             .build());
         });
         Thread.sleep(DEVICE_PROPERTY_PROPAGATION_DELAY_MICROSECONDS);
-        Context context = InstrumentationRegistry.getContext();
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
         MediaMetricsManager manager = context.getSystemService(MediaMetricsManager.class);
         PlaybackSession s = manager.createPlaybackSession();
         PlaybackMetrics e =
@@ -500,6 +512,7 @@
                         .addExperimentId(123)
                         .build();
         s.reportPlaybackMetrics(e);
+        writeSessionIdToFile(s.getSessionId().getStringId());
         resetProperties();
     }
 
@@ -526,4 +539,17 @@
      */
     @Test
     public native void testAAudioLegacyInputStream();
+
+    private void writeSessionIdToFile(String stringId) throws IOException {
+        // TODO(b/259258249): Name session id after the test.
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        Log.i(TAG, "log_session_id=" + stringId);
+        File logDir = context.getExternalFilesDir(null);
+        File logFile = new File(logDir, "log_session_id.txt");
+        logFile.createNewFile();
+        FileWriter fw = new FileWriter(logFile.getAbsolutePath());
+        fw.write(stringId);
+        fw.close();
+        Log.i(TAG, "Logged to " + logFile.getAbsolutePath());
+    }
 }
diff --git a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
index 3e6bbea0..fe2ac25 100644
--- a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
+++ b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
@@ -17,6 +17,7 @@
 package android.media.metrics.cts;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.cts.statsdatom.lib.AtomTestUtils;
 import android.cts.statsdatom.lib.ConfigUtils;
@@ -26,15 +27,21 @@
 import com.android.os.AtomsProto;
 import com.android.os.StatsLog;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
+import com.google.common.truth.Correspondence;
+
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildReceiver {
+    private static final String TAG = "MediaMetricsAtomTests";
     public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk";
     public static final String TEST_PKG = "android.media.metrics.cts";
     private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
@@ -68,9 +75,7 @@
     public void testPlaybackStateEvent_default() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testPlaybackStateEvent_default");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -79,8 +84,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
-        AtomsProto.MediaPlaybackStateChanged result =
-                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        AtomsProto.MediaPlaybackStateChanged result = data.get(
+                0).getAtom().getMediaPlaybackStateChanged();
         assertThat(result.getPlaybackState().toString()).isEqualTo("NOT_STARTED");
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
     }
@@ -88,9 +93,7 @@
     public void testPlaybackStateEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testPlaybackStateEvent");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -99,8 +102,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
-        AtomsProto.MediaPlaybackStateChanged result =
-                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        AtomsProto.MediaPlaybackStateChanged result = data.get(
+                0).getAtom().getMediaPlaybackStateChanged();
         assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
     }
@@ -109,9 +112,7 @@
     public void testBundleSessionPlaybackStateEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testBundleSessionPlaybackStateEvent");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -120,8 +121,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
-        AtomsProto.MediaPlaybackStateChanged result =
-                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        AtomsProto.MediaPlaybackStateChanged result = data.get(
+                0).getAtom().getMediaPlaybackStateChanged();
         assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
     }
@@ -130,9 +131,7 @@
     public void testPlaybackErrorEvent_default() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testPlaybackErrorEvent_default");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -141,23 +140,21 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue();
-        AtomsProto.MediaPlaybackErrorReported result =
-                data.get(0).getAtom().getMediaPlaybackErrorReported();
+        AtomsProto.MediaPlaybackErrorReported result = data.get(
+                0).getAtom().getMediaPlaybackErrorReported();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
         assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_UNKNOWN");
         assertThat(result.getSubErrorCode()).isEqualTo(0);
         assertThat(result.getExceptionStack().startsWith(
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent"))
-                        .isTrue();
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests"
+                        + ".testPlaybackErrorEvent")).isTrue();
     }
 
     public void testPlaybackErrorEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testPlaybackErrorEvent");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -166,23 +163,21 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue();
-        AtomsProto.MediaPlaybackErrorReported result =
-                data.get(0).getAtom().getMediaPlaybackErrorReported();
+        AtomsProto.MediaPlaybackErrorReported result = data.get(
+                0).getAtom().getMediaPlaybackErrorReported();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(17630000L);
         assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_RUNTIME");
         assertThat(result.getSubErrorCode()).isEqualTo(378);
         assertThat(result.getExceptionStack().startsWith(
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent"))
-                        .isTrue();
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests"
+                        + ".testPlaybackErrorEvent")).isTrue();
     }
 
     public void testTrackChangeEvent_default() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testTrackChangeEvent_default");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -191,8 +186,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
-        AtomsProto.MediaPlaybackTrackChanged result =
-                data.get(0).getAtom().getMediaPlaybackTrackChanged();
+        AtomsProto.MediaPlaybackTrackChanged result = data.get(
+                0).getAtom().getMediaPlaybackTrackChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
         assertThat(result.getState().toString()).isEqualTo("OFF");
@@ -211,9 +206,7 @@
     public void testTrackChangeEvent_text() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testTrackChangeEvent_text");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -222,8 +215,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
-        AtomsProto.MediaPlaybackTrackChanged result =
-                data.get(0).getAtom().getMediaPlaybackTrackChanged();
+        AtomsProto.MediaPlaybackTrackChanged result = data.get(
+                0).getAtom().getMediaPlaybackTrackChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
         assertThat(result.getState().toString()).isEqualTo("ON");
@@ -240,9 +233,7 @@
     public void testTrackChangeEvent_audio() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testTrackChangeEvent_audio");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -251,8 +242,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
-        AtomsProto.MediaPlaybackTrackChanged result =
-                data.get(0).getAtom().getMediaPlaybackTrackChanged();
+        AtomsProto.MediaPlaybackTrackChanged result = data.get(
+                0).getAtom().getMediaPlaybackTrackChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
         assertThat(result.getState().toString()).isEqualTo("OFF");
@@ -271,9 +262,7 @@
     public void testTrackChangeEvent_video() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testTrackChangeEvent_video");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -282,8 +271,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
-        AtomsProto.MediaPlaybackTrackChanged result =
-                data.get(0).getAtom().getMediaPlaybackTrackChanged();
+        AtomsProto.MediaPlaybackTrackChanged result = data.get(
+                0).getAtom().getMediaPlaybackTrackChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
         assertThat(result.getState().toString()).isEqualTo("OFF");
@@ -303,9 +292,7 @@
     public void testNetworkEvent_default() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testNetworkEvent_default");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -314,8 +301,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue();
-        AtomsProto.MediaNetworkInfoChanged result =
-                data.get(0).getAtom().getMediaNetworkInfoChanged();
+        AtomsProto.MediaNetworkInfoChanged result = data.get(
+                0).getAtom().getMediaNetworkInfoChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
         assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN");
@@ -324,19 +311,16 @@
     public void testNetworkEvent() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testNetworkEvent");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue();
-        AtomsProto.MediaNetworkInfoChanged result =
-                data.get(0).getAtom().getMediaNetworkInfoChanged();
+        AtomsProto.MediaNetworkInfoChanged result = data.get(
+                0).getAtom().getMediaNetworkInfoChanged();
 
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(3032L);
         assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI");
@@ -345,9 +329,7 @@
     public void testPlaybackMetrics_default() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testPlaybackMetrics_default");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
@@ -357,8 +339,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
-        AtomsProto.MediametricsPlaybackReported result =
-                data.get(0).getAtom().getMediametricsPlaybackReported();
+        AtomsProto.MediametricsPlaybackReported result = data.get(
+                0).getAtom().getMediametricsPlaybackReported();
 
         assertThat(result.getUid()).isEqualTo(appUid);
         assertThat(result.getMediaDurationMillis()).isEqualTo(-1L);
@@ -382,11 +364,8 @@
     public void testPlaybackMetrics() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testPlaybackMetrics");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -394,8 +373,8 @@
 
         assertThat(data.size()).isEqualTo(1);
         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
-        AtomsProto.MediametricsPlaybackReported result =
-                data.get(0).getAtom().getMediametricsPlaybackReported();
+        AtomsProto.MediametricsPlaybackReported result = data.get(
+                0).getAtom().getMediametricsPlaybackReported();
 
         assertThat(result.getUid()).isEqualTo(appUid);
         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
@@ -421,104 +400,96 @@
     public void testSessionId() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testSessionId");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-        assertThat(data.size()).isEqualTo(0);
+        assertThat(data).isEmpty();
     }
 
     public void testRecordingSession() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testRecordingSession");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-        assertThat(data.size()).isEqualTo(0);
+        assertThat(data).isEmpty();
     }
 
     public void testEditingSession() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testEditingSession");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-        assertThat(data.size()).isEqualTo(0);
+        assertThat(data).isEmpty();
     }
 
     public void testTranscodingSession() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testTranscodingSession");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-        assertThat(data.size()).isEqualTo(0);
+        assertThat(data).isEmpty();
     }
 
     public void testBundleSession() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testBundleSession");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-        assertThat(data.size()).isEqualTo(0);
+        assertThat(data).isEmpty();
     }
 
     public void testAppBlocklist() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testAppBlocklist");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
+        String logSessionId = getLogSessionId();
+        assertWithMessage("log session id").that(logSessionId).isNotEmpty();
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
-
-        assertThat(data.size()).isEqualTo(0);
+        List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
+                AtomsProto.Atom::getMediametricsPlaybackReported);
+        assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming(
+                AtomsProto.MediametricsPlaybackReported::getLogSessionId,
+                "getLogSessionId")).doesNotContain(logSessionId);
     }
 
+
     public void testAttributionBlocklist() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testAttributionBlocklist");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+        String logSessionId = getLogSessionId();
+        assertWithMessage("log session id").that(logSessionId).isNotEmpty();
+        List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
+                AtomsProto.Atom::getMediametricsPlaybackReported);
+        assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming(
+                AtomsProto.MediametricsPlaybackReported::getLogSessionId,
+                "getLogSessionId")).contains(logSessionId);
 
-        assertThat(data.size()).isEqualTo(1);
-        assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
-        AtomsProto.MediametricsPlaybackReported result =
-                data.get(0).getAtom().getMediametricsPlaybackReported();
+        AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter(
+                a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow();
 
         assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
@@ -540,19 +511,21 @@
     public void testAppAllowlist() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                "testAppAllowlist");
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppAllowlist");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+        String logSessionId = getLogSessionId();
+        assertWithMessage("log session id").that(logSessionId).isNotEmpty();
+        List<AtomsProto.MediaPlaybackStateChanged> stateChangedList = toMyAtoms(data,
+                AtomsProto.Atom::getMediaPlaybackStateChanged);
+        assertThat(stateChangedList).comparingElementsUsing(
+                Correspondence.transforming(AtomsProto.MediaPlaybackStateChanged::getLogSessionId,
+                        "getLogSessionId")).contains(logSessionId);
 
-        assertThat(data.size()).isEqualTo(1);
-        assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
-        AtomsProto.MediaPlaybackStateChanged result =
-                data.get(0).getAtom().getMediaPlaybackStateChanged();
+        AtomsProto.MediaPlaybackStateChanged result = stateChangedList.stream().filter(
+                a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow();
         assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
     }
@@ -560,19 +533,22 @@
     public void testAttributionAllowlist() throws Exception {
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
                 "testAttributionAllowlist");
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+        String logSessionId = getLogSessionId();
+        assertWithMessage("log session id").that(logSessionId).isNotEmpty();
+        List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
+                AtomsProto.Atom::getMediametricsPlaybackReported);
+        assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming(
+                AtomsProto.MediametricsPlaybackReported::getLogSessionId,
+                "getLogSessionId")).contains(logSessionId);
 
-        assertThat(data.size()).isEqualTo(1);
-        assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
-        AtomsProto.MediametricsPlaybackReported result =
-                data.get(0).getAtom().getMediametricsPlaybackReported();
+        AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter(
+                a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow();
 
         assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
@@ -611,19 +587,16 @@
         }
     }
 
-    private void runAAudioTestAndValidate(
-            String requiredFeature, int direction, String testFunctionName) throws Exception {
+    private void runAAudioTestAndValidate(String requiredFeature, int direction,
+            String testFunctionName) throws Exception {
         if (!DeviceUtils.hasFeature(getDevice(), requiredFeature)) {
             return;
         }
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER);
 
-        DeviceUtils.runDeviceTests(
-                getDevice(),
-                TEST_PKG,
-                "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
-                testFunctionName);
+        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+                "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName);
         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
 
         validateAAudioStreamAtom(direction);
@@ -636,8 +609,7 @@
      * the data is collected correctly.
      */
     public void testAAudioLowLatencyInputStream() throws Exception {
-        runAAudioTestAndValidate(
-                FEATURE_MICROPHONE,
+        runAAudioTestAndValidate(FEATURE_MICROPHONE,
                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
                 "testAAudioLowLatencyInputStream");
     }
@@ -649,8 +621,7 @@
      * the data is collected correctly.
      */
     public void testAAudioLowLatencyOutputStream() throws Exception {
-        runAAudioTestAndValidate(
-                FEATURE_AUDIO_OUTPUT,
+        runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT,
                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
                 "testAAudioLowLatencyOutputStream");
     }
@@ -662,8 +633,7 @@
      * the data is collected correctly.
      */
     public void testAAudioLegacyInputStream() throws Exception {
-        runAAudioTestAndValidate(
-                FEATURE_MICROPHONE,
+        runAAudioTestAndValidate(FEATURE_MICROPHONE,
                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
                 "testAAudioLegacyInputStream");
     }
@@ -675,9 +645,22 @@
      * the data is collected correctly.
      */
     public void testAAudioLegacyOutputStream() throws Exception {
-        runAAudioTestAndValidate(
-                FEATURE_AUDIO_OUTPUT,
+        runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT,
                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
                 "testAAudioLegacyOutputStream");
     }
+
+    private String getLogSessionId() throws DeviceNotAvailableException {
+        // TODO(b/259258249): Name session id file after the test.
+        String logSessionId = getDevice().pullFileContents(
+                "/storage/emulated/0/Android/data/android.media.metrics"
+                        + ".cts/files/log_session_id" + ".txt");
+        return logSessionId;
+    }
+
+    private static <T> List<T> toMyAtoms(List<StatsLog.EventMetricData> data,
+            Function<AtomsProto.Atom, T> mapper) {
+        return data.stream().map(StatsLog.EventMetricData::getAtom).map(mapper).collect(
+                Collectors.toUnmodifiableList());
+    }
 }
diff --git a/hostsidetests/multidevices/uwb/Android.bp b/hostsidetests/multidevices/uwb/Android.bp
deleted file mode 100644
index cee671a..0000000
--- a/hostsidetests/multidevices/uwb/Android.bp
+++ /dev/null
@@ -1,34 +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 {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-python_test_host {
-    name: "CtsUwbMultiDeviceTestCases",
-    main: "uwb_manager_test.py",
-    srcs: ["uwb_manager_test.py"],
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
-    test_options: {
-        unit_test: false,
-    },
-    data: [
-        // Package the snippet with the mobly test
-        ":uwb_snippet",
-    ],
-}
diff --git a/hostsidetests/multidevices/uwb/AndroidTest.xml b/hostsidetests/multidevices/uwb/AndroidTest.xml
deleted file mode 100644
index d230b3a..0000000
--- a/hostsidetests/multidevices/uwb/AndroidTest.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?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.
--->
-<configuration description="Config for CTS Uwb multi-device test cases">
-    <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="uwb" />
-    <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="not_secondary_user" />
-
-    <object class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController"
-        type="module_controller">
-        <option name="required-feature" value="android.hardware.uwb" />
-    </object>
-
-    <device name="device1">
-        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-            <option name="test-file-name" value="uwb_snippet.apk" />
-        </target_preparer>
-        <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-            <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
-            <option name="run-command" value="wm dismiss-keyguard" />
-        </target_preparer>
-        <!-- Any python dependencies can be specified and will be installed with pip -->
-        <!-- TODO(b/225958696): Import python dependencies -->
-        <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer">
-          <option name="dep-module" value="mobly" />
-        </target_preparer>
-        -->
-    </device>
-    <device name="device2">
-        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-            <option name="test-file-name" value="uwb_snippet.apk" />
-        </target_preparer>
-        <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-            <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
-            <option name="run-command" value="wm dismiss-keyguard" />
-        </target_preparer>
-    </device>
-
-    <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
-      <!-- The mobly-par-file-name should match the module name -->
-      <option name="mobly-par-file-name" value="CtsUwbMultiDeviceTestCases" />
-      <!-- Timeout limit in milliseconds for all test cases of the python binary -->
-      <option name="mobly-test-timeout" value="60000" />
-    </test>
-</configuration>
-
diff --git a/hostsidetests/multidevices/uwb/OWNERS b/hostsidetests/multidevices/uwb/OWNERS
deleted file mode 100644
index ea05fdf..0000000
--- a/hostsidetests/multidevices/uwb/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Bug component: 33618
-include platform/packages/modules/Uwb:/OWNERS
-
-# Engprod - Not owner of the test but help maintaining the module as an example
-jdesprez@google.com
-frankfeng@google.com
-murj@google.com
diff --git a/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml b/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml
deleted file mode 100644
index 6b28be9..0000000
--- a/hostsidetests/multidevices/uwb/snippet/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.snippet.uwb">
-
-  <uses-permission android:name="android.permissions.UWB_PRIVILEGED" />
-  <uses-permission android:name="android.permission.UWB_RANGING" />
-
-  <application>
-    <!-- Add any classes that implement the Snippet interface as meta-data, whose
-         value is a comma-separated string, each section being the package path
-         of a snippet class -->
-    <meta-data
-        android:name="mobly-snippets"
-        android:value="com.google.snippet.uwb.UwbManagerSnippet" />
-  </application>
-  <!-- Add an instrumentation tag so that the app can be launched through an
-       instrument command. The runner `com.google.android.mobly.snippet.SnippetRunner`
-       is derived from `AndroidJUnitRunner`, and is required to use the
-       Mobly Snippet Lib. -->
-  <instrumentation
-      android:name="com.google.android.mobly.snippet.SnippetRunner"
-      android:targetPackage="com.google.snippet.uwb" />
-</manifest>
diff --git a/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java b/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java
deleted file mode 100644
index 484d8cb..0000000
--- a/hostsidetests/multidevices/uwb/snippet/UwbManagerSnippet.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-
-package com.google.snippet.uwb;
-
-import android.app.UiAutomation;
-import android.content.Context;
-import android.uwb.UwbManager;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.google.android.mobly.snippet.Snippet;
-import com.google.android.mobly.snippet.rpc.Rpc;
-import com.google.android.mobly.snippet.util.Log;
-
-import java.lang.reflect.Method;
-
-/** Snippet class exposing Android APIs for Uwb. */
-public class UwbManagerSnippet implements Snippet {
-    private static class UwbManagerSnippetException extends Exception {
-        private static final long serialVersionUID = 1;
-
-        UwbManagerSnippetException(String msg) {
-            super(msg);
-        }
-
-        UwbManagerSnippetException(String msg, Throwable err) {
-            super(msg, err);
-        }
-    }
-    private final UwbManager mUwbManager;
-    private final Context mContext;
-
-    public UwbManagerSnippet() throws Throwable {
-        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        mUwbManager = mContext.getSystemService(UwbManager.class);
-        adoptShellPermission();
-    }
-
-    /** Get the UWB state. */
-    @Rpc(description = "Get Uwb state")
-    public boolean isUwbEnabled() {
-        return mUwbManager.isUwbEnabled();
-    }
-
-    /** Get the UWB state. */
-    @Rpc(description = "Set Uwb state")
-    public void setUwbEnabled(boolean enabled) {
-        mUwbManager.setUwbEnabled(enabled);
-    }
-
-    @Override
-    public void shutdown() {}
-
-    private void adoptShellPermission() throws Throwable {
-        UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        uia.adoptShellPermissionIdentity();
-        try {
-            Class<?> cls = Class.forName("android.app.UiAutomation");
-            Method destroyMethod = cls.getDeclaredMethod("destroy");
-            destroyMethod.invoke(uia);
-        } catch (ReflectiveOperationException e) {
-            throw new UwbManagerSnippetException("Failed to cleaup Ui Automation", e);
-        }
-    }
-}
diff --git a/hostsidetests/multidevices/uwb/uwb_manager_test.py b/hostsidetests/multidevices/uwb/uwb_manager_test.py
deleted file mode 100644
index abff616..0000000
--- a/hostsidetests/multidevices/uwb/uwb_manager_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Lint as: python3
-"""Porting UWB tests from mobly."""
-import sys
-import time
-
-import logging
-logging.basicConfig(filename="/tmp/uwb_test_log.txt", level=logging.INFO)
-
-from mobly import asserts
-from mobly import base_test
-from mobly import test_runner
-from mobly import utils
-from mobly.controllers import android_device
-from pprint import pprint
-
-UWB_SNIPPET_PACKAGE = 'com.google.snippet.uwb'
-
-class UwbManagerTest(base_test.BaseTestClass):
-
-  def setup_class(self):
-    # Declare that two Android devices are needed.
-    self.initiator, self.responder = self.register_controller(
-        android_device, min_number=2)
-
-    def setup_device(device):
-      # Expect uwb apk to be installed as it is configured to install
-      # with the module configuration AndroidTest.xml on both devices.
-      device.adb.shell([
-          'pm', 'grant', UWB_SNIPPET_PACKAGE,
-          'android.permission.UWB_RANGING'
-      ])
-      device.load_snippet('uwb_snippet', UWB_SNIPPET_PACKAGE)
-
-    # Sets up devices in parallel to save time.
-    utils.concurrent_exec(
-        setup_device, ((self.initiator,), (self.responder,)),
-        max_workers=2,
-        raise_on_exception=True)
-
-
-  def test_default_uwb_state(self):
-    """Verifies default UWB state is On after flashing the device."""
-    asserts.assert_true(self.initiator.uwb_snippet.isUwbEnabled(),
-                        "UWB state: Off; Expected: On.")
-    asserts.assert_true(self.responder.uwb_snippet.isUwbEnabled(),
-                        "UWB state: Off; Expected: On.")
-
-  def test_uwb_toggle(self):
-      """Verifies UWB toggle on/off """
-      self.initiator.uwb_snippet.setUwbEnabled(False)
-      self.responder.uwb_snippet.setUwbEnabled(False)
-      # TODO: Use callback to wait for toggle off completion.
-      time.sleep(5)
-      asserts.assert_false(self.initiator.uwb_snippet.isUwbEnabled(),
-                          "UWB state: Off; Expected: On.")
-      asserts.assert_false(self.responder.uwb_snippet.isUwbEnabled(),
-                          "UWB state: Off; Expected: On.")
-
-      self.initiator.uwb_snippet.setUwbEnabled(True)
-      self.responder.uwb_snippet.setUwbEnabled(True)
-      # TODO: Use callback to wait for toggle off completion.
-      time.sleep(5)
-      asserts.assert_true(self.initiator.uwb_snippet.isUwbEnabled(),
-                          "UWB state: Off; Expected: On.")
-      asserts.assert_true(self.responder.uwb_snippet.isUwbEnabled(),
-                          "UWB state: Off; Expected: On.")
-
-if __name__ == '__main__':
-  # Take test args
-  index = sys.argv.index('--')
-  sys.argv = sys.argv[:1] + sys.argv[index + 1:]
-
-  test_runner.main()
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0484/poc.cpp
index 1aafea3..cea0ad0 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,49 +18,37 @@
 #include <media/mediaplayer.h>
 #include "../includes/common.h"
 
-#define PREPARE_DRM 39
-
 using namespace android;
 
 int main() {
+    constexpr size_t bufferSize = 16;
+    constexpr uint32_t prepareDrm = 39;
+    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 bea2bd8..b767b53 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -63,6 +63,10 @@
     final static Pattern regexSpecialCharsEscapedPattern =
             Pattern.compile("[" + regexSpecialCharsEscaped + "]");
 
+    /**
+     * @deprecated Use {@link NativePoc} instead.
+     */
+    @Deprecated
     public static class pocConfig {
         String binaryName;
         String arguments;
@@ -79,12 +83,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(
@@ -96,10 +103,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);
     }
@@ -107,11 +116,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);
     }
@@ -119,12 +130,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();
@@ -135,48 +148,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
@@ -184,9 +206,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);
 
@@ -242,9 +270,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);
@@ -351,7 +382,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(
@@ -373,16 +407,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;
@@ -390,11 +425,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);
@@ -402,36 +439,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);
@@ -439,27 +489,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);
     }
@@ -467,12 +527,15 @@
     /**
      * 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));
     }
@@ -480,25 +543,32 @@
     /**
      * 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, CrashUtils.Config config) throws Exception {
         runPocAssertNoCrashes(pocName, device, null, config);
     }
 
     /**
      * Runs the poc binary and asserts that there are no security crashes that match the expected
      * process pattern, including arguments when running.
+     *
+     * @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 {
+    @Deprecated
+    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);
@@ -506,97 +576,115 @@
     }
 
     /**
-     * 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;
@@ -620,13 +708,14 @@
     }
 
     /**
-     * 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()) {
@@ -660,11 +749,14 @@
 
     /**
      * 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.
+     * By default, checks min crash addresses pattern. Ensure that adb logcat -c is called
+     * beforehand.
+     *
+     * @deprecated Use {@link TombstoneUtils} instead.
      * @param device device to be ran on
      * @param processPatternStrings a Pattern string to match the crash tombstone process
      */
+    @Deprecated
     public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
             throws Exception {
         assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings));
@@ -673,11 +765,14 @@
     /**
      * 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
+     * @deprecated Use {@link TombstoneUtils} instead.
      */
-    public static void assertNoCrashes(ITestDevice device,
-            CrashUtils.Config config) throws Exception {
+    @Deprecated
+    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());
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 05aa43e..c96b27a 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.
@@ -30,10 +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.runPocAssertNoCrashesNotVulnerable("CVE-2021-0484", null, getDevice());
+       AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-0484", getDevice(), 300);
     }
 }
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_2022_20475.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
new file mode 100644
index 0000000..62d0f16
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20475.java
@@ -0,0 +1,60 @@
+/*
+ * 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.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20475 extends NonRootSecurityTestCase {
+
+    /**
+     * b/240663194
+     * Vulnerable module : services.jar
+     * Is Play Managed   : No
+     */
+    @AsbSecurityTest(cveBugId = 240663194)
+    @Test
+    public void testPocCVE_2022_20475() {
+        try {
+            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);
+
+            // Run the test "testCVE_2022_20475"
+            runDeviceTests(testPkg, testPkg + ".DeviceTest", "testCVE_2022_20475");
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
new file mode 100644
index 0000000..ea39e68
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-0963",
+    defaults: [
+        "cts_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+    ],
+    platform_apis: true,
+}
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-0963/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
new file mode 100644
index 0000000..6a14b4a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?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>
+    <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-0963/res/xml/device_policies.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
new file mode 100644
index 0000000..a826e80
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/res/xml/device_policies.xml
@@ -0,0 +1,21 @@
+<?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.
+  -->
+
+<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-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
new file mode 100644
index 0000000..5592323
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocDeviceAdminReceiver.java
@@ -0,0 +1,22 @@
+/*
+ * 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.admin.DeviceAdminReceiver;
+
+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-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
new file mode 100644
index 0000000..de67f0f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0963/src/android/security/cts/CVE_2021_0963/PocStatus.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+public class PocStatus {
+    int statusCode;
+    String errorMessage;
+
+    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-20475/target-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
new file mode 100644
index 0000000..db55729
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * 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: "CVE-2022-20475-target",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    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-2022-20475/target-app/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
new file mode 100644
index 0000000..c424970
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/target-app/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?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="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-20475/test-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
new file mode 100644
index 0000000..043de912
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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: "CVE-2022-20475-test",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+    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-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
new file mode 100644
index 0000000..8ac03f6
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20475/test-app/src/android/security/cts/CVE_2022_20475/HijackActivity.java
@@ -0,0 +1,33 @@
+/*
+ * 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 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/stagedinstall/Android.bp b/hostsidetests/stagedinstall/Android.bp
index 2bab456..35850fe 100644
--- a/hostsidetests/stagedinstall/Android.bp
+++ b/hostsidetests/stagedinstall/Android.bp
@@ -605,13 +605,17 @@
 genrule {
   name: "deapexer.zip",
   tools: [
+      "blkid",
       "deapexer",
       "debugfs_static",
+      "fsck.erofs",
       "soong_zip",
   ],
   cmd: "rm -rf mkdir $(genDir)/deapexer && mkdir $(genDir)/deapexer && " +
        "cp $(location deapexer) $(genDir)/deapexer && " +
        "cp $(location debugfs_static) $(genDir)/deapexer && " +
+       "cp $(location blkid) $(genDir)/deapexer && " +
+       "cp $(location fsck.erofs) $(genDir)/deapexer && " +
        "HOST_OUT_SHARED_LIBRARIES=$$(dirname $(location deapexer))/../lib64 && " +
        "cp $${HOST_OUT_SHARED_LIBRARIES}/libc++.* $(genDir)/deapexer && " +
        "$(location soong_zip) -o $(out) -C $(genDir)/deapexer -D $(genDir)/deapexer",
diff --git a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
index ef03c1f..1e52abd 100644
--- a/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
+++ b/hostsidetests/stagedinstall/src/com/android/tests/stagedinstall/host/ApexShimValidationTest.java
@@ -76,6 +76,8 @@
     private static final String DEAPEXING_FOLDER_NAME = "deapexing_";
     private static final String DEAPEXER_FILE_NAME = "deapexer";
     private static final String DEBUGFS_STATIC_FILE_NAME = "debugfs_static";
+    private static final String BLKID_FILE_NAME = "blkid";
+    private static final String FSCKEROFS_FILE_NAME = "fsck.erofs";
 
     private static final long DEFAULT_RUN_TIMEOUT_MS = 30 * 1000L;
 
@@ -148,12 +150,14 @@
         mDeapexingDir = FileUtil.createTempDir(DEAPEXING_FOLDER_NAME);
         final File deapexer = extractDeapexer(mDeapexingDir);
         final File debugfs = new File(mDeapexingDir, DEBUGFS_STATIC_FILE_NAME);
+        final File blkid = new File(mDeapexingDir, BLKID_FILE_NAME);
+        final File fsckerofs = new File(mDeapexingDir, FSCKEROFS_FILE_NAME);
         final List<File> apexes = extractApexes(mDeapexingDir);
         for (File apex : apexes) {
             final File outDir = new File(apex.getParent(), apex.getName().substring(
                     0, apex.getName().length() - APEX_FILE_SUFFIX.length()));
             try {
-                runDeapexerExtract(deapexer, debugfs, apex, outDir);
+                runDeapexerExtract(deapexer, debugfs, blkid, fsckerofs, apex, outDir);
                 final List<File> apkFiles = FileUtil.findFiles(outDir, ".+\\.apk").stream()
                         .map(str -> new File(str)).collect(Collectors.toList());
                 for (File apkFile : apkFiles) {
@@ -252,6 +256,14 @@
         assertWithMessage("Can't find " + DEBUGFS_STATIC_FILE_NAME + " binary file")
                 .that(debugfs).isNotNull();
         debugfs.setExecutable(true);
+        final File blkid = FileUtil.findFile(destDir, BLKID_FILE_NAME);
+        assertWithMessage("Can't find " + BLKID_FILE_NAME + " binary file")
+                .that(debugfs).isNotNull();
+        blkid.setExecutable(true);
+        final File fsckerofs = FileUtil.findFile(destDir, FSCKEROFS_FILE_NAME);
+        assertWithMessage("Can't find " + FSCKEROFS_FILE_NAME + " binary file")
+                .that(debugfs).isNotNull();
+        fsckerofs.setExecutable(true);
         return deapexer;
     }
 
@@ -290,7 +302,8 @@
      * @param apex The apex file to be extracted.
      * @param outDir The out folder.
      */
-    private void runDeapexerExtract(File deapexer, File debugfs, File apex, File outDir) {
+    private void runDeapexerExtract(File deapexer, File debugfs, File blkid, File fsckerofs,
+        File apex, File outDir) {
         final RunUtil runUtil = new RunUtil();
         final String os = System.getProperty("os.name").toLowerCase();
         final boolean isMacOs = (os.startsWith("mac") || os.startsWith("darwin"));
@@ -303,6 +316,10 @@
                 deapexer.getAbsolutePath(),
                 "--debugfs_path",
                 debugfs.getAbsolutePath(),
+                "--blkid_path",
+                blkid.getAbsolutePath(),
+                "--fsckerofs_path",
+                fsckerofs.getAbsolutePath(),
                 "extract",
                 apex.getAbsolutePath(),
                 outDir.getAbsolutePath());
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 781be6b..9888e36 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -39,7 +39,6 @@
 import com.android.os.AtomsProto.FlashlightStateChanged;
 import com.android.os.AtomsProto.ForegroundServiceAppOpSessionEnded;
 import com.android.os.AtomsProto.ForegroundServiceStateChanged;
-import com.android.os.AtomsProto.GpsScanStateChanged;
 import com.android.os.AtomsProto.LmkKillOccurred;
 import com.android.os.AtomsProto.MediaCodecStateChanged;
 import com.android.os.AtomsProto.OverlayStateChanged;
@@ -50,6 +49,7 @@
 import com.android.os.AtomsProto.WakelockStateChanged;
 import com.android.os.AttributionNode;
 import com.android.os.StatsLog.EventMetricData;
+import com.android.os.gps.GpsScanStateChanged;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.log.LogUtil;
 import com.android.tradefed.testtype.DeviceTestCase;
diff --git a/hostsidetests/multidevices/uwb/snippet/Android.bp b/libs/webkit-shared/Android.bp
similarity index 64%
rename from hostsidetests/multidevices/uwb/snippet/Android.bp
rename to libs/webkit-shared/Android.bp
index 2ad7dd2..b303268 100644
--- a/hostsidetests/multidevices/uwb/snippet/Android.bp
+++ b/libs/webkit-shared/Android.bp
@@ -11,25 +11,26 @@
 // WITHOUT 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: "uwb_snippet",
-    sdk_version: "system_current",
+java_library {
+    name: "ctswebkitsharedenv",
     srcs: [
-        "UwbManagerSnippet.java",
+        "src/**/*.java",
+        "src/**/*.aidl",
     ],
-    manifest: "AndroidManifest.xml",
+    libs: [
+        "android.test.base",
+    ],
     static_libs: [
-        "androidx.test.runner",
-        "guava",
-        "mobly-snippet-lib",
-        "com.uwb.support.ccc",
-        "com.uwb.support.fira",
-        "com.uwb.support.generic",
-        "com.uwb.support.multichip",
+        "compatibility-device-util-axt",
+        "ctsdeviceutillegacy-axt",
+        "platform-test-annotations",
+    ],
+    visibility: [
+        "//cts/tests/tests/webkit:__subpackages__",
+        "//cts/tests/tests/sdksandbox/webkit:__subpackages__",
     ],
 }
diff --git a/libs/webkit-shared/OWNERS b/libs/webkit-shared/OWNERS
new file mode 100644
index 0000000..4d049f9
--- /dev/null
+++ b/libs/webkit-shared/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 76427
+include /tests/tests/webkit/OWNERS
\ No newline at end of file
diff --git a/libs/webkit-shared/README.md b/libs/webkit-shared/README.md
new file mode 100644
index 0000000..ac2a15b
--- /dev/null
+++ b/libs/webkit-shared/README.md
@@ -0,0 +1,5 @@
+# Shared Webkit Environment
+
+This helper lib makes a test suite extendable to run
+in both an activity based environment and within
+the SDK Runtime.
\ No newline at end of file
diff --git a/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl b/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl
new file mode 100644
index 0000000..d2ff7b5
--- /dev/null
+++ b/libs/webkit-shared/src/android/webkit/cts/IHostAppInvoker.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.webkit.cts;
+
+import android.view.MotionEvent;
+
+/**
+ * This shared interface is used to invoke methods
+ * that belong to the activity of a test.
+ */
+interface IHostAppInvoker {
+    void waitForIdleSync();
+
+    void sendKeyDownUpSync(int keyCode);
+
+    void sendPointerSync(in MotionEvent event);
+}
diff --git a/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.java b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.java
new file mode 100644
index 0000000..ef29810
--- /dev/null
+++ b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTest.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.webkit.cts;
+
+/**
+ * Extending this class indicates that a test can be shared between the SDK Runtime and Activity
+ * based tests.
+ *
+ * <p>If a test is shared, it will be expected to provide its own {@link
+ * SharedWebViewTestEnvironment} implementation.
+ */
+public abstract class SharedWebViewTest {
+    private SharedWebViewTestEnvironment mEnvironment;
+
+    protected abstract SharedWebViewTestEnvironment createTestEnvironment();
+
+    public void setTestEnvironment(SharedWebViewTestEnvironment sharedWebViewTestEnvironment) {
+        mEnvironment = sharedWebViewTestEnvironment;
+    }
+
+    protected SharedWebViewTestEnvironment getTestEnvironment() {
+        if (mEnvironment == null) {
+            mEnvironment = createTestEnvironment();
+        }
+        return mEnvironment;
+    }
+}
diff --git a/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java
new file mode 100644
index 0000000..e13350d
--- /dev/null
+++ b/libs/webkit-shared/src/android/webkit/cts/SharedWebViewTestEnvironment.java
@@ -0,0 +1,171 @@
+/*
+ * 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.webkit.cts;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.view.MotionEvent;
+import android.webkit.WebView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+
+/**
+ * This class contains all the environmental variables that need to be configured for WebView tests
+ * to either run inside the SDK Runtime or within an Activity.
+ */
+public final class SharedWebViewTestEnvironment {
+    @Nullable private final Context mContext;
+    @Nullable private final WebView mWebView;
+    @Nullable private final WebViewOnUiThread mWebViewOnUiThread;
+    @Nullable private final IHostAppInvoker mHostAppInvoker;
+
+    private SharedWebViewTestEnvironment(
+            Context context,
+            WebView webView,
+            WebViewOnUiThread webViewOnUiThread,
+            IHostAppInvoker hostAppInvoker) {
+        mContext = context;
+        mWebView = webView;
+        mWebViewOnUiThread = webViewOnUiThread;
+        mHostAppInvoker = hostAppInvoker;
+    }
+
+    @Nullable
+    public Context getContext() {
+        return mContext;
+    }
+
+    @Nullable
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    @Nullable
+    public WebViewOnUiThread getWebViewOnUiThread() {
+        return mWebViewOnUiThread;
+    }
+
+    /**
+     * Invokes waitForIdleSync on the {@link Instrumentation}
+     * in the activity.
+     */
+    public void waitForIdleSync() throws Exception {
+        mHostAppInvoker.waitForIdleSync();
+    }
+
+    /**
+     * Invokes sendKeyDownUpSync on the {@link Instrumentation}
+     * in the activity.
+     */
+    public void sendKeyDownUpSync(int keyCode) throws Exception {
+        mHostAppInvoker.sendKeyDownUpSync(keyCode);
+    }
+
+    /**
+     * Invokes sendPointerSync on the {@link Instrumentation}
+     * in the activity.
+     */
+    public void sendPointerSync(MotionEvent event) throws Exception {
+        mHostAppInvoker.sendPointerSync(event);
+    }
+
+    /**
+     * Use this builder to create a {@link SharedWebViewTestEnvironment}.
+     * The {@link SharedWebViewTestEnvironment} can not be built directly.
+     */
+    public static final class Builder {
+        private Context mContext;
+        private WebView mWebView;
+        private WebViewOnUiThread mWebViewOnUiThread;
+        private IHostAppInvoker mHostAppInvoker;
+
+        /**
+         * Provide a {@link Context} the tests should use
+         * for your environment.
+         */
+        public Builder setContext(@NonNull Context context) {
+            mContext = context;
+            return this;
+        }
+
+        /**
+         * Provide a {@link WebView} the tests should use
+         * for your environment.
+         */
+        public Builder setWebView(@NonNull WebView webView) {
+            mWebView = webView;
+            return this;
+        }
+
+        /**
+         * Provide a {@link WebViewOnUiThread} the tests should use
+         * for your environment.
+         */
+        public Builder setWebViewOnUiThread(@NonNull WebViewOnUiThread webViewOnUiThread) {
+            mWebViewOnUiThread = webViewOnUiThread;
+            return this;
+        }
+
+        /**
+         * Provide a {@link IHostAppInvoker} the tests should use
+         * for your environment.
+         *
+         * This can be created with {@link createHostAppInvoker}.
+         *
+         * Note: This is required.
+         */
+        public Builder setHostAppInvoker(@NonNull IHostAppInvoker hostAppInvoker) {
+            mHostAppInvoker = hostAppInvoker;
+            return this;
+        }
+
+        /**
+         * Build a new SharedWebViewTestEnvironment.
+         */
+        public SharedWebViewTestEnvironment build() {
+            if (mHostAppInvoker == null) {
+                throw new NullPointerException("The host app invoker is required");
+            }
+            return new SharedWebViewTestEnvironment(
+                    mContext, mWebView, mWebViewOnUiThread, mHostAppInvoker);
+        }
+    }
+
+    /**
+     * This will generate a new {@link IHostAppInvoker} binder node. This should be called from
+     * wherever the activity exists for test cases.
+     */
+    public static IHostAppInvoker.Stub createHostAppInvoker() {
+        return new IHostAppInvoker.Stub() {
+            private Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+            public void waitForIdleSync() {
+                mInstrumentation.waitForIdleSync();
+            }
+
+            public void sendKeyDownUpSync(int keyCode) {
+                mInstrumentation.sendKeyDownUpSync(keyCode);
+            }
+
+            public void sendPointerSync(MotionEvent event) {
+                mInstrumentation.sendPointerSync(event);
+            }
+        };
+    }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index c89716f..6405cf7 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -17,13 +17,14 @@
 package android.photopicker.cts;
 
 import static android.os.SystemProperties.getBoolean;
+import static android.photopicker.cts.PhotoPickerCloudUtils.addImage;
+import static android.photopicker.cts.PhotoPickerCloudUtils.containsExcept;
+import static android.photopicker.cts.PhotoPickerCloudUtils.extractMediaIds;
 import static android.photopicker.cts.PickerProviderMediaGenerator.MediaGenerator;
 import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
 import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
 import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImagesAndGetUris;
 import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
-import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
-import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
 import static android.photopicker.cts.util.ResultsAssertionsUtils.assertRedactedReadOnlyAccess;
 import static android.provider.MediaStore.PickerMediaColumns;
 
@@ -47,7 +48,6 @@
 
 import androidx.test.filters.SdkSuppress;
 import androidx.test.runner.AndroidJUnit4;
-import androidx.test.uiautomator.UiObject;
 
 import org.junit.After;
 import org.junit.Assume;
@@ -112,7 +112,7 @@
     public void testCloudOnlySync() throws Exception {
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
-        final ClipData clipData = fetchPickerMedia(1);
+        final ClipData clipData = launchPickerAndFetchMedia(1);
         final List<String> mediaIds = extractMediaIds(clipData, 1);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1);
@@ -123,7 +123,7 @@
         mUriList.addAll(createImagesAndGetUris(1, mContext.getUserId()));
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
-        final ClipData clipData = fetchPickerMedia(2);
+        final ClipData clipData = launchPickerAndFetchMedia(2);
         final List<String> mediaIds = extractMediaIds(clipData, 2);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1, mUriList.get(0).getLastPathSegment());
@@ -135,7 +135,7 @@
         initPrimaryCloudProviderWithImage(Pair.create(mUriList.get(0).getLastPathSegment(),
                         CLOUD_ID1));
 
-        final ClipData clipData = fetchPickerMedia(1);
+        final ClipData clipData = launchPickerAndFetchMedia(1);
         final List<String> mediaIds = extractMediaIds(clipData, 1);
 
         containsExcept(mediaIds, mUriList.get(0).getLastPathSegment(), CLOUD_ID1);
@@ -146,7 +146,7 @@
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1),
                 Pair.create(null, CLOUD_ID2));
 
-        ClipData clipData = fetchPickerMedia(2);
+        ClipData clipData = launchPickerAndFetchMedia(2);
         List<String> mediaIds = extractMediaIds(clipData, 2);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2);
@@ -155,7 +155,7 @@
                 /* trackDeleted */ true);
         syncCloudProvider(mContext);
 
-        clipData = fetchPickerMedia(2);
+        clipData = launchPickerAndFetchMedia(2);
         mediaIds = extractMediaIds(clipData, 1);
 
         containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1);
@@ -166,7 +166,7 @@
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1),
                 Pair.create(null, CLOUD_ID2));
 
-        ClipData clipData = fetchPickerMedia(2);
+        ClipData clipData = launchPickerAndFetchMedia(2);
         List<String> mediaIds = extractMediaIds(clipData, 2);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2);
@@ -175,7 +175,7 @@
                 /* trackDeleted */ false);
         syncCloudProvider(mContext);
 
-        clipData = fetchPickerMedia(2);
+        clipData = launchPickerAndFetchMedia(2);
         mediaIds = extractMediaIds(clipData, 2);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1, CLOUD_ID2);
@@ -183,7 +183,7 @@
         mCloudPrimaryMediaGenerator.setMediaCollectionId(COLLECTION_2);
         syncCloudProvider(mContext);
 
-        clipData = fetchPickerMedia(2);
+        clipData = launchPickerAndFetchMedia(2);
         mediaIds = extractMediaIds(clipData, 1);
 
         containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1);
@@ -213,7 +213,7 @@
 
         syncCloudProvider(mContext);
 
-        ClipData clipData = fetchPickerMedia(2);
+        ClipData clipData = launchPickerAndFetchMedia(2);
         List<String> mediaIds = extractMediaIds(clipData, 1);
 
         containsExcept(mediaIds, CLOUD_ID1, CLOUD_ID2);
@@ -222,7 +222,7 @@
         assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
                         CloudProviderPrimary.AUTHORITY)).isFalse();
 
-        clipData = fetchPickerMedia(2);
+        clipData = launchPickerAndFetchMedia(2);
         mediaIds = extractMediaIds(clipData, 1);
 
         containsExcept(mediaIds, CLOUD_ID2, CLOUD_ID1);
@@ -243,7 +243,7 @@
     public void testUriAccessWithValidProjection() throws Exception {
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
-        final ClipData clipData = fetchPickerMedia(1);
+        final ClipData clipData = launchPickerAndFetchMedia(1);
         final List<String> mediaIds = extractMediaIds(clipData, 1);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1);
@@ -278,7 +278,7 @@
     public void testUriAccessWithInvalidProjection() throws Exception {
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
-        final ClipData clipData = fetchPickerMedia(1);
+        final ClipData clipData = launchPickerAndFetchMedia(1);
         final List<String> mediaIds = extractMediaIds(clipData, 1);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1);
@@ -310,7 +310,7 @@
         // Sleep because the notification API throttles requests with a 1s delay
         Thread.sleep(1500);
 
-        ClipData clipData = fetchPickerMedia(1);
+        ClipData clipData = launchPickerAndFetchMedia(1);
         List<String> mediaIds = extractMediaIds(clipData, 1);
 
         assertThat(mediaIds).containsNoneIn(Collections.singletonList(CLOUD_ID1));
@@ -330,7 +330,7 @@
         // Sleep because the notification API throttles requests with a 1s delay
         Thread.sleep(1500);
 
-        clipData = fetchPickerMedia(1);
+        clipData = launchPickerAndFetchMedia(1);
         mediaIds = extractMediaIds(clipData, 1);
 
         assertThat(mediaIds).containsExactly(CLOUD_ID1);
@@ -353,60 +353,17 @@
         assertThat(storageManager.getCloudMediaProvider()).isNull();
     }
 
-    private List<String> extractMediaIds(ClipData clipData, int minCount) {
-        final int count = clipData.getItemCount();
-        assertThat(count).isAtLeast(minCount);
-
-        final List<String> mediaIds = new ArrayList<>();
-        for (int i = 0; i < count; i++) {
-            mediaIds.add(clipData.getItemAt(i).getUri().getLastPathSegment());
-        }
-
-        return mediaIds;
-    }
-
-    private ClipData fetchPickerMedia(int maxCount) throws Exception {
+    private ClipData launchPickerAndFetchMedia(int maxCount) throws Exception {
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
         intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
-        final List<UiObject> itemList = findItemList(maxCount);
-        for (int i = 0; i < itemList.size(); i++) {
-            final UiObject item = itemList.get(i);
-            item.click();
-            sDevice.waitForIdle();
-        }
-
-        final UiObject addButton = findAddButton();
-        addButton.click();
-        sDevice.waitForIdle();
-
-        return mActivity.getResult().data.getClipData();
+        return PhotoPickerCloudUtils.fetchPickerMedia(mActivity, sDevice, maxCount);
     }
 
     private void initPrimaryCloudProviderWithImage(Pair<String, String>... mediaPairs)
             throws Exception {
-        setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
-        assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
-                        CloudProviderPrimary.AUTHORITY)).isTrue();
-
-        for (Pair<String, String> pair: mediaPairs) {
-            addImage(mCloudPrimaryMediaGenerator, pair.first, pair.second);
-        }
-
-        syncCloudProvider(mContext);
-    }
-
-    private void addImage(MediaGenerator generator, String localId, String cloudId)
-            throws Exception {
-        generator.addMedia(localId, cloudId, /* albumId */ null, "image/jpeg",
-                /* mimeTypeExtension */ 0, IMAGE_SIZE_BYTES, /* isFavorite */ false,
-                R.raw.lg_g4_iso_800_jpg);
-    }
-
-    private static void containsExcept(List<String> mediaIds, String contained,
-            String notContained) {
-        assertThat(mediaIds).contains(contained);
-        assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained));
+        PhotoPickerCloudUtils.initCloudProviderWithImage(mContext, mCloudPrimaryMediaGenerator,
+                CloudProviderPrimary.AUTHORITY, mediaPairs);
     }
 }
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index ca5a251..ad62e755 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -19,11 +19,14 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.uiautomator.UiDevice;
 
+import org.junit.Assume;
 import org.junit.Before;
+import org.junit.BeforeClass;
 
 /**
  * Photo Picker Base class for Photo Picker tests. This includes common setup methods
@@ -38,6 +41,11 @@
     protected GetResultActivity mActivity;
     protected Context mContext;
 
+    @BeforeClass
+    public static void setUpClass() {
+        Assume.assumeTrue(isHardwareSupported());
+    }
+
     @Before
     public void setUp() throws Exception {
         final String setSyncDelayCommand =
@@ -58,4 +66,14 @@
         mActivity.clearResult();
         sDevice.waitForIdle();
     }
+
+    private static boolean isHardwareSupported() {
+        // These UI tests are not optimised for Watches, TVs, Auto;
+        // IoT devices do not have a UI to run these UI tests
+        PackageManager pm = sInstrumentation.getContext().getPackageManager();
+        return !pm.hasSystemFeature(pm.FEATURE_EMBEDDED)
+                && !pm.hasSystemFeature(pm.FEATURE_WATCH)
+                && !pm.hasSystemFeature(pm.FEATURE_LEANBACK)
+                && !pm.hasSystemFeature(pm.FEATURE_AUTOMOTIVE);
+    }
 }
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.java
new file mode 100644
index 0000000..204eb1c
--- /dev/null
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCloudUtils.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.photopicker.cts;
+
+import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
+import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ClipData;
+import android.content.Context;
+import android.provider.MediaStore;
+import android.util.Pair;
+
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class PhotoPickerCloudUtils {
+    public static List<String> extractMediaIds(ClipData clipData, int minCount) {
+        final int count = clipData.getItemCount();
+        assertThat(count).isAtLeast(minCount);
+
+        final List<String> mediaIds = new ArrayList<>();
+        for (int i = 0; i < count; i++) {
+            mediaIds.add(clipData.getItemAt(i).getUri().getLastPathSegment());
+        }
+
+        return mediaIds;
+    }
+
+    public static ClipData fetchPickerMedia(GetResultActivity activity, UiDevice uiDevice,
+            int maxCount) throws Exception {
+        final List<UiObject> itemList = findItemList(maxCount);
+        for (int i = 0; i < itemList.size(); i++) {
+            final UiObject item = itemList.get(i);
+            item.click();
+            uiDevice.waitForIdle();
+        }
+
+        final UiObject addButton = findAddButton();
+        addButton.click();
+        uiDevice.waitForIdle();
+
+        return activity.getResult().data.getClipData();
+    }
+
+    public static void initCloudProviderWithImage(
+            Context context, PickerProviderMediaGenerator.MediaGenerator mediaGenerator,
+            String authority, Pair<String, String>... mediaPairs) throws Exception {
+        setCloudProvider(context, authority);
+        assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(context.getContentResolver(),
+                authority)).isTrue();
+
+        for (Pair<String, String> pair : mediaPairs) {
+            addImage(mediaGenerator, pair.first, pair.second);
+        }
+
+        syncCloudProvider(context);
+    }
+
+    public static void addImage(PickerProviderMediaGenerator.MediaGenerator generator,
+            String localId, String cloudId)
+            throws Exception {
+        final long imageSizeBytes = 107684;
+        generator.addMedia(localId, cloudId, /* albumId */ null, "image/jpeg",
+                /* mimeTypeExtension */ 0, imageSizeBytes, /* isFavorite */ false,
+                R.raw.lg_g4_iso_800_jpg);
+    }
+
+    public static void containsExcept(List<String> mediaIds, String contained,
+            String notContained) {
+        assertThat(mediaIds).contains(contained);
+        assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained));
+    }
+}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
index 5cdb592..26de423 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
@@ -105,7 +105,7 @@
     public static UiObject findSettingsOverflowMenuItem(UiDevice uiDevice) throws Exception {
         final UiObject overflowMenu = getOverflowMenuObject(uiDevice);
         clickAndWait(uiDevice, overflowMenu);
-        return new UiObject(new UiSelector().textContains("Settings"));
+        return new UiObject(new UiSelector().textContains("Cloud media app"));
     }
 
     public static UiObject getOverflowMenuObject(UiDevice uiDevice)  {
diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp
index 27ccdc3..53263d4 100644
--- a/tests/tests/permission/Android.bp
+++ b/tests/tests/permission/Android.bp
@@ -49,6 +49,7 @@
         "bluetooth-test-util-lib",
         "CtsAccessibilityCommon",
         "safety-center-internal-data",
+        "sts-device-util",
     ],
     jni_libs: [
         "libctspermission_jni",
@@ -115,7 +116,6 @@
         ":CtsVictimPermissionDefinerApp",
         ":CtsAppThatRequestsSystemAlertWindow22",
         ":CtsAppThatRequestsSystemAlertWindow23",
-        ":CtsAppThatRequestCustomCameraPermission",
     ],
     per_testcase_directory: true,
 }
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index 368f94e..eafc6a6 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -94,7 +94,6 @@
         <option name="push" value="CtsAppThatHasNotificationListener.apk->/data/local/tmp/cts/permissions/CtsAppThatHasNotificationListener.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" />
-        <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk" />
     </target_preparer>
 
     <!-- Remove additional apps if installed -->
diff --git a/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
index 8dd3e96..b88b9ae 100644
--- a/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
+++ b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
@@ -16,6 +16,8 @@
 
 package android.permission.cts;
 
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
 import android.app.UiAutomation;
 import android.os.Process;
 import android.util.Log;
@@ -23,8 +25,6 @@
 import androidx.annotation.NonNull;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.compatibility.common.util.SystemUtil;
-
 import org.junit.Assert;
 
 /** Common test utilities */
@@ -151,21 +151,30 @@
             UiAutomation automation) {
         String runJobCmd = "cmd jobscheduler run -u " + Process.myUserHandle().getIdentifier()
                 + " -f " + packageName + " " + jobId;
+        try {
+            runShellCommand(automation, runJobCmd);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+        // waiting state is expected after completion for the periodic jobs.
+        awaitJobUntilRequestedState(packageName, jobId, timeout, automation, "waiting");
+    }
+
+    public static void awaitJobUntilRequestedState(
+            String packageName,
+            int jobId,
+            long timeout,
+            UiAutomation automation,
+            String requestedState) {
         String statusCmd = "cmd jobscheduler get-job-state -u "
                 + Process.myUserHandle().getIdentifier() + " " + packageName + " " + jobId;
-
-        SystemUtil.runWithShellPermissionIdentity(automation, () -> {
-            SystemUtil.runShellCommand(automation, runJobCmd);
-            Thread.sleep(500);
-            try {
-                eventually(() -> Assert.assertEquals(
-                        "The job is probably still running",
-                        "waiting",
-                        SystemUtil.runShellCommand(automation, statusCmd).trim()),
-                        timeout);
-            } catch (Throwable e) {
-                throw new RuntimeException(e);
-            }
-        });
+        try {
+            eventually(() -> Assert.assertTrue(
+                    "The job doesn't have requested state " + requestedState + " yet",
+                    runShellCommand(automation, statusCmd).trim().startsWith(requestedState)),
+                    timeout);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
     }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
index 513e1df..41a24db 100644
--- a/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
+++ b/tests/tests/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
@@ -43,10 +43,8 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.runner.AndroidJUnit4
 import com.android.compatibility.common.util.DeviceConfigStateChangerRule
-import com.android.compatibility.common.util.ProtoUtils
 import com.android.compatibility.common.util.SystemUtil.runShellCommand
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import com.android.server.job.nano.JobSchedulerServiceDumpProto
 import org.junit.After
 import org.junit.Assert
 import org.junit.Assume
@@ -159,18 +157,22 @@
     @Test
     fun testAccessibilityListenerSendsIssueToSafetyCenter() {
         setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString())
-        val automation = getAutomation()
-        mAccessibilityServiceRule.enableService()
-        TestUtils.eventually(
-            {
-                assertSafetyCenterIssueExist(
-                    SC_ACCESSIBILITY_SOURCE_ID,
-                    safetyCenterIssueId,
-                    SC_ACCESSIBILITY_ISSUE_TYPE_ID,
-                    automation)
-            },
-            TIMEOUT_MILLIS)
-        automation.destroy()
+        try {
+            val automation = getAutomation()
+            mAccessibilityServiceRule.enableService()
+            TestUtils.eventually(
+                {
+                    assertSafetyCenterIssueExist(
+                        SC_ACCESSIBILITY_SOURCE_ID,
+                        safetyCenterIssueId,
+                        SC_ACCESSIBILITY_ISSUE_TYPE_ID,
+                        automation)
+                },
+                TIMEOUT_MILLIS)
+            automation.destroy()
+        } finally {
+            setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString())
+        }
     }
 
     @Test
@@ -246,25 +248,18 @@
     @Throws(Throwable::class)
     private fun resetPermissionController() {
         PermissionUtils.clearAppState(permissionControllerPackage)
-        val currentUserId = Process.myUserHandle().identifier
-
-        // Wait until jobs are cleared
-        TestUtils.eventually(
-            {
-                val dump = getJobSchedulerDump()
-                for (job in dump!!.registeredJobs) {
-                    if (job.dump.sourceUserId == currentUserId &&
-                        job.dump.sourcePackageName == permissionControllerPackage) {
-                        Assert.assertFalse(
-                            job.dump.jobInfo.service.className.contains("AccessibilityJobService"))
-                    }
-                }
-            },
-            TIMEOUT_MILLIS)
+        TestUtils.awaitJobUntilRequestedState(
+            permissionControllerPackage,
+            ACCESSIBILITY_JOB_ID,
+            TIMEOUT_MILLIS,
+            getAutomation(),
+            "unknown"
+        )
 
         runShellCommand(
             "cmd jobscheduler reset-execution-quota -u " +
                 "${Process.myUserHandle().identifier} $permissionControllerPackage")
+        runShellCommand("cmd jobscheduler reset-schedule-quota")
 
         // Setup up permission controller again (simulate a reboot)
         val permissionControllerSetupIntent =
@@ -288,28 +283,13 @@
                 })
         }
 
-        // Wait until jobs are set up
-        TestUtils.eventually(
-            {
-                val dump = getJobSchedulerDump()
-                for (job in dump!!.registeredJobs) {
-                    if (job.dump.sourceUserId == currentUserId &&
-                        job.dump.sourcePackageName == permissionControllerPackage &&
-                        job.dump.jobInfo.service.className.contains("AccessibilityJobService")) {
-                        return@eventually
-                    }
-                }
-                Assert.fail("accessibility job not found")
-            },
-            TIMEOUT_MILLIS)
-    }
-
-    @Throws(Exception::class)
-    private fun getJobSchedulerDump(): JobSchedulerServiceDumpProto? {
-        return ProtoUtils.getProto(
+        TestUtils.awaitJobUntilRequestedState(
+            permissionControllerPackage,
+            ACCESSIBILITY_JOB_ID,
+            TIMEOUT_MILLIS,
             getAutomation(),
-            JobSchedulerServiceDumpProto::class.java,
-            ProtoUtils.DUMPSYS_JOB_SCHEDULER)
+            "waiting"
+        )
     }
 
     companion object {
diff --git a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
index 67bb916..6880e22 100644
--- a/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
@@ -24,18 +24,13 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
-import static com.android.server.job.nano.JobPackageHistoryProto.START_PERIODIC_JOB;
-import static com.android.server.job.nano.JobPackageHistoryProto.STOP_PERIODIC_JOB;
+import static com.android.compatibility.common.util.SystemUtil.waitForBroadcasts;
 
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import static java.lang.Math.max;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import android.app.NotificationManager;
@@ -57,10 +52,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
-import com.android.compatibility.common.util.ProtoUtils;
-import com.android.server.job.nano.JobPackageHistoryProto;
-import com.android.server.job.nano.JobSchedulerServiceDumpProto;
-import com.android.server.job.nano.JobSchedulerServiceDumpProto.RegisteredJob;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -105,13 +96,7 @@
             "notification_listener_check_interval_millis";
 
     protected static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
-            SECONDS.toMillis(1);
-
-    private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW =
-            "qc_max_job_count_per_rate_limiting_window";
-
-    private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS =
-            "qc_rate_limiting_window_ms";
+            SECONDS.toMillis(0);
 
     private static final String ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK =
             "com.android.permissioncontroller.action.SET_UP_NOTIFICATION_LISTENER_CHECK";
@@ -161,22 +146,6 @@
                     PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS,
                     Long.toString(OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS));
 
-    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
-    @Rule
-    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig1 =
-            new DeviceConfigStateChangerRule(sContext,
-                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW,
-                    Integer.toString(3000000));
-
-    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
-    @Rule
-    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig2 =
-            new DeviceConfigStateChangerRule(sContext,
-                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS,
-                    Integer.toString(30000));
-
     @Rule
     public CtsNotificationListenerHelperRule ctsNotificationListenerHelper =
             new CtsNotificationListenerHelperRule(sContext);
@@ -264,65 +233,23 @@
     }
 
     /**
-     * Get the state of the job scheduler
-     */
-    private static JobSchedulerServiceDumpProto getJobSchedulerDump() throws Exception {
-        return ProtoUtils.getProto(sUiAutomation, JobSchedulerServiceDumpProto.class,
-                ProtoUtils.DUMPSYS_JOB_SCHEDULER);
-    }
-
-    /**
-     * Get the last time the NOTIFICATION_LISTENER_CHECK_JOB_ID job was started/stopped for
-     * permission
-     * controller.
-     *
-     * @param event the job event (start/stop)
-     * @return the last time the event happened.
-     */
-    private static long getLastJobTime(int event) throws Exception {
-        int permControllerUid = sPackageManager.getPackageUid(PERMISSION_CONTROLLER_PKG, 0);
-
-        long lastTime = -1;
-
-        for (JobPackageHistoryProto.HistoryEvent historyEvent :
-                getJobSchedulerDump().history.historyEvent) {
-            if (historyEvent.uid == permControllerUid
-                    && historyEvent.jobId == NOTIFICATION_LISTENER_CHECK_JOB_ID
-                    && historyEvent.event == event) {
-                lastTime = max(lastTime,
-                        System.currentTimeMillis() - historyEvent.timeSinceEventMs);
-            }
-        }
-
-        return lastTime;
-    }
-
-    /**
      * Force a run of the notification listener check.
      */
     protected static void runNotificationListenerCheck() throws Throwable {
-        // Sleep a little to make sure we don't have overlap in timing
-        Thread.sleep(1000);
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                NOTIFICATION_LISTENER_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "waiting"
+        );
 
-        long beforeJob = System.currentTimeMillis();
-
-        // Sleep a little to avoid raciness in time keeping
-        Thread.sleep(1000);
-
-        runShellCommand("cmd jobscheduler run -u " + myUserHandle().getIdentifier() + " -f "
-                + PERMISSION_CONTROLLER_PKG + " " + NOTIFICATION_LISTENER_CHECK_JOB_ID);
-
-        eventually(() -> {
-            long startTime = getLastJobTime(START_PERIODIC_JOB);
-            assertTrue(startTime + " !> " + beforeJob, startTime > beforeJob);
-        }, UNEXPECTED_TIMEOUT_MILLIS);
-
-        // We can't simply require startTime <= endTime because the time being reported isn't
-        // accurate, and sometimes the end time may come before the start time by around 100 ms.
-        eventually(() -> {
-            long stopTime = getLastJobTime(STOP_PERIODIC_JOB);
-            assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob);
-        }, UNEXPECTED_TIMEOUT_MILLIS);
+        TestUtils.runJobAndWaitUntilCompleted(
+                PERMISSION_CONTROLLER_PKG,
+                NOTIFICATION_LISTENER_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation
+        );
     }
 
     /**
@@ -357,6 +284,7 @@
         runShellCommand(
                 "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " "
                         + PERMISSION_CONTROLLER_PKG);
+        runShellCommand("cmd jobscheduler reset-schedule-quota");
     }
 
     /**
@@ -364,18 +292,15 @@
      */
     private static void resetPermissionController() throws Throwable {
         clearAppState(PERMISSION_CONTROLLER_PKG);
-        int currentUserId = myUserHandle().getIdentifier();
 
         // Wait until jobs are cleared
-        eventually(() -> {
-            JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
-
-            for (RegisteredJob job : dump.registeredJobs) {
-                if (job.dump.sourceUserId == currentUserId) {
-                    assertNotEquals(job.dump.sourcePackageName, PERMISSION_CONTROLLER_PKG);
-                }
-            }
-        }, UNEXPECTED_TIMEOUT_MILLIS);
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                NOTIFICATION_LISTENER_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "unknown"
+        );
 
         // Setup up permission controller again (simulate a reboot)
         Intent permissionControllerSetupIntent = new Intent(
@@ -394,22 +319,16 @@
                     .setFlags(FLAG_RECEIVER_FOREGROUND)
                     .setPackage(PERMISSION_CONTROLLER_PKG));
         }
+        waitForBroadcasts();
 
         // Wait until jobs are set up
-        eventually(() -> {
-            JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
-
-            for (RegisteredJob job : dump.registeredJobs) {
-                if (job.dump.sourceUserId == currentUserId
-                        && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG)
-                        && job.dump.jobInfo.service.className.contains(
-                        "NotificationListenerCheck")) {
-                    return;
-                }
-            }
-
-            fail("Permission controller jobs not found");
-        }, UNEXPECTED_TIMEOUT_MILLIS);
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                NOTIFICATION_LISTENER_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "waiting"
+        );
     }
 
     /**
diff --git a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
index ceb4ede..8acf120 100644
--- a/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -31,19 +31,14 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
-import static com.android.server.job.nano.JobPackageHistoryProto.START_PERIODIC_JOB;
-import static com.android.server.job.nano.JobPackageHistoryProto.STOP_JOB;
-import static com.android.server.job.nano.JobPackageHistoryProto.STOP_PERIODIC_JOB;
+import static com.android.compatibility.common.util.SystemUtil.waitForBroadcasts;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import static java.lang.Math.max;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import android.app.ActivityManager;
@@ -65,30 +60,24 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.permission.cts.appthataccesseslocation.IAccessLocationOnCommand;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.AsbSecurityTest;
 import android.platform.test.annotations.SystemUserOnly;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
-import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SdkSuppress;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
-import com.android.compatibility.common.util.ProtoUtils;
 import com.android.compatibility.common.util.mainline.MainlineModule;
 import com.android.compatibility.common.util.mainline.ModuleDetector;
-import com.android.modules.utils.build.SdkLevel;
-import com.android.server.job.nano.JobPackageHistoryProto;
-import com.android.server.job.nano.JobSchedulerServiceDumpProto;
-import com.android.server.job.nano.JobSchedulerServiceDumpProto.RegisteredJob;
 
 import org.junit.After;
 import org.junit.AfterClass;
@@ -98,7 +87,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -133,10 +121,6 @@
     private static final String PROPERTY_LOCATION_ACCESS_PERIODIC_INTERVAL_MILLIS =
             "location_access_check_periodic_interval_millis";
     private static final String PROPERTY_BG_LOCATION_CHECK_ENABLED = "bg_location_check_is_enabled";
-    private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW =
-            "qc_max_job_count_per_rate_limiting_window";
-    private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS =
-            "qc_rate_limiting_window_ms";
 
     private static final long UNEXPECTED_TIMEOUT_MILLIS = 10000;
     private static final long EXPECTED_TIMEOUT_MILLIS = 15000;
@@ -212,27 +196,17 @@
                     PROPERTY_LOCATION_ACCESS_CHECK_DELAY_MILLIS,
                     "50");
 
-    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
-    @Rule
-    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig1 =
-            new DeviceConfigStateChangerRule(sContext,
-                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW,
-                    Integer.toString(3000000));
-
-    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
-    @Rule
-    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig2 =
-            new DeviceConfigStateChangerRule(sContext,
-                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
-                    PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS,
-                    Integer.toString(30000));
+    @BeforeClass
+    public static void beforeClassSetup() throws Exception {
+        reduceDelays();
+        allowNotificationAccess();
+        installBackgroundAccessApp();
+    }
 
     /**
      * Change settings so that permission controller can show location access notifications more
      * often.
      */
-    @BeforeClass
     public static void reduceDelays() {
         runWithShellPermissionIdentity(() -> {
             ContentResolver cr = sContext.getContentResolver();
@@ -242,10 +216,16 @@
         });
     }
 
+    @AfterClass
+    public static void cleanupAfterClass() throws Throwable {
+        resetDelays();
+        uninstallBackgroundAccessApp();
+        disallowNotificationAccess();
+    }
+
     /**
      * Reset settings so that permission controller runs normally.
      */
-    @AfterClass
     public static void resetDelays() throws Throwable {
         runWithShellPermissionIdentity(() -> {
             ContentResolver cr = sContext.getContentResolver();
@@ -347,14 +327,6 @@
     }
 
     /**
-     * Get the state of the job scheduler
-     */
-    public static JobSchedulerServiceDumpProto getJobSchedulerDump() throws Exception {
-        return ProtoUtils.getProto(sUiAutomation, JobSchedulerServiceDumpProto.class,
-                ProtoUtils.DUMPSYS_JOB_SCHEDULER);
-    }
-
-    /**
      * Clear all data of a package including permissions and files.
      *
      * @param pkg The name of the package to be cleared
@@ -364,85 +336,35 @@
         runShellCommand("pm clear --user -2 " + pkg);
     }
 
-    /**
-     * Get the last time the LOCATION_ACCESS_CHECK_JOB_ID job was started/stopped for permission
-     * controller.
-     *
-     * @param event the job event (start/stop)
-     * @return the last time the event happened.
-     */
-    private static long getLastJobTime(int event) throws Exception {
-        int permControllerUid = sPackageManager.getPackageUid(PERMISSION_CONTROLLER_PKG, 0);
-
-        long lastTime = -1;
-
-        for (JobPackageHistoryProto.HistoryEvent historyEvent :
-                getJobSchedulerDump().history.historyEvent) {
-            if (historyEvent.uid == permControllerUid
-                    && historyEvent.jobId == LOCATION_ACCESS_CHECK_JOB_ID
-                    && historyEvent.event == event) {
-                lastTime = max(lastTime,
-                        System.currentTimeMillis() - historyEvent.timeSinceEventMs);
-            }
-        }
-
-        return lastTime;
+    private static boolean isJobReady() {
+        String jobStatus = runShellCommand("cmd jobscheduler get-job-state -u "
+                + Process.myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG
+                + " " + LOCATION_ACCESS_CHECK_JOB_ID);
+        return jobStatus.contains("waiting");
     }
 
     /**
      * Force a run of the location check.
      */
     private static void runLocationCheck() throws Throwable {
-        // If the job isn't setup, do it before running a location check
-        if (!isLocationAccessJobSetup(myUserHandle().getIdentifier())) {
+        if (!isJobReady()) {
             setupLocationAccessCheckJob();
         }
 
-        // Sleep a little bit to make sure we don't have overlap in timing
-        Thread.sleep(1000);
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                LOCATION_ACCESS_CHECK_JOB_ID,
+                EXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "waiting"
+        );
 
-        long beforeJob = System.currentTimeMillis();
-
-        // Sleep a little bit to avoid raciness in time keeping
-        Thread.sleep(1000);
-
-        runShellCommand(
-                "cmd jobscheduler run -u " + android.os.Process.myUserHandle().getIdentifier()
-                        + " -f " + PERMISSION_CONTROLLER_PKG + " 0");
-
-        eventually(() -> {
-            long startTime = getLastJobTime(START_PERIODIC_JOB);
-            assertTrue(startTime + " !> " + beforeJob, startTime > beforeJob);
-        }, EXPECTED_TIMEOUT_MILLIS);
-
-        // We can't simply require startTime <= endTime because the time being reported isn't
-        // accurate, and sometimes the end time may come before the start time by around 100 ms.
-        eventually(() -> {
-            long stopTime;
-            if (SdkLevel.isAtLeastT()) {
-                stopTime = getLastJobTime(STOP_PERIODIC_JOB);
-            } else {
-                stopTime = getLastJobTime(STOP_JOB);
-            }
-            assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob);
-        }, EXPECTED_TIMEOUT_MILLIS);
-    }
-
-    /**
-     * Get a notification thrown by the permission controller that is currently visible.
-     *
-     * @return The notification or {@code null} if there is none
-     */
-    private @Nullable StatusBarNotification getPermissionControllerNotification() throws Exception {
-        NotificationListenerService notificationService = NotificationListener.getInstance();
-
-        for (StatusBarNotification notification : notificationService.getActiveNotifications()) {
-            if (notification.getPackageName().equals(PERMISSION_CONTROLLER_PKG)) {
-                return notification;
-            }
-        }
-
-        return null;
+        TestUtils.runJobAndWaitUntilCompleted(
+                PERMISSION_CONTROLLER_PKG,
+                LOCATION_ACCESS_CHECK_JOB_ID,
+                EXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation
+        );
     }
 
     /**
@@ -452,29 +374,8 @@
      * @return The notification or {@code null} if there is none
      */
     private StatusBarNotification getNotification(boolean cancelNotification) throws Throwable {
-        NotificationListenerService notificationService = NotificationListener.getInstance();
-
-        StatusBarNotification notification = getPermissionControllerNotification();
-        if (notification == null) {
-            return null;
-        }
-
-        if (notification.getId() == LOCATION_ACCESS_CHECK_NOTIFICATION_ID) {
-            if (cancelNotification) {
-                notificationService.cancelNotification(notification.getKey());
-
-                // Wait for notification to get canceled
-                eventually(() -> assertFalse(
-                        Arrays.asList(notificationService.getActiveNotifications()).contains(
-                                notification)), UNEXPECTED_TIMEOUT_MILLIS);
-            }
-
-            return notification;
-        }
-
-        Log.d(LOG_TAG, "Bad notification " + notification);
-
-        return null;
+        return NotificationListenerUtils.getNotificationForPackageAndId(PERMISSION_CONTROLLER_PKG,
+                LOCATION_ACCESS_CHECK_NOTIFICATION_ID, cancelNotification);
     }
 
     /**
@@ -489,13 +390,11 @@
     /**
      * Register {@link NotificationListener}.
      */
-    @BeforeClass
     public static void allowNotificationAccess() {
         runShellCommand("cmd notification allow_listener " + (new ComponentName(sContext,
                 NotificationListener.class).flattenToString()));
     }
 
-    @BeforeClass
     public static void installBackgroundAccessApp() throws Exception {
         installBackgroundAccessApp(false);
     }
@@ -511,7 +410,6 @@
         Thread.sleep(5000);
     }
 
-    @AfterClass
     public static void uninstallBackgroundAccessApp() {
         unbindService();
         runShellCommand("pm uninstall " + TEST_APP_PKG);
@@ -555,18 +453,15 @@
     /**
      * Skip each test for low ram device
      */
-    @Before
     public void assumeIsNotLowRamDevice() {
         assumeFalse(sActivityManager.isLowRamDevice());
     }
 
-    @Before
     public void wakeUpAndDismissKeyguard() {
         runShellCommand("input keyevent KEYCODE_WAKEUP");
         runShellCommand("wm dismiss-keyguard");
     }
 
-    @Before
     public void bindService() {
         sConnection = new ServiceConnection() {
             @Override
@@ -587,11 +482,20 @@
         sContext.bindService(testAppService, sConnection, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND);
     }
 
+    @Before
+    public void beforeEachTestSetup() throws Throwable {
+        assumeIsNotLowRamDevice();
+        wakeUpAndDismissKeyguard();
+        bindService();
+        resetPermissionControllerBeforeEachTest();
+        assumeCanGetFineLocation();
+    }
+
     /**
      * Reset the permission controllers state before each test
      */
-    @Before
     public void resetPermissionControllerBeforeEachTest() throws Throwable {
+        //setupLocationAccessCheckJob();
         // Has to be before resetPermissionController to make sure enablement time is the reset time
         // of permission controller
         enableLocationAccessCheck();
@@ -604,6 +508,7 @@
         runShellCommand(
                 "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " "
                         + PERMISSION_CONTROLLER_PKG);
+        runShellCommand("cmd jobscheduler reset-schedule-quota");
     }
 
     /**
@@ -629,7 +534,6 @@
     /**
      * Make sure fine location can be accessed at all.
      */
-    @Before
     public void assumeCanGetFineLocation() {
         if (sCanAccessFineLocation == null) {
             Criteria crit = new Criteria();
@@ -672,38 +576,22 @@
      */
     private static void resetPermissionController() throws Throwable {
         clearPackageData(PERMISSION_CONTROLLER_PKG);
-        int currentUserId = myUserHandle().getIdentifier();
-
-        // Wait until jobs are cleared
-        eventually(() -> {
-            JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
-
-            for (RegisteredJob job : dump.registeredJobs) {
-                if (job.dump.sourceUserId == currentUserId) {
-                    assertNotEquals(job.dump.sourcePackageName, PERMISSION_CONTROLLER_PKG);
-                }
-            }
-        }, UNEXPECTED_TIMEOUT_MILLIS);
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                LOCATION_ACCESS_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "unknown"
+        );
 
         setupLocationAccessCheckJob();
-
-        // Wait until jobs are set up
-        eventually(() -> {
-            assertTrue("LocationAccessCheck job not found",
-                    isLocationAccessJobSetup(currentUserId));
-        }, UNEXPECTED_TIMEOUT_MILLIS);
-    }
-
-    private static boolean isLocationAccessJobSetup(int currentUserId) throws Exception {
-        JobSchedulerServiceDumpProto dump = getJobSchedulerDump();
-        for (RegisteredJob job : dump.registeredJobs) {
-            if (job.dump.sourceUserId == currentUserId
-                    && job.dump.sourcePackageName.equals(PERMISSION_CONTROLLER_PKG)
-                    && job.dump.jobInfo.service.className.contains("LocationAccessCheck")) {
-                return true;
-            }
-        }
-        return false;
+        TestUtils.awaitJobUntilRequestedState(
+                PERMISSION_CONTROLLER_PKG,
+                LOCATION_ACCESS_CHECK_JOB_ID,
+                UNEXPECTED_TIMEOUT_MILLIS,
+                sUiAutomation,
+                "waiting"
+        );
     }
 
     private static void setupLocationAccessCheckJob() {
@@ -724,27 +612,31 @@
                     .setFlags(FLAG_RECEIVER_FOREGROUND)
                     .setPackage(PERMISSION_CONTROLLER_PKG));
         }
+        waitForBroadcasts();
     }
 
     /**
      * Unregister {@link NotificationListener}.
      */
-    @AfterClass
     public static void disallowNotificationAccess() {
         runShellCommand("cmd notification disallow_listener " + (new ComponentName(sContext,
                 NotificationListener.class)).flattenToString());
     }
 
+    @After
+    public void cleanupAfterEachTest() throws Throwable {
+        resetPrivacyConfig();
+        locationUnbind();
+    }
+
     /**
      * Reset location access check
      */
-    @After
     public void resetPrivacyConfig() throws Throwable {
         // Run a location access check to update enabled state inside permission controller
         runLocationCheck();
     }
 
-    @After
     public void locationUnbind() throws Throwable {
         unbindService();
     }
@@ -786,6 +678,7 @@
 
         // Wait until package is cleared and permission controller has cleared the state
         Thread.sleep(10000);
+        waitForBroadcasts();
 
         // Clearing removed the permissions, hence grant them again
         grantPermissionToTestApp(ACCESS_FINE_LOCATION);
@@ -811,7 +704,7 @@
         Thread.sleep(2000);
 
         installBackgroundAccessApp();
-
+        waitForBroadcasts();
         accessLocation();
         runLocationCheck();
 
@@ -829,12 +722,14 @@
         eventually(() -> assertNotNull(getNotification(false)), EXPECTED_TIMEOUT_MILLIS);
 
         uninstallBackgroundAccessApp();
+        // wait for permission controller (broadcast receiver) to clean up things
+        Thread.sleep(5000);
+        waitForBroadcasts();
 
         try {
             eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
         } finally {
             installBackgroundAccessApp();
-            getNotification(true);
         }
     }
 
@@ -887,6 +782,7 @@
         assertNull(getNotification(false));
 
         enableLocationAccessCheck();
+        Thread.sleep(2000);
 
         // Trigger update of location enable time. In the real world it enabling happens on the
         // first location check. I.e. accesses before this location check are ignored.
@@ -935,6 +831,7 @@
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
     public void notificationOnClickOpensSafetyCenter() throws Throwable {
+        assumeTrue(SafetyCenterUtils.deviceSupportsSafetyCenter(sContext));
         accessLocation();
         runLocationCheck();
 
diff --git a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
index 88006b9..8999a93 100644
--- a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
@@ -109,7 +109,6 @@
         eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
 
         runNotificationListenerCheck();
-
         ensure(() -> assertNull("Expected no notifications", getNotification(false)),
                 ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
     }
@@ -117,11 +116,9 @@
     @Test
     public void notificationIsShownAgainAfterClear() throws Throwable {
         runNotificationListenerCheck();
-
         eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
 
         clearAppState(TEST_APP_PKG);
-
         // Wait until package is cleared and permission controller has cleared the state
         Thread.sleep(2000);
 
diff --git a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
index 05bc542..6c6f3cb 100644
--- a/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/OneTimePermissionTest.java
@@ -17,7 +17,6 @@
 package android.permission.cts;
 
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
-import static android.Manifest.permission.CAMERA;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
@@ -32,7 +31,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.platform.test.annotations.AsbSecurityTest;
 import android.provider.DeviceConfig;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
@@ -98,7 +96,6 @@
     @Before
     public void installApp() {
         runShellCommand("pm install -r " + APK);
-        runShellCommand("pm install -r " + CUSTOM_CAMERA_PERM_APK);
     }
 
     @Before
@@ -119,7 +116,6 @@
     @After
     public void uninstallApp() {
         runShellCommand("pm uninstall " + APP_PKG_NAME);
-        runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME);
     }
 
     @After
@@ -226,33 +222,6 @@
         }));
     }
 
-    @Test
-    @AsbSecurityTest(cveBugId = 237405974L)
-    public void testCustomPermissionIsGrantedOneTime() throws Throwable {
-        Intent startApp = new Intent()
-                .setComponent(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME,
-                        CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission"))
-                .addFlags(FLAG_ACTIVITY_NEW_TASK);
-
-        mContext.startActivity(startApp);
-
-        // We're only manually granting CAMERA, but the app will later request CUSTOM and get it
-        // granted silently. This is intentional since it's in the same group but both should
-        // eventually be revoked
-        clickOneTimeButton();
-
-        // Just waiting for the revocation
-        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
-                mContext.getPackageManager()
-                        .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
-
-        // This checks the vulnerability
-        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
-                mContext.getPackageManager()
-                        .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
-
-    }
-
     private void assertGrantedState(String s, int permissionGranted, long timeoutMillis) {
         eventually(() -> Assert.assertEquals(s,
                 permissionGranted, mPackageManager
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/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index 71442c7..6a02041 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -15,9 +15,13 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-     package="com.android.car.updatable" >
+     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" >
 
+    <!--
+        This file contains the permissions defined by CarService-Builtin(com.android.car)
+        and CarService-updatable(com.[google.]?android.car.updatable). As this is only a
+        resource file, permissions from both packages can be added here.
+    -->
     <permission-group android:name="android.car.permission-group.CAR_MONITORING"
          android:icon="@drawable/perm_group_car"
          android:description="@string/car_permission_desc"
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index ca4794d..752a794 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -133,6 +133,35 @@
 
             declaredPermissionsMap.putAll(
                     getPermissionsForPackage(sContext, carServicePackageName));
+
+            // Load signature permission declared in CarService-builtin
+            String carServiceBuiltInPackageName = "com.android.car";
+            Map<String, PermissionInfo> carServiceBuiltInPermissionsMap = getPermissionsForPackage(
+                    sContext, carServiceBuiltInPackageName);
+            // carServiceBuiltInPermissionsMap should only have signature permissions and those
+            // permissions should not be defined in car service updatable.
+            for (Map.Entry<String, PermissionInfo> permissionData : carServiceBuiltInPermissionsMap
+                    .entrySet()) {
+                PermissionInfo carServiceBuiltInDeclaredPermission = permissionData.getValue();
+                String carServiceBuiltInDeclaredPermissionName = permissionData.getKey();
+
+                // Signature only permission should be defined in built-in car service
+                if ((carServiceBuiltInDeclaredPermission
+                        .getProtection() != PermissionInfo.PROTECTION_SIGNATURE)
+                        || (carServiceBuiltInDeclaredPermission.getProtectionFlags() != 0)) {
+                    offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName
+                            + " should be signature only permission to be declared in"
+                            + " carServiceBuiltIn package.");
+                    continue;
+                }
+
+                if (declaredPermissionsMap.get(carServiceBuiltInDeclaredPermissionName) != null) {
+                    offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName
+                            + " from car service builtin is already declared in other packages.");
+                    continue;
+                }
+            }
+            declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap);
         }
 
         for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 266b486..40feeb4 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -202,5 +202,7 @@
     protected fun startActivityForFuture(
         intent: Intent
     ): CompletableFuture<Instrumentation.ActivityResult> =
-        activityRule.launchActivity(null).startActivityForFuture(intent)
+        CompletableFuture<Instrumentation.ActivityResult>().also {
+            activityRule.launchActivity(null).startActivityForFuture(intent, it)
+        }
 }
diff --git a/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt b/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt
index 19cf115..1774030 100644
--- a/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/StartForFutureActivity.kt
@@ -22,17 +22,22 @@
 import java.util.concurrent.CompletableFuture
 
 class StartForFutureActivity : Activity() {
-    private val future = CompletableFuture<Instrumentation.ActivityResult>()
-
-    fun startActivityForFuture(intent: Intent): CompletableFuture<Instrumentation.ActivityResult> {
+    fun startActivityForFuture(
+        intent: Intent,
+        future: CompletableFuture<Instrumentation.ActivityResult>
+    ) {
         startActivityForResult(intent, 1)
-        return future
+        StartForFutureActivity.future = future
     }
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
-
-        future.complete(Instrumentation.ActivityResult(resultCode, data))
+        future!!.complete(Instrumentation.ActivityResult(resultCode, data))
+        future = null
         finish()
     }
+
+    companion object {
+        private var future: CompletableFuture<Instrumentation.ActivityResult>? = null
+    }
 }
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index b88fcf5..7abf096 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -32,6 +32,7 @@
         "mockito-target-minus-junit4",
         // TODO: remove testng once Android migrates to JUnit 4.12, which provides assertThrows
         "testng",
+        "sts-device-util",
     ],
 
     jni_libs: [
diff --git a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
index be6ff87..eaddc09 100644
--- a/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MultiAuthorityTest.java
@@ -16,24 +16,20 @@
 
 package android.provider.cts;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
-import com.android.compatibility.common.util.SystemUtil;
-
 import android.app.ActivityManager;
-import android.app.Instrumentation;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
-import android.content.Context;
-import android.provider.SearchIndexableResource;
 
-import androidx.test.filters.SmallTest;
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import org.junit.After;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,26 +42,24 @@
     private static final String PROVIDER2 = "android.provider.apps.cts.multi2";
     private static final String PROVIDER_NONEXISTENT = "android.provider.apps.cts.multi3";
 
-    private Context mContext;
-    private ActivityManager mAm;
     private ContentResolver mContentResolver;
 
     @Before
     public void setUp() {
-        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        mContentResolver = mContext.getContentResolver();
-        mAm = mContext.getSystemService(ActivityManager.class);
+        mContentResolver = InstrumentationRegistry.getInstrumentation()
+                            .getTargetContext().getContentResolver();
     }
 
-    @After
-    public void shutDown() {
+    @AfterClass
+    public static void shutDown() {
         killProviderProcess();
     }
 
-    private void killProviderProcess() {
-        SystemUtil.runWithShellPermissionIdentity(() -> {
-            mAm.forceStopPackage("android.provider.apps.cts.multiauthority");
-        });
+    private static void killProviderProcess() {
+        final ActivityManager am = InstrumentationRegistry.getInstrumentation()
+                                    .getTargetContext().getSystemService(ActivityManager.class);
+        SystemUtil.runWithShellPermissionIdentity(() ->
+                am.forceStopPackage("android.provider.apps.cts.multiauthority"));
     }
 
     @Test
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 2f5155a..9c603f8 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/sdksandbox/webkit/Android.bp b/tests/tests/sdksandbox/webkit/Android.bp
index 5eb4236..47af400 100644
--- a/tests/tests/sdksandbox/webkit/Android.bp
+++ b/tests/tests/sdksandbox/webkit/Android.bp
@@ -27,6 +27,7 @@
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
         "CtsSdkSandboxTestScenario",
+        "ctswebkitsharedenv",
     ],
     data: [
         ":EmptySdkProviderApp",
diff --git a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp
index d6f6b10..625d304 100644
--- a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp
+++ b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/Android.bp
@@ -28,6 +28,8 @@
         "CtsSdkSandboxTestRunner",
         "compatibility-device-util-axt",
         "ctsdeviceutillegacy-axt",
+        "ctswebkitsharedenv",
+        "CtsWebkitTestCasesSharedWithSdk",
     ],
     libs: [
         "android.test.base",
diff --git a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java
index 7a1c827..427a815 100644
--- a/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java
+++ b/tests/tests/sdksandbox/webkit/sdksidetests/WebViewSandboxTest/src/com/android/cts/sdksidetests/webviewsandboxtest/WebViewSandboxTestSdk.java
@@ -16,33 +16,41 @@
 
 package com.android.cts.sdksidetests.webviewsandboxtest;
 
-
-import static com.google.common.truth.Truth.assertThat;
-
 import android.app.sdksandbox.testutils.testscenario.SdkSandboxTestScenarioRunner;
 import android.content.Context;
 import android.os.Bundle;
 import android.view.View;
 import android.webkit.WebView;
-
-import org.junit.Test;
-
+import android.webkit.cts.IHostAppInvoker;
+import android.webkit.cts.SharedWebViewTestEnvironment;
+import android.webkit.cts.WebViewOnUiThread;
+import android.webkit.cts.WebViewTest;
 
 public class WebViewSandboxTestSdk extends SdkSandboxTestScenarioRunner {
+    private WebViewTest mTestInstance = new WebViewTest();
     private WebView mWebView;
+    private WebViewOnUiThread mOnUiThread;
+
+    @Override
+    public Object getTestInstance() {
+        return mTestInstance;
+    }
 
     @Override
     public View beforeEachTest(Context windowContext, Bundle params, int width, int height) {
         mWebView = new WebView(windowContext);
+        mOnUiThread = new WebViewOnUiThread(mWebView);
+
+        SharedWebViewTestEnvironment testEnvironment =
+                new SharedWebViewTestEnvironment.Builder()
+                        .setContext(getContext())
+                        .setWebView(mWebView)
+                        .setWebViewOnUiThread(mOnUiThread)
+                        .setHostAppInvoker(IHostAppInvoker.Stub.asInterface(getCustomInterface()))
+                        .build();
+
+        mTestInstance.setTestEnvironment(testEnvironment);
+
         return mWebView;
     }
-
-    @Test
-    public void testScrollBarOverlay() {
-        mWebView.setHorizontalScrollbarOverlay(true);
-        mWebView.setVerticalScrollbarOverlay(false);
-
-        assertThat(mWebView.overlayHorizontalScrollbar()).isTrue();
-        assertThat(mWebView.overlayVerticalScrollbar()).isFalse();
-    }
 }
diff --git a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java
index 98295b7..a960cce 100755
--- a/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java
+++ b/tests/tests/sdksandbox/webkit/src/android/sdksandbox/webkit/cts/WebViewSandboxTest.java
@@ -16,10 +16,14 @@
 
 package android.sdksandbox.webkit.cts;
 
+import static android.app.sdksandbox.testutils.testscenario.SdkSandboxScenarioRule.ENABLE_LIFE_CYCLE_ANNOTATIONS;
+
 import android.app.sdksandbox.testutils.testscenario.KeepSdkSandboxAliveRule;
 import android.app.sdksandbox.testutils.testscenario.SdkSandboxScenarioRule;
+import android.webkit.cts.SharedWebViewTestEnvironment;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
 
 import org.junit.ClassRule;
 import org.junit.Rule;
@@ -30,15 +34,25 @@
 public class WebViewSandboxTest {
 
     @ClassRule
-    public static final KeepSdkSandboxAliveRule sSdkTestSuiteSetup = new KeepSdkSandboxAliveRule(
-            "com.android.emptysdkprovider");
+    public static final KeepSdkSandboxAliveRule sSdkTestSuiteSetup =
+            new KeepSdkSandboxAliveRule("com.android.emptysdkprovider");
 
     @Rule
-    public final SdkSandboxScenarioRule sdkTester = new SdkSandboxScenarioRule(
-            "com.android.cts.sdksidetests.webviewsandboxtest");
+    public final SdkSandboxScenarioRule sdkTester =
+            new SdkSandboxScenarioRule(
+                    "com.android.cts.sdksidetests.webviewsandboxtest",
+                    SharedWebViewTestEnvironment.createHostAppInvoker(),
+                    ENABLE_LIFE_CYCLE_ANNOTATIONS);
 
     @Test
+    @MediumTest
     public void testScrollBarOverlay() throws Exception {
         sdkTester.assertSdkTestRunPasses("testScrollBarOverlay");
     }
+
+    @Test
+    @MediumTest
+    public void testFlingScroll() throws Exception {
+        sdkTester.assertSdkTestRunPasses("testFlingScroll");
+    }
 }
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 9f4cda5..56d02d2 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -91,7 +91,8 @@
         ":CtsPermissionBackupAppCert34",
         ":CtsPermissionBackupAppCert123",
         ":CtsPermissionBackupAppCert4History124",
-     ],
+        ":CtsAppThatRequestCustomCameraPermission",
+    ],
 }
 
 android_test_helper_app {
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 73e6bc7..6a6dc92 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -62,6 +62,7 @@
         <option name="push" value="CtsPermissionBackupAppCert123.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert123.apk" />
         <option name="push" value="CtsPermissionBackupAppCert34.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert34.apk" />
         <option name="push" value="CtsPermissionBackupAppCert4History124.apk->/data/local/tmp/cts/security/CtsPermissionBackupAppCert4History124.apk" />
+        <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/Android.bp b/tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp
similarity index 100%
rename from tests/tests/permission/AppThatRequestCustomCameraPermission/Android.bp
rename to tests/tests/security/AppThatRequestCustomCameraPermission/Android.bp
diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml b/tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml
similarity index 100%
rename from tests/tests/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml
rename to tests/tests/security/AppThatRequestCustomCameraPermission/AndroidManifest.xml
diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml b/tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml
similarity index 100%
rename from tests/tests/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml
rename to tests/tests/security/AppThatRequestCustomCameraPermission/res/values/strings.xml
diff --git a/tests/tests/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java b/tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
similarity index 100%
rename from tests/tests/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
rename to tests/tests/security/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
diff --git a/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt b/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt
index b449451..201df17 100644
--- a/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt
+++ b/tests/tests/security/src/android/security/cts/BasePermissionUiTest.kt
@@ -263,7 +263,9 @@
     private fun startActivityForFuture(
         intent: Intent
     ): CompletableFuture<Instrumentation.ActivityResult> =
-        activityRule.launchActivity(null).startActivityForFuture(intent)
+        CompletableFuture<Instrumentation.ActivityResult>().also {
+            activityRule.launchActivity(null).startActivityForFuture(intent, it)
+        }
 
     protected fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) {
         assertEquals(
@@ -301,4 +303,4 @@
             click(By.res(ALLOW_BUTTON), timeoutMillis)
         }
     }
-}
\ No newline at end of file
+}
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/MediaSessionTest.java b/tests/tests/security/src/android/security/cts/MediaSessionTest.java
new file mode 100644
index 0000000..d74179e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MediaSessionTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.assertThrows;
+
+import android.content.ComponentName;
+import android.content.ContextWrapper;
+import android.media.session.MediaSession;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class MediaSessionTest extends StsExtraBusinessLogicTestCase {
+    private static final String TAG = "MediaSessionTest";
+
+    private static final String TEST_SESSION_TAG_FOREIGN_PACKAGE =
+            "test-session-tag-foreign-package";
+    private static final String TEST_FOREIGN_PACKAGE_NAME = "fakepackage";
+    private static final String TEST_FOREIGN_PACKAGE_CLASS = "com.fakepackage.media.FakeReceiver";
+
+    @Test
+    @AsbSecurityTest(cveBugId = 238177121)
+    public void setMediaButtonBroadcastReceiver_withForeignPackageName_fails() throws Exception {
+        // Create Media Session
+        MediaSession mediaSession = new MediaSession(new ContextWrapper(getContext()) {
+                    @Override
+                    public String getPackageName() {
+                        return TEST_FOREIGN_PACKAGE_NAME;
+                    }
+                }, TEST_SESSION_TAG_FOREIGN_PACKAGE);
+
+        assertThrows("Component name with different package name was registered.",
+                IllegalArgumentException.class,
+                () -> mediaSession.setMediaButtonBroadcastReceiver(
+                        new ComponentName(TEST_FOREIGN_PACKAGE_NAME, TEST_FOREIGN_PACKAGE_CLASS)));
+
+        mediaSession.release();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java
new file mode 100644
index 0000000..eafef73
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/OneTimePermissionTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.Manifest.permission.CAMERA;
+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 android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.provider.DeviceConfig;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.UiAutomatorUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class OneTimePermissionTest {
+
+    private static final String CUSTOM_CAMERA_PERM_APP_PKG_NAME =
+            "android.permission.cts.appthatrequestcustomcamerapermission";
+    private static final String CUSTOM_CAMERA_PERM_APK =
+            "/data/local/tmp/cts/permissions/CtsAppThatRequestCustomCameraPermission.apk";
+
+    public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+
+    private static final long ONE_TIME_TIMEOUT_MILLIS = 5000;
+    private static final long ONE_TIME_KILLED_DELAY_MILLIS = 5000;
+
+    private final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+    private String mOldOneTimePermissionTimeoutValue;
+    private String mOldOneTimePermissionKilledDelayValue;
+
+    @Before
+    public void wakeUpScreen() {
+        SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+
+        SystemUtil.runShellCommand("input keyevent 82");
+    }
+
+    @Before
+    public void installApp() {
+        runShellCommand("pm install -r " + CUSTOM_CAMERA_PERM_APK);
+    }
+
+    @Before
+    public void prepareDeviceForOneTime() {
+        runWithShellPermissionIdentity(() -> {
+            mOldOneTimePermissionTimeoutValue = DeviceConfig.getProperty("permissions",
+                    "one_time_permissions_timeout_millis");
+            mOldOneTimePermissionKilledDelayValue = DeviceConfig.getProperty("permissions",
+                    "one_time_permissions_killed_delay_millis");
+            DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+                    Long.toString(ONE_TIME_TIMEOUT_MILLIS), false);
+            DeviceConfig.setProperty("permissions",
+                    "one_time_permissions_killed_delay_millis",
+                    Long.toString(ONE_TIME_KILLED_DELAY_MILLIS), false);
+        });
+    }
+
+    @After
+    public void uninstallApp() {
+        runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME);
+    }
+
+    @After
+    public void restoreDeviceForOneTime() {
+        runWithShellPermissionIdentity(
+                () -> {
+                    DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+                            mOldOneTimePermissionTimeoutValue, false);
+                    DeviceConfig.setProperty("permissions",
+                            "one_time_permissions_killed_delay_millis",
+                            mOldOneTimePermissionKilledDelayValue, false);
+                });
+    }
+
+    @Test
+    @AsbSecurityTest(cveBugId = 237405974L)
+    public void testCustomPermissionIsGrantedOneTime() throws Throwable {
+        Intent startApp = new Intent()
+                .setComponent(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME,
+                        CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission"))
+                .addFlags(FLAG_ACTIVITY_NEW_TASK);
+
+        mContext.startActivity(startApp);
+
+        // We're only manually granting CAMERA, but the app will later request CUSTOM and get it
+        // granted silently. This is intentional since it's in the same group but both should
+        // eventually be revoked
+        clickOneTimeButton();
+
+        // Just waiting for the revocation
+        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+                mContext.getPackageManager()
+                        .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+        // This checks the vulnerability
+        eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+                mContext.getPackageManager()
+                        .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+    }
+
+    private void clickOneTimeButton() throws Throwable {
+        final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(By.res(
+                "com.android.permissioncontroller:id/permission_allow_one_time_button"), 10000);
+        Thread.sleep(500);
+        uiObject.click();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt b/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt
index ed2c8e8..d5c535d 100644
--- a/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt
+++ b/tests/tests/security/src/android/security/cts/StartForFutureActivity.kt
@@ -22,17 +22,22 @@
 import java.util.concurrent.CompletableFuture
 
 class StartForFutureActivity : Activity() {
-    private val future = CompletableFuture<Instrumentation.ActivityResult>()
-
-    fun startActivityForFuture(intent: Intent): CompletableFuture<Instrumentation.ActivityResult> {
+    fun startActivityForFuture(
+        intent: Intent,
+        future: CompletableFuture<Instrumentation.ActivityResult>
+    ) {
         startActivityForResult(intent, 1)
-        return future
+        StartForFutureActivity.future = future
     }
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
-
-        future.complete(Instrumentation.ActivityResult(resultCode, data))
+        future!!.complete(Instrumentation.ActivityResult(resultCode, data))
+        future = null
         finish()
     }
-}
\ No newline at end of file
+
+    companion object {
+        private var future: CompletableFuture<Instrumentation.ActivityResult>? = null
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
index 12574e2..226cc80 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
@@ -16,7 +16,8 @@
 
 package android.telecom.cts;
 
-import static android.telecom.cts.TestUtils.*;
+import static android.telecom.cts.TestUtils.InvokeCounter;
+import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
 
 import android.os.Bundle;
 import android.os.Handler;
@@ -29,7 +30,6 @@
 import android.telecom.RemoteConference;
 import android.telecom.RemoteConnection;
 import android.telecom.TelecomManager;
-import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -59,6 +59,13 @@
     MockConference mConference, mRemoteConference;
     RemoteConference mRemoteConferenceObject;
 
+    @Override
+    public void tearDown() throws Exception {
+        mRemoteConference.destroy();
+        mConference.destroy();
+        super.tearDown();
+    }
+
     public void testRemoteConferenceCreate() {
         if (!mShouldTestTelecom) {
             return;
diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionServiceTest.java
index c890889..60b03b7 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.provider.CallLog;
@@ -35,14 +45,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.function.Predicate;
 
-import static android.media.AudioManager.MODE_IN_COMMUNICATION;
-import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_1;
-import static android.telecom.cts.TestUtils.TEST_SELF_MANAGED_HANDLE_4;
-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;
-
 /**
  * CTS tests for the self-managed {@link android.telecom.ConnectionService} APIs.
  * For more information about these APIs, see {@link android.telecom}, and
@@ -123,6 +125,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/webkit/Android.bp b/tests/tests/webkit/Android.bp
index a046dae..0b206ff 100644
--- a/tests/tests/webkit/Android.bp
+++ b/tests/tests/webkit/Android.bp
@@ -16,9 +16,11 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
-    name: "CtsWebkitTestCases",
+android_library {
+    name: "CtsWebkitTestCasesSharedWithSdk",
     defaults: ["cts_defaults"],
+    manifest: "shared/AndroidManifest.xml",
+    resource_dirs: ["shared/res"],
     libs: [
         "android.test.runner",
         "org.apache.http.legacy",
@@ -31,11 +33,24 @@
         "ctstestserver",
         "ctstestrunner-axt",
         "hamcrest-library",
+        "ctswebkitsharedenv",
     ],
     srcs: [
         "src/**/*.java",
         "src/**/*.aidl",
     ],
+    // uncomment when dalvik.annotation.Test* are removed or part of SDK
+    //sdk_version: "current"
+    platform_apis: true,
+}
+
+android_test {
+    name: "CtsWebkitTestCases",
+    defaults: ["cts_defaults"],
+    resource_dirs: ["res"],
+    static_libs: [
+        "CtsWebkitTestCasesSharedWithSdk",
+    ],
     // Tag this module as a cts test artifact
     test_suites: [
         "cts",
diff --git a/tests/uwb/AndroidManifest.xml b/tests/tests/webkit/shared/AndroidManifest.xml
similarity index 66%
rename from tests/uwb/AndroidManifest.xml
rename to tests/tests/webkit/shared/AndroidManifest.xml
index adecade..fc3e5cd 100644
--- a/tests/uwb/AndroidManifest.xml
+++ b/tests/tests/webkit/shared/AndroidManifest.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- * 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.
@@ -16,13 +16,5 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.uwb.cts">
-
-    <!--  self-instrumenting test package. -->
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:label="CTS tests for android.uwb"
-        android:targetPackage="android.uwb.cts" >
-    </instrumentation>
+     package="android.webkit.cts">
 </manifest>
-
diff --git a/tests/tests/webkit/shared/README.md b/tests/tests/webkit/shared/README.md
new file mode 100644
index 0000000..73054f4
--- /dev/null
+++ b/tests/tests/webkit/shared/README.md
@@ -0,0 +1,7 @@
+# Shared with SDK resources
+
+This directory contains any resources that
+should be shared with the WebView SDK Runtime tests.
+
+It also contains the AndroidManifest.xml that will be used
+to create a shared library.
\ No newline at end of file
diff --git a/tests/tests/webkit/res/layout/webview_layout.xml b/tests/tests/webkit/shared/res/layout/webview_layout.xml
similarity index 100%
rename from tests/tests/webkit/res/layout/webview_layout.xml
rename to tests/tests/webkit/shared/res/layout/webview_layout.xml
diff --git a/tests/tests/webkit/res/raw/trustedcert.crt b/tests/tests/webkit/shared/res/raw/trustedcert.crt
similarity index 100%
rename from tests/tests/webkit/res/raw/trustedcert.crt
rename to tests/tests/webkit/shared/res/raw/trustedcert.crt
diff --git a/tests/tests/webkit/res/raw/trustedkey.der b/tests/tests/webkit/shared/res/raw/trustedkey.der
similarity index 100%
rename from tests/tests/webkit/res/raw/trustedkey.der
rename to tests/tests/webkit/shared/res/raw/trustedkey.der
Binary files differ
diff --git a/tests/tests/webkit/res/raw/untrustedcert.crt b/tests/tests/webkit/shared/res/raw/untrustedcert.crt
similarity index 100%
rename from tests/tests/webkit/res/raw/untrustedcert.crt
rename to tests/tests/webkit/shared/res/raw/untrustedcert.crt
diff --git a/tests/tests/webkit/res/raw/untrustedkey.der b/tests/tests/webkit/shared/res/raw/untrustedkey.der
similarity index 100%
rename from tests/tests/webkit/res/raw/untrustedkey.der
rename to tests/tests/webkit/shared/res/raw/untrustedkey.der
Binary files differ
diff --git a/tests/tests/webkit/res/xml/network_security_config.xml b/tests/tests/webkit/shared/res/xml/network_security_config.xml
similarity index 100%
rename from tests/tests/webkit/res/xml/network_security_config.xml
rename to tests/tests/webkit/shared/res/xml/network_security_config.xml
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 7ca3f46..056cce9 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -78,7 +78,6 @@
 import android.widget.LinearLayout;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.core.app.ActivityScenario;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -123,7 +122,7 @@
 
 @AppModeFull
 @RunWith(AndroidJUnit4.class)
-public class WebViewTest {
+public class WebViewTest extends SharedWebViewTest {
     private static final int INITIAL_PROGRESS = 100;
     private static final String X_REQUESTED_WITH = "X-Requested-With";
     private static final String PRINTER_TEST_FILE = "print.pdf";
@@ -156,36 +155,19 @@
     public ActivityScenarioRule mActivityScenarioRule =
             new ActivityScenarioRule(WebViewCtsActivity.class);
 
-    private ActivityScenario mScenario;
-    private WebViewCtsActivity mActivity;
     private WebView mWebView;
-    private CtsTestServer mWebServer;
     private WebViewOnUiThread mOnUiThread;
+
+    // TODO(bewise): Get rid of all of these member variables
+    // once all these tests are referencing the test environment.
+    private WebViewCtsActivity mActivity;
+    private CtsTestServer mWebServer;
     private WebIconDatabase mIconDb;
 
     @Before
     public void setUp() throws Exception {
-        mScenario = mActivityScenarioRule.getScenario();
-        mScenario.onActivity(
-                activity -> {
-                    mActivity = (WebViewCtsActivity) activity;
-                    mWebView = mActivity.getWebView();
-                });
-        if (mWebView != null) {
-            new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
-                @Override
-                protected boolean check() {
-                    return mActivity.hasWindowFocus();
-                }
-            }.run();
-            File f = mActivity.getFileStreamPath("snapshot");
-            if (f.exists()) {
-                f.delete();
-            }
-
-            mOnUiThread = new WebViewOnUiThread(mWebView);
-        }
-        Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
+        mWebView = getTestEnvironment().getWebView();
+        mOnUiThread = getTestEnvironment().getWebViewOnUiThread();
     }
 
     @After
@@ -204,6 +186,46 @@
         mActivity = null;
     }
 
+    @Override
+    protected SharedWebViewTestEnvironment createTestEnvironment() {
+        Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
+
+        SharedWebViewTestEnvironment.Builder builder = new SharedWebViewTestEnvironment.Builder()
+                .setHostAppInvoker(SharedWebViewTestEnvironment.createHostAppInvoker());
+
+        mActivityScenarioRule.getScenario().onActivity(activity -> {
+            mActivity = (WebViewCtsActivity) activity;
+            builder.setContext(mActivity);
+
+            WebView webView = mActivity.getWebView();
+            builder.setWebView(webView);
+
+            if (webView != null) {
+                WebViewOnUiThread onUi = new WebViewOnUiThread(webView);
+                builder.setWebViewOnUiThread(onUi);
+            }
+        });
+
+        SharedWebViewTestEnvironment environment = builder.build();
+
+        // Wait for window focus and clean up the snapshot before
+        // returning the test environment.
+        if (environment.getWebView() != null) {
+            new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+                @Override
+                protected boolean check() {
+                    return mActivity.hasWindowFocus();
+                }
+            }.run();
+            File f = mActivity.getFileStreamPath("snapshot");
+            if (f.exists()) {
+                f.delete();
+            }
+        }
+
+        return environment;
+    }
+
     private void startWebServer(boolean secure) throws Exception {
         assertNull(mWebServer);
         mWebServer = new CtsTestServer(mActivity, secure);
@@ -1704,7 +1726,8 @@
                 return mOnUiThread.getContentHeight() >= dimension;
             }
         }.run();
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        getTestEnvironment().waitForIdleSync();
 
         final int previousScrollX = mOnUiThread.getScrollX();
         final int previousScrollY = mOnUiThread.getScrollY();
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
index 279e242..0107119 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiBackupRestoreTest.java
@@ -27,6 +27,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.app.UiAutomation;
+import android.app.compat.CompatChanges;
 import android.content.Context;
 import android.net.IpConfiguration;
 import android.net.LinkAddress;
@@ -91,6 +92,7 @@
     public static final int EXPECTED_LEGACY_STATIC_PROXY_PORT = 8000;
     public static final String EXPECTED_LEGACY_STATIC_PROXY_EXCLUSION_LIST = "";
     public static final String EXPECTED_LEGACY_PAC_PROXY_LOCATION = "http://";
+    private static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L;
 
     private Context mContext;
     private WifiManager mWifiManager;
@@ -201,12 +203,10 @@
                 Log.e(TAG, "Need a non-enterprise and non-Passpoint network created by an app "
                         + "holding OVERRIDE_WIFI_CONFIG permission to fully evaluate the "
                         + "functionality");
-            }
+            } else {
 
-            // Retrieve backup data.
-            byte[] backupData = mWifiManager.retrieveBackupData();
-
-            if (origNetwork != null) {
+                // Retrieve backup data.
+                byte[] backupData = mWifiManager.retrieveBackupData();
                 // Modify the metered bit.
                 final String origNetworkSsid = origNetwork.SSID;
                 WifiConfiguration modNetwork = new WifiConfiguration(origNetwork);
@@ -219,19 +219,26 @@
                         .findAny()
                         .get().meteredOverride)
                         .isNotEqualTo(origNetwork.meteredOverride);
-            }
 
-            // Restore the original backup data & ensure that the metered bit is back to orig.
-            mWifiManager.restoreBackupData(backupData);
+                // Restore the original backup data & ensure that the metered bit is back to orig.
+                mWifiManager.restoreBackupData(backupData);
 
-            if (origNetwork != null) {
-                final String origNetworkSsid = origNetwork.SSID;
-                assertThat(mWifiManager.getConfiguredNetworks()
-                        .stream()
-                        .filter(n -> n.SSID.equals(origNetworkSsid))
-                        .findAny()
-                        .get().meteredOverride)
-                        .isEqualTo(origNetwork.meteredOverride);
+                if (CompatChanges.isChangeEnabled(NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE)) {
+                    assertThat(mWifiManager.getConfiguredNetworks()
+                            .stream()
+                            .filter(n -> n.SSID.equals(origNetworkSsid))
+                            .findAny()
+                            .get().meteredOverride)
+                            .isNotEqualTo(origNetwork.meteredOverride);
+
+                } else {
+                    assertThat(mWifiManager.getConfiguredNetworks()
+                            .stream()
+                            .filter(n -> n.SSID.equals(origNetworkSsid))
+                            .findAny()
+                            .get().meteredOverride)
+                            .isEqualTo(origNetwork.meteredOverride);
+                }
             }
         } finally {
             // Restore the orig network
diff --git a/tests/uwb/Android.bp b/tests/uwb/Android.bp
deleted file mode 100644
index 55e7ba6..0000000
--- a/tests/uwb/Android.bp
+++ /dev/null
@@ -1,43 +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 {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test {
-    name: "CtsUwbTestCases",
-    defaults: [
-        "cts_defaults",
-        "framework-uwb-cts-defaults",
-    ],
-    // Tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "general-tests",
-        "mts-uwb",
-    ],
-    libs: ["android.test.runner"],
-    static_libs: [
-        "androidx.test.ext.junit",
-        "ctstestrunner-axt",
-        "compatibility-device-util-axt",
-        "mockito-target-minus-junit4",
-        "com.uwb.support.fira",
-        "com.uwb.support.multichip",
-        "com.uwb.support.oemextension",
-    ],
-    srcs: ["src/**/*.java"],
-    platform_apis: true,
-}
diff --git a/tests/uwb/AndroidTest.xml b/tests/uwb/AndroidTest.xml
deleted file mode 100644
index 3104ec5..0000000
--- a/tests/uwb/AndroidTest.xml
+++ /dev/null
@@ -1,33 +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.
--->
-<configuration description="Config for CTS UWB 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="instant_app" />
-    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
-    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
-    <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.uwb.apex" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsUwbTestCases.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.uwb.cts" />
-    </test>
-    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
-        <option name="mainline-module-package-name" value="com.google.android.uwb" />
-    </object>
-</configuration>
diff --git a/tests/uwb/OWNERS b/tests/uwb/OWNERS
deleted file mode 100644
index c4ad416..0000000
--- a/tests/uwb/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 1042770
-include platform/packages/modules/Uwb:/OWNERS
diff --git a/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java b/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java
deleted file mode 100644
index f96b798..0000000
--- a/tests/uwb/src/android/uwb/cts/AngleMeasurementTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.uwb.AngleMeasurement;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link AngleMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AngleMeasurementTest {
-    @Test
-    public void testConstructs() {
-        double radians = 0.1234;
-        double errorRadians = 0.5678;
-        double confidence = 0.5;
-
-        AngleMeasurement measurement = new AngleMeasurement(radians, errorRadians, confidence);
-        assertEquals(measurement.getRadians(), radians, 0);
-        assertEquals(measurement.getErrorRadians(), errorRadians, 0);
-        assertEquals(measurement.getConfidenceLevel(), confidence, 0);
-    }
-
-    @Test
-    public void testInvalidRadians() {
-        double radians = Math.PI + 0.01;
-        double errorRadians = 0.5678;
-        double confidence = 0.5;
-
-        constructExpectFailure(radians, errorRadians, confidence);
-        constructExpectFailure(-radians, errorRadians, confidence);
-    }
-
-    @Test
-    public void testInvalidErrorRadians() {
-        double radians = 0.1234;
-        double confidence = 0.5;
-
-        constructExpectFailure(radians, -0.01, confidence);
-        constructExpectFailure(-radians, Math.PI + 0.01, confidence);
-    }
-
-    @Test
-    public void testInvalidConfidence() {
-        double radians = 0.1234;
-        double errorRadians = 0.5678;
-
-        constructExpectFailure(radians, errorRadians, -0.01);
-        constructExpectFailure(radians, errorRadians, 1.01);
-    }
-
-    private void constructExpectFailure(double radians, double errorRadians, double confidence) {
-        try {
-            new AngleMeasurement(radians, errorRadians, confidence);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        AngleMeasurement measurement = UwbTestUtils.getAngleMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AngleMeasurement fromParcel = AngleMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java b/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java
deleted file mode 100644
index 085ce2e..0000000
--- a/tests/uwb/src/android/uwb/cts/AngleOfArrivalMeasurementTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.uwb.AngleMeasurement;
-import android.uwb.AngleOfArrivalMeasurement;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link AngleOfArrivalMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AngleOfArrivalMeasurementTest {
-
-    @Test
-    public void testBuilder() {
-        AngleMeasurement azimuth = UwbTestUtils.getAngleMeasurement();
-        AngleMeasurement altitude = UwbTestUtils.getAngleMeasurement();
-
-        AngleOfArrivalMeasurement.Builder builder = new AngleOfArrivalMeasurement.Builder(azimuth);
-        builder.setAltitude(altitude);
-
-        AngleOfArrivalMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(azimuth, measurement.getAzimuth());
-        assertEquals(altitude, measurement.getAltitude());
-    }
-
-    private AngleOfArrivalMeasurement tryBuild(AngleOfArrivalMeasurement.Builder builder,
-            boolean expectSuccess) {
-        AngleOfArrivalMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected AngleOfArrivalMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected AngleOfArrivalMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        AngleOfArrivalMeasurement measurement = UwbTestUtils.getAngleOfArrivalMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        AngleOfArrivalMeasurement fromParcel =
-                AngleOfArrivalMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java b/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java
deleted file mode 100644
index fdebc78..0000000
--- a/tests/uwb/src/android/uwb/cts/DistanceMeasurementTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.uwb.DistanceMeasurement;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link DistanceMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class DistanceMeasurementTest {
-    private static final double EPSILON = 0.00000000001;
-
-    @Test
-    public void testBuilder() {
-        double meters = 0.12;
-        double error = 0.54;
-        double confidence = 0.99;
-
-        DistanceMeasurement.Builder builder = new DistanceMeasurement.Builder();
-        tryBuild(builder, false);
-
-        builder.setMeters(meters);
-        tryBuild(builder, false);
-
-        builder.setErrorMeters(error);
-        tryBuild(builder, false);
-
-        builder.setConfidenceLevel(confidence);
-        DistanceMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(meters, measurement.getMeters(), 0);
-        assertEquals(error, measurement.getErrorMeters(), 0);
-        assertEquals(confidence, measurement.getConfidenceLevel(), 0);
-    }
-
-    private DistanceMeasurement tryBuild(DistanceMeasurement.Builder builder,
-            boolean expectSuccess) {
-        DistanceMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        DistanceMeasurement measurement = UwbTestUtils.getDistanceMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        DistanceMeasurement fromParcel =
-                DistanceMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java b/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java
deleted file mode 100644
index bc5c2fd..0000000
--- a/tests/uwb/src/android/uwb/cts/RangingMeasurementTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.os.SystemClock;
-import android.uwb.AngleOfArrivalMeasurement;
-import android.uwb.DistanceMeasurement;
-import android.uwb.RangingMeasurement;
-import android.uwb.UwbAddress;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link RangingMeasurement}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingMeasurementTest {
-    private static final int TEST_RSSI_DBM = -80;
-    private static final int INVALID_RSSI_DBM = -129;
-
-    @Test
-    public void testBuilder() {
-        int status = RangingMeasurement.RANGING_STATUS_SUCCESS;
-        UwbAddress address = UwbTestUtils.getUwbAddress(false);
-        long time = SystemClock.elapsedRealtimeNanos();
-        AngleOfArrivalMeasurement angleMeasurement = UwbTestUtils.getAngleOfArrivalMeasurement();
-        AngleOfArrivalMeasurement destinationAngleMeasurement =
-                UwbTestUtils.getAngleOfArrivalMeasurement();
-        DistanceMeasurement distanceMeasurement = UwbTestUtils.getDistanceMeasurement();
-        int los = RangingMeasurement.NLOS;
-        int measurementFocus = RangingMeasurement.MEASUREMENT_FOCUS_RANGE;
-
-
-        RangingMeasurement.Builder builder = new RangingMeasurement.Builder();
-
-        builder.setStatus(status);
-        tryBuild(builder, false);
-
-        builder.setElapsedRealtimeNanos(time);
-        tryBuild(builder, false);
-
-        builder.setAngleOfArrivalMeasurement(angleMeasurement);
-        tryBuild(builder, false);
-
-        builder.setDestinationAngleOfArrivalMeasurement(destinationAngleMeasurement);
-        tryBuild(builder, false);
-
-        builder.setDistanceMeasurement(distanceMeasurement);
-        tryBuild(builder, false);
-
-        builder.setRssiDbm(TEST_RSSI_DBM);
-        tryBuild(builder, false);
-
-        builder.setRemoteDeviceAddress(address);
-        tryBuild(builder, true);
-
-        builder.setLineOfSight(los);
-        tryBuild(builder, true);
-
-        builder.setMeasurementFocus(measurementFocus);
-        RangingMeasurement measurement = tryBuild(builder, true);
-
-        assertEquals(status, measurement.getStatus());
-        assertEquals(address, measurement.getRemoteDeviceAddress());
-        assertEquals(time, measurement.getElapsedRealtimeNanos());
-        assertEquals(angleMeasurement, measurement.getAngleOfArrivalMeasurement());
-        assertEquals(destinationAngleMeasurement,
-                measurement.getDestinationAngleOfArrivalMeasurement());
-        assertEquals(distanceMeasurement, measurement.getDistanceMeasurement());
-        assertEquals(los, measurement.getLineOfSight());
-        assertEquals(measurementFocus, measurement.getMeasurementFocus());
-        assertEquals(TEST_RSSI_DBM, measurement.getRssiDbm());
-    }
-
-    @Test
-    public void testInvalidRssi() {
-        RangingMeasurement.Builder builder = new RangingMeasurement.Builder();
-        try {
-            builder.setRssiDbm(INVALID_RSSI_DBM);
-            fail("Expected RangingMeasurement.Builder.setRssiDbm() to fail");
-        } catch (Exception e) {
-            assertTrue(e.getMessage().contains("Invalid"));
-        }
-    }
-
-    private RangingMeasurement tryBuild(RangingMeasurement.Builder builder,
-            boolean expectSuccess) {
-        RangingMeasurement measurement = null;
-        try {
-            measurement = builder.build();
-            if (!expectSuccess) {
-                fail("Expected RangingMeasurement.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected DistanceMeasurement.Builder.build() to succeed");
-            }
-        }
-        return measurement;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        RangingMeasurement measurement = UwbTestUtils.getRangingMeasurement();
-        measurement.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        RangingMeasurement fromParcel = RangingMeasurement.CREATOR.createFromParcel(parcel);
-        assertEquals(measurement, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/RangingReportTest.java b/tests/uwb/src/android/uwb/cts/RangingReportTest.java
deleted file mode 100644
index b2524e7..0000000
--- a/tests/uwb/src/android/uwb/cts/RangingReportTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.os.Parcel;
-import android.uwb.RangingMeasurement;
-import android.uwb.RangingReport;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-/**
- * Test of {@link RangingReport}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class RangingReportTest {
-
-    @Test
-    public void testBuilder() {
-        List<RangingMeasurement> measurements = UwbTestUtils.getRangingMeasurements(5);
-
-        RangingReport.Builder builder = new RangingReport.Builder();
-        builder.addMeasurements(measurements);
-        RangingReport report = tryBuild(builder, true);
-        verifyMeasurementsEqual(measurements, report.getMeasurements());
-
-
-        builder = new RangingReport.Builder();
-        for (RangingMeasurement measurement : measurements) {
-            builder.addMeasurement(measurement);
-        }
-        report = tryBuild(builder, true);
-        verifyMeasurementsEqual(measurements, report.getMeasurements());
-    }
-
-    private void verifyMeasurementsEqual(List<RangingMeasurement> expected,
-            List<RangingMeasurement> actual) {
-        assertEquals(expected.size(), actual.size());
-        for (int i = 0; i < expected.size(); i++) {
-            assertEquals(expected.get(i), actual.get(i));
-        }
-    }
-
-    private RangingReport tryBuild(RangingReport.Builder builder,
-            boolean expectSuccess) {
-        RangingReport report = null;
-        try {
-            report = builder.build();
-            if (!expectSuccess) {
-                fail("Expected RangingReport.Builder.build() to fail");
-            }
-        } catch (IllegalStateException e) {
-            if (expectSuccess) {
-                fail("Expected RangingReport.Builder.build() to succeed");
-            }
-        }
-        return report;
-    }
-
-    @Test
-    public void testParcel() {
-        Parcel parcel = Parcel.obtain();
-        RangingReport report = UwbTestUtils.getRangingReports(5);
-        report.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        RangingReport fromParcel = RangingReport.CREATOR.createFromParcel(parcel);
-        assertEquals(report, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/UwbAddressTest.java b/tests/uwb/src/android/uwb/cts/UwbAddressTest.java
deleted file mode 100644
index d2f4228..0000000
--- a/tests/uwb/src/android/uwb/cts/UwbAddressTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-import android.uwb.UwbAddress;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test of {@link UwbAddress}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class UwbAddressTest {
-
-    @Test
-    public void testFromBytes_Short() {
-        runFromBytes(UwbAddress.SHORT_ADDRESS_BYTE_LENGTH);
-    }
-
-    @Test
-    public void testFromBytes_Extended() {
-        runFromBytes(UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH);
-    }
-
-    private void runFromBytes(int len) {
-        byte[] addressBytes = getByteArray(len);
-        UwbAddress address = UwbAddress.fromBytes(addressBytes);
-        assertEquals(address.size(), len);
-        assertEquals(addressBytes, address.toBytes());
-    }
-
-    private byte[] getByteArray(int len) {
-        byte[] res = new byte[len];
-        for (int i = 0; i < len; i++) {
-            res[i] = (byte) i;
-        }
-        return res;
-    }
-
-    @Test
-    public void testParcel_Short() {
-        runParcel(true);
-    }
-
-    @Test
-    public void testParcel_Extended() {
-        runParcel(false);
-    }
-
-    private void runParcel(boolean useShortAddress) {
-        Parcel parcel = Parcel.obtain();
-        UwbAddress address = UwbTestUtils.getUwbAddress(useShortAddress);
-        address.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        UwbAddress fromParcel = UwbAddress.CREATOR.createFromParcel(parcel);
-        assertEquals(address, fromParcel);
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java b/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java
deleted file mode 100644
index ddd22c6..0000000
--- a/tests/uwb/src/android/uwb/cts/UwbFrameworkInitializerTest.java
+++ /dev/null
@@ -1,68 +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.uwb.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import android.content.Context;
-import android.platform.test.annotations.AppModeFull;
-import android.uwb.UwbFrameworkInitializer;
-import android.uwb.UwbManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-/**
- * Test of {@link UwbManager}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-@AppModeFull(reason = "Cannot get UwbManager in instant app mode")
-public class UwbFrameworkInitializerTest {
-    private final Context mContext = InstrumentationRegistry.getContext();
-    private UwbManager mUwbManager;
-
-    @Before
-    public void setup() throws Exception {
-        mUwbManager = mContext.getSystemService(UwbManager.class);
-        assumeTrue(UwbTestUtils.isUwbSupported(mContext));
-        assertThat(mUwbManager).isNotNull();
-    }
-
-    /**
-     * UwbFrameworkInitializer.registerServiceWrappers() should only be called by
-     * SystemServiceRegistry during boot up when Uwb is first initialized. Calling this API at
-     * any other time should throw an exception.
-     */
-    @Test
-    public void testRegisterServiceWrappers_failsWhenCalledOutsideOfSystemServiceRegistry() {
-        try {
-            UwbFrameworkInitializer.registerServiceWrappers();
-            fail("Expected exception when calling "
-                    + "UwbFrameworkInitializer.registerServiceWrappers() outside of "
-                    + "SystemServiceRegistry!");
-        } catch (IllegalStateException expected) { }
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java b/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
deleted file mode 100644
index f10eb11..0000000
--- a/tests/uwb/src/android/uwb/cts/UwbManagerTest.java
+++ /dev/null
@@ -1,1350 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import static android.Manifest.permission.UWB_PRIVILEGED;
-import static android.Manifest.permission.UWB_RANGING;
-import static android.uwb.UwbManager.AdapterStateCallback.STATE_DISABLED;
-import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE;
-import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.UiAutomation;
-import android.content.AttributionSource;
-import android.content.Context;
-import android.content.ContextParams;
-import android.os.CancellationSignal;
-import android.os.PersistableBundle;
-import android.os.Process;
-import android.permission.PermissionManager;
-import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
-import android.uwb.RangingReport;
-import android.uwb.RangingSession;
-import android.uwb.UwbAddress;
-import android.uwb.UwbManager;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.ShellIdentityUtils;
-import com.android.modules.utils.build.SdkLevel;
-
-import com.google.uwb.support.fira.FiraControleeParams;
-import com.google.uwb.support.fira.FiraOpenSessionParams;
-import com.google.uwb.support.fira.FiraParams;
-import com.google.uwb.support.fira.FiraProtocolVersion;
-import com.google.uwb.support.fira.FiraSpecificationParams;
-import com.google.uwb.support.multichip.ChipInfoParams;
-import com.google.uwb.support.oemextension.DeviceStatus;
-import com.google.uwb.support.oemextension.RangingReportMetadata;
-import com.google.uwb.support.oemextension.SessionStatus;
-
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test of {@link UwbManager}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-@AppModeFull(reason = "Cannot get UwbManager in instant app mode")
-public class UwbManagerTest {
-    private static final String TAG = "UwbManagerTest";
-
-    private final Context mContext = InstrumentationRegistry.getContext();
-    private UwbManager mUwbManager;
-    private String mDefaultChipId;
-    public static final int UWB_SESSION_STATE_IDLE = 0x03;
-    public static final byte DEVICE_STATE_ACTIVE = 0x02;
-    public static final int REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS = 0x00;
-
-    @Before
-    public void setup() throws Exception {
-        mUwbManager = mContext.getSystemService(UwbManager.class);
-        assumeTrue(UwbTestUtils.isUwbSupported(mContext));
-        assertThat(mUwbManager).isNotNull();
-
-        // Ensure UWB is toggled on.
-        ShellIdentityUtils.invokeWithShellPermissions(() -> {
-            if (!mUwbManager.isUwbEnabled()) {
-                try {
-                    setUwbEnabledAndWaitForCompletion(true);
-                } catch (Exception e) {
-                    fail("Exception while processing UWB toggle " + e);
-                }
-            }
-            mDefaultChipId = mUwbManager.getDefaultChipId();
-        });
-    }
-
-    // Should be invoked with shell permissions.
-    private void setUwbEnabledAndWaitForCompletion(boolean enabled) throws Exception {
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        int adapterState = enabled ? STATE_ENABLED_INACTIVE : STATE_DISABLED;
-        AdapterStateCallback adapterStateCallback =
-                new AdapterStateCallback(countDownLatch, adapterState);
-        try {
-            mUwbManager.registerAdapterStateCallback(
-                    Executors.newSingleThreadExecutor(), adapterStateCallback);
-            mUwbManager.setUwbEnabled(enabled);
-            assertThat(countDownLatch.await(2, TimeUnit.SECONDS)).isTrue();
-            assertThat(mUwbManager.isUwbEnabled()).isEqualTo(enabled);
-            assertThat(adapterStateCallback.state).isEqualTo(adapterState);
-        } finally {
-            mUwbManager.unregisterAdapterStateCallback(adapterStateCallback);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetSpecificationInfo() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            PersistableBundle persistableBundle = mUwbManager.getSpecificationInfo();
-            assertThat(persistableBundle).isNotNull();
-            assertThat(persistableBundle.isEmpty()).isFalse();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetSpecificationInfoWithChipId() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            PersistableBundle persistableBundle =
-                    mUwbManager.getSpecificationInfo(mDefaultChipId);
-            assertThat(persistableBundle).isNotNull();
-            assertThat(persistableBundle.isEmpty()).isFalse();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetChipInfos() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            List<PersistableBundle> chipInfos = mUwbManager.getChipInfos();
-            assertThat(chipInfos).hasSize(1);
-            ChipInfoParams chipInfoParams = ChipInfoParams.fromBundle(chipInfos.get(0));
-            assertThat(chipInfoParams.getChipId()).isEqualTo(mDefaultChipId);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetSpecificationInfoWithInvalidChipId() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            assertThrows(IllegalArgumentException.class,
-                    () -> mUwbManager.getSpecificationInfo("invalidChipId"));
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetSpecificationInfoWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getSpecificationInfo();
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetSpecificationInfoWithChipIdWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getSpecificationInfo(mDefaultChipId);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testElapsedRealtimeResolutionNanos() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            assertThat(mUwbManager.elapsedRealtimeResolutionNanos() >= 0L).isTrue();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testElapsedRealtimeResolutionNanosWithChipId() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            assertThat(mUwbManager.elapsedRealtimeResolutionNanos(mDefaultChipId) >= 0L)
-                    .isTrue();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testElapsedRealtimeResolutionNanosWithInvalidChipId() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            assertThrows(IllegalArgumentException.class,
-                    () -> mUwbManager.elapsedRealtimeResolutionNanos("invalidChipId"));
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testElapsedRealtimeResolutionNanosWithoutUwbPrivileged() {
-        try {
-            mUwbManager.elapsedRealtimeResolutionNanos();
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testElapsedRealtimeResolutionNanosWithChipIdWithoutUwbPrivileged() {
-        try {
-            mUwbManager.elapsedRealtimeResolutionNanos(mDefaultChipId);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testAddServiceProfileWithoutUwbPrivileged() {
-        try {
-            mUwbManager.addServiceProfile(new PersistableBundle());
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testRemoveServiceProfileWithoutUwbPrivileged() {
-        try {
-            mUwbManager.removeServiceProfile(new PersistableBundle());
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetAllServiceProfilesWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getAllServiceProfiles();
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetAdfProvisioningAuthoritiesWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getAdfProvisioningAuthorities(new PersistableBundle());
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetAdfCertificateInfoWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getAdfCertificateInfo(new PersistableBundle());
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testGetChipInfosWithoutUwbPrivileged() {
-        try {
-            mUwbManager.getChipInfos();
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testSendVendorUciWithoutUwbPrivileged() {
-        try {
-            mUwbManager.sendVendorUciMessage(10, 0, new byte[0]);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    private class AdfProvisionStateCallback extends UwbManager.AdfProvisionStateCallback {
-        private final CountDownLatch mCountDownLatch;
-
-        public boolean onSuccessCalled;
-        public boolean onFailedCalled;
-
-        AdfProvisionStateCallback(@NonNull CountDownLatch countDownLatch) {
-            mCountDownLatch = countDownLatch;
-        }
-
-        @Override
-        public void onProfileAdfsProvisioned(@NonNull PersistableBundle params) {
-            onSuccessCalled = true;
-            mCountDownLatch.countDown();
-        }
-
-        @Override
-        public void onProfileAdfsProvisionFailed(int reason, @NonNull PersistableBundle params) {
-            onFailedCalled = true;
-            mCountDownLatch.countDown();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testProvisionProfileAdfByScriptWithoutUwbPrivileged() {
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        AdfProvisionStateCallback adfProvisionStateCallback =
-                new AdfProvisionStateCallback(countDownLatch);
-        try {
-            mUwbManager.provisionProfileAdfByScript(
-                    new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    adfProvisionStateCallback);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testRemoveProfileAdfWithoutUwbPrivileged() {
-        try {
-            mUwbManager.removeProfileAdf(new PersistableBundle());
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    private class UwbVendorUciCallback implements UwbManager.UwbVendorUciCallback {
-        private final CountDownLatch mRspCountDownLatch;
-        private final CountDownLatch mNtfCountDownLatch;
-
-        public int gid;
-        public int oid;
-        public byte[] payload;
-
-        UwbVendorUciCallback(
-                @NonNull CountDownLatch rspCountDownLatch,
-                @NonNull CountDownLatch ntfCountDownLatch) {
-            mRspCountDownLatch = rspCountDownLatch;
-            mNtfCountDownLatch = ntfCountDownLatch;
-        }
-
-        @Override
-        public void onVendorUciResponse(int gid, int oid, byte[] payload) {
-            this.gid = gid;
-            this.oid = oid;
-            this.payload = payload;
-            mRspCountDownLatch.countDown();
-        }
-
-        @Override
-        public void onVendorUciNotification(int gid, int oid, byte[] payload) {
-            this.gid = gid;
-            this.oid = oid;
-            this.payload = payload;
-            mNtfCountDownLatch.countDown();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testRegisterVendorUciCallbackWithoutUwbPrivileged() {
-        UwbManager.UwbVendorUciCallback cb =
-                new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1));
-        try {
-            mUwbManager.registerUwbVendorUciCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testUnregisterVendorUciCallbackWithoutUwbPrivileged() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        UwbManager.UwbVendorUciCallback cb =
-                new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1));
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.registerUwbVendorUciCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-        } catch (SecurityException e) {
-            /* pass */
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-        try {
-            mUwbManager.unregisterUwbVendorUciCallback(cb);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-        try {
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.unregisterUwbVendorUciCallback(cb);
-            /* pass */
-        } catch (SecurityException e) {
-            /* fail */
-            fail();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testInvalidCallbackUnregisterVendorUciCallback() {
-        UwbManager.UwbVendorUciCallback cb =
-                new UwbVendorUciCallback(new CountDownLatch(1), new CountDownLatch(1));
-        try {
-            mUwbManager.registerUwbVendorUciCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-        } catch (SecurityException e) {
-            /* registration failed */
-        }
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.unregisterUwbVendorUciCallback(cb);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    private class RangingSessionCallback implements RangingSession.Callback {
-        private CountDownLatch mCtrlCountDownLatch;
-        private CountDownLatch mResultCountDownLatch;
-
-        public boolean onOpenedCalled;
-        public boolean onOpenFailedCalled;
-        public boolean onStartedCalled;
-        public boolean onStartFailedCalled;
-        public boolean onReconfiguredCalled;
-        public boolean onReconfiguredFailedCalled;
-        public boolean onClosedCalled;
-        public RangingSession rangingSession;
-        public RangingReport rangingReport;
-
-        RangingSessionCallback(
-                @NonNull CountDownLatch ctrlCountDownLatch) {
-            this(ctrlCountDownLatch, null /* resultCountDownLaynch */);
-        }
-
-        RangingSessionCallback(
-                @NonNull CountDownLatch ctrlCountDownLatch,
-                @Nullable CountDownLatch resultCountDownLatch) {
-            mCtrlCountDownLatch = ctrlCountDownLatch;
-            mResultCountDownLatch = resultCountDownLatch;
-        }
-
-        public void replaceCtrlCountDownLatch(@NonNull CountDownLatch countDownLatch) {
-            mCtrlCountDownLatch = countDownLatch;
-        }
-
-        public void onOpened(@NonNull RangingSession session) {
-            onOpenedCalled = true;
-            rangingSession = session;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onOpenFailed(@Reason int reason, @NonNull PersistableBundle params) {
-            onOpenFailedCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onStarted(@NonNull PersistableBundle sessionInfo) {
-            onStartedCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onStartFailed(@Reason int reason, @NonNull PersistableBundle params) {
-            onStartFailedCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onReconfigured(@NonNull PersistableBundle params) {
-            onReconfiguredCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onReconfigureFailed(@Reason int reason, @NonNull PersistableBundle params) {
-            onReconfiguredFailedCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onStopped(@Reason int reason, @NonNull PersistableBundle parameters) { }
-
-        public void onStopFailed(@Reason int reason, @NonNull PersistableBundle params) { }
-
-        public void onClosed(@Reason int reason, @NonNull PersistableBundle parameters) {
-            onClosedCalled = true;
-            mCtrlCountDownLatch.countDown();
-        }
-
-        public void onReportReceived(@NonNull RangingReport rangingReport) {
-            if (mResultCountDownLatch != null) {
-                this.rangingReport = rangingReport;
-                mResultCountDownLatch.countDown();
-            }
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithInvalidChipId() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch);
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            // Try to start a ranging session with invalid params, should fail.
-            assertThrows(IllegalArgumentException.class, () -> mUwbManager.openRangingSession(
-                    new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    rangingSessionCallback,
-                    "invalidChipId"));
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithChipIdWithBadParams() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CancellationSignal cancellationSignal = null;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch);
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            // Try to start a ranging session with invalid params, should fail.
-            cancellationSignal = mUwbManager.openRangingSession(
-                    new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    rangingSessionCallback,
-                    mDefaultChipId);
-            // Wait for the on start failed callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onOpenedCalled).isFalse();
-            assertThat(rangingSessionCallback.onOpenFailedCalled).isTrue();
-        } finally {
-            if (cancellationSignal != null) {
-                cancellationSignal.cancel();
-            }
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithInvalidChipIdWithBadParams() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CancellationSignal cancellationSignal = null;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        RangingSessionCallback rangingSessionCallback = new RangingSessionCallback(countDownLatch);
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            // Try to start a ranging session with invalid params, should fail.
-            cancellationSignal = mUwbManager.openRangingSession(
-                    new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    rangingSessionCallback,
-                    mDefaultChipId);
-            // Wait for the on start failed callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onOpenedCalled).isFalse();
-            assertThat(rangingSessionCallback.onOpenFailedCalled).isTrue();
-        } finally {
-            if (cancellationSignal != null) {
-                cancellationSignal.cancel();
-            }
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Simulates the app holding UWB_RANGING permission, but not UWB_PRIVILEGED.
-     */
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithoutUwbPrivileged() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Only hold UWB_RANGING permission
-            uiAutomation.adoptShellPermissionIdentity(UWB_RANGING);
-            mUwbManager.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)));
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithChipIdWithoutUwbPrivileged() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Only hold UWB_RANGING permission
-            uiAutomation.adoptShellPermissionIdentity(UWB_RANGING);
-            mUwbManager.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)),
-                    mDefaultChipId);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    /**
-     * Simulates the app holding UWB_PRIVILEGED permission, but not UWB_RANGING.
-     */
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithoutUwbRanging() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity(UWB_PRIVILEGED);
-            mUwbManager.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)));
-            // should fail if the call was successful without UWB_RANGING permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testOpenRangingSessionWithChipIdWithoutUwbRanging() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity(UWB_PRIVILEGED);
-            mUwbManager.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)),
-                    mDefaultChipId);
-            // should fail if the call was successful without UWB_RANGING permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    private AttributionSource getShellAttributionSourceWithRenouncedPermissions(
-            @Nullable Set<String> renouncedPermissions) {
-        try {
-            AttributionSource shellAttributionSource =
-                    new AttributionSource.Builder(Process.SHELL_UID)
-                            .setPackageName("com.android.shell")
-                            .setRenouncedPermissions(renouncedPermissions)
-                            .build();
-            PermissionManager permissionManager =
-                    mContext.getSystemService(PermissionManager.class);
-            permissionManager.registerAttributionSource(shellAttributionSource);
-            return shellAttributionSource;
-        } catch (SecurityException e) {
-            fail("Failed to create shell attribution source" + e);
-            return null;
-        }
-    }
-
-    private Context createShellContextWithRenouncedPermissionsAndAttributionSource(
-            @Nullable Set<String> renouncedPermissions) {
-        return mContext.createContext(new ContextParams.Builder()
-                .setRenouncedPermissions(renouncedPermissions)
-                .setNextAttributionSource(
-                        getShellAttributionSourceWithRenouncedPermissions(renouncedPermissions))
-                .build());
-    }
-
-    /**
-     * Simulates the calling app holding UWB_PRIVILEGED permission and UWB_RANGING permission, but
-     * the proxied app not holding UWB_RANGING permission.
-     */
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
-    public void testOpenRangingSessionWithoutUwbRangingInNextAttributeSource() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Only hold UWB_PRIVILEGED permission
-            uiAutomation.adoptShellPermissionIdentity();
-            Context shellContextWithUwbRangingRenounced =
-                    createShellContextWithRenouncedPermissionsAndAttributionSource(
-                            Set.of(UWB_RANGING));
-            UwbManager uwbManagerWithUwbRangingRenounced =
-                    shellContextWithUwbRangingRenounced.getSystemService(UwbManager.class);
-            uwbManagerWithUwbRangingRenounced.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)));
-            // should fail if the call was successful without UWB_RANGING permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
-    public void testOpenRangingSessionWithChipIdWithoutUwbRangingInNextAttributeSource() {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Only hold UWB_PRIVILEGED permission
-            uiAutomation.adoptShellPermissionIdentity();
-            Context shellContextWithUwbRangingRenounced =
-                    createShellContextWithRenouncedPermissionsAndAttributionSource(
-                            Set.of(UWB_RANGING));
-            UwbManager uwbManagerWithUwbRangingRenounced =
-                    shellContextWithUwbRangingRenounced.getSystemService(UwbManager.class);
-            uwbManagerWithUwbRangingRenounced.openRangingSession(new PersistableBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    new RangingSessionCallback(new CountDownLatch(1)),
-                    mDefaultChipId);
-            // should fail if the call was successful without UWB_RANGING permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
-    public void testFiraRangingSession() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CancellationSignal cancellationSignal = null;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        CountDownLatch resultCountDownLatch = new CountDownLatch(1);
-        RangingSessionCallback rangingSessionCallback =
-                new RangingSessionCallback(countDownLatch, resultCountDownLatch);
-        FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder()
-                .setProtocolVersion(new FiraProtocolVersion(1, 1))
-                .setSessionId(1)
-                .setStsConfig(FiraParams.STS_CONFIG_STATIC)
-                .setVendorId(new byte[]{0x5, 0x6})
-                .setStaticStsIV(new byte[]{0x5, 0x6, 0x9, 0xa, 0x4, 0x6})
-                .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
-                .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
-                .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
-                .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6}))
-                .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6})))
-                .build();
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            // Try to start a ranging session with invalid params, should fail.
-            cancellationSignal = mUwbManager.openRangingSession(
-                    firaOpenSessionParams.toBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    rangingSessionCallback,
-                    mDefaultChipId);
-            // Wait for the on opened callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onOpenedCalled).isTrue();
-            assertThat(rangingSessionCallback.onOpenFailedCalled).isFalse();
-            assertThat(rangingSessionCallback.rangingSession).isNotNull();
-
-            countDownLatch = new CountDownLatch(1);
-            rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-            rangingSessionCallback.rangingSession.start(new PersistableBundle());
-            // Wait for the on started callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onStartedCalled).isTrue();
-            assertThat(rangingSessionCallback.onStartFailedCalled).isFalse();
-
-            // Wait for the on ranging report callback.
-            assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.rangingReport).isNotNull();
-
-            // Check the UWB state.
-            assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE);
-
-            // Stop ongoing session.
-            rangingSessionCallback.rangingSession.stop();
-        } finally {
-            if (cancellationSignal != null) {
-                countDownLatch = new CountDownLatch(1);
-                rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-
-                // Close session.
-                cancellationSignal.cancel();
-
-                // Wait for the on closed callback.
-                assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-                assertThat(rangingSessionCallback.onClosedCalled).isTrue();
-            }
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
-    public void testFiraRangingSessionWithProvisionedSTS() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        // Needs UWB_PRIVILEGED permission which is held by shell.
-        uiAutomation.adoptShellPermissionIdentity();
-        CancellationSignal cancellationSignal = null;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        CountDownLatch resultCountDownLatch = new CountDownLatch(1);
-        RangingSessionCallback rangingSessionCallback =
-                new RangingSessionCallback(countDownLatch, resultCountDownLatch);
-        PersistableBundle bundle = mUwbManager.getSpecificationInfo();
-        if (bundle.keySet().contains(FiraParams.PROTOCOL_NAME)) {
-            bundle = requireNonNull(bundle.getPersistableBundle(FiraParams.PROTOCOL_NAME));
-        }
-        FiraSpecificationParams params =
-                FiraSpecificationParams.fromBundle(bundle);
-        EnumSet<FiraParams.StsCapabilityFlag> stsCapabilities = EnumSet.of(
-                FiraParams.StsCapabilityFlag.HAS_STATIC_STS_SUPPORT,
-                FiraParams.StsCapabilityFlag.HAS_PROVISIONED_STS_SUPPORT);
-        assumeTrue(params.getStsCapabilities() == stsCapabilities);
-
-        FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder()
-                .setProtocolVersion(new FiraProtocolVersion(1, 1))
-                .setSessionId(1)
-                .setStsConfig(FiraParams.STS_CONFIG_PROVISIONED)
-                .setSessionKey(new byte[]{
-                    0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
-                    0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8
-                })
-                .setSubsessionKey(new byte[]{
-                    0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
-                    0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8
-                })
-                .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
-                .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
-                .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
-                .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6}))
-                .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6})))
-                .build();
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            cancellationSignal = mUwbManager.openRangingSession(
-                firaOpenSessionParams.toBundle(),
-                Executors.newSingleThreadExecutor(),
-                rangingSessionCallback,
-                mDefaultChipId);
-            // Wait for the on opened callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onOpenedCalled).isTrue();
-            assertThat(rangingSessionCallback.onOpenFailedCalled).isFalse();
-            assertThat(rangingSessionCallback.rangingSession).isNotNull();
-
-            countDownLatch = new CountDownLatch(1);
-            rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-            rangingSessionCallback.rangingSession.start(new PersistableBundle());
-            // Wait for the on started callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onStartedCalled).isTrue();
-            assertThat(rangingSessionCallback.onStartFailedCalled).isFalse();
-
-            countDownLatch = new CountDownLatch(1);
-            rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-            UwbAddress uwbAddress = UwbAddress.fromBytes(new byte[] {0x5, 5});
-            rangingSessionCallback.rangingSession.addControlee(
-                    new FiraControleeParams.Builder()
-                    .setAddressList(new UwbAddress[] {uwbAddress})
-                    .setSubSessionIdList(new int[] {1})
-                    .build().toBundle()
-            );
-            // Wait for the on reconfigured callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.onReconfiguredCalled).isTrue();
-            assertThat(rangingSessionCallback.onReconfiguredFailedCalled).isFalse();
-
-            // Wait for the on ranging report callback.
-            assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.rangingReport).isNotNull();
-
-            // Check the UWB state.
-            assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE);
-
-            // Stop ongoing session.
-            rangingSessionCallback.rangingSession.stop();
-        } finally {
-            if (cancellationSignal != null) {
-                countDownLatch = new CountDownLatch(1);
-                rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-
-                // Close session.
-                cancellationSignal.cancel();
-
-                // Wait for the on closed callback.
-                assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-                assertThat(rangingSessionCallback.onClosedCalled).isTrue();
-            }
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    private class AdapterStateCallback implements UwbManager.AdapterStateCallback {
-        private final CountDownLatch mCountDownLatch;
-        private final @State Integer mWaitForState;
-        public int state;
-        public int reason;
-
-        AdapterStateCallback(@NonNull CountDownLatch countDownLatch,
-                @Nullable @State Integer waitForState) {
-            mCountDownLatch = countDownLatch;
-            mWaitForState = waitForState;
-        }
-
-        public void onStateChanged(@State int state, @StateChangedReason int reason) {
-            this.state = state;
-            this.reason = reason;
-            if (mWaitForState != null) {
-                if (mWaitForState == state) {
-                    mCountDownLatch.countDown();
-                }
-            } else {
-                mCountDownLatch.countDown();
-            }
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-4"})
-    public void testUwbStateToggle() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        try {
-            // Needs UWB_PRIVILEGED permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            assertThat(mUwbManager.isUwbEnabled()).isTrue();
-            assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_INACTIVE);
-            // Toggle the state
-            setUwbEnabledAndWaitForCompletion(false);
-            assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_DISABLED);
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testSendVendorUciMessage() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CountDownLatch rspCountDownLatch = new CountDownLatch(1);
-        CountDownLatch ntfCountDownLatch = new CountDownLatch(1);
-        UwbVendorUciCallback cb =
-                new UwbVendorUciCallback(rspCountDownLatch, ntfCountDownLatch);
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.registerUwbVendorUciCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-
-            // Send random payload with a vendor gid.
-            byte[] payload = new byte[100];
-            new Random().nextBytes(payload);
-            int gid = 9;
-            int oid = 1;
-            mUwbManager.sendVendorUciMessage(gid, oid, payload);
-
-            // Wait for response.
-            assertThat(rspCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(cb.gid).isEqualTo(gid);
-            assertThat(cb.oid).isEqualTo(oid);
-            assertThat(cb.payload).isNotEmpty();
-        } catch (SecurityException e) {
-            /* pass */
-        } finally {
-            mUwbManager.unregisterUwbVendorUciCallback(cb);
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testSendVendorUciMessageWithFragmentedPackets() throws Exception {
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CountDownLatch rspCountDownLatch = new CountDownLatch(1);
-        CountDownLatch ntfCountDownLatch = new CountDownLatch(1);
-        UwbVendorUciCallback cb =
-                new UwbVendorUciCallback(rspCountDownLatch, ntfCountDownLatch);
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.registerUwbVendorUciCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-
-            // Send random payload > 255 bytes with a vendor gid.
-            byte[] payload = new byte[400];
-            new Random().nextBytes(payload);
-            int gid = 9;
-            int oid = 1;
-            mUwbManager.sendVendorUciMessage(gid, oid, payload);
-
-            // Wait for response.
-            assertThat(rspCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(cb.gid).isEqualTo(gid);
-            assertThat(cb.oid).isEqualTo(oid);
-            assertThat(cb.payload).isNotEmpty();
-        } catch (SecurityException e) {
-            /* pass */
-        } finally {
-            mUwbManager.unregisterUwbVendorUciCallback(cb);
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    private class UwbOemExtensionCallback implements UwbManager.UwbOemExtensionCallback {
-        public PersistableBundle mSessionChangeNtf;
-        public PersistableBundle mDeviceStatusNtf;
-        public PersistableBundle mSessionConfig;
-        public RangingReport mRangingReport;
-        public boolean onSessionConfigCompleteCalled = false;
-        public boolean onRangingReportReceivedCalled = false;
-        public boolean onSessionChangedCalled = false;
-        public boolean onDeviceStatusNtfCalled = false;
-
-        @Override
-        public void onSessionStatusNotificationReceived(
-                @NonNull PersistableBundle sessionStatusBundle) {
-            mSessionChangeNtf = sessionStatusBundle;
-            onSessionChangedCalled = true;
-        }
-
-        @Override
-        public void onDeviceStatusNotificationReceived(PersistableBundle deviceStatusBundle) {
-            mDeviceStatusNtf = deviceStatusBundle;
-            onDeviceStatusNtfCalled = true;
-        }
-
-        @NonNull
-        @Override
-        public int onSessionConfigurationComplete(@NonNull PersistableBundle openSessionBundle) {
-            mSessionConfig = openSessionBundle;
-            onSessionConfigCompleteCalled = true;
-            return 0;
-        }
-
-        @NonNull
-        @Override
-        public RangingReport onRangingReportReceived(
-                @NonNull RangingReport rangingReport) {
-            onRangingReportReceivedCalled = true;
-            mRangingReport = rangingReport;
-            return mRangingReport;
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2,C-1-5"})
-    public void testOemCallbackExtension() throws Exception {
-        Assume.assumeTrue(SdkLevel.isAtLeastU());
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        CancellationSignal cancellationSignal = null;
-        CountDownLatch countDownLatch = new CountDownLatch(1);
-        CountDownLatch resultCountDownLatch = new CountDownLatch(1);
-        UwbOemExtensionCallback uwbOemExtensionCallback = new UwbOemExtensionCallback();
-
-        int sessionId = 1;
-        RangingSessionCallback rangingSessionCallback =
-                new RangingSessionCallback(countDownLatch, resultCountDownLatch);
-        FiraOpenSessionParams firaOpenSessionParams = new FiraOpenSessionParams.Builder()
-                .setProtocolVersion(new FiraProtocolVersion(1, 1))
-                .setSessionId(sessionId)
-                .setStsConfig(FiraParams.STS_CONFIG_STATIC)
-                .setVendorId(new byte[]{0x5, 0x6})
-                .setStaticStsIV(new byte[]{0x5, 0x6, 0x9, 0xa, 0x4, 0x6})
-                .setDeviceType(FiraParams.RANGING_DEVICE_TYPE_CONTROLLER)
-                .setDeviceRole(FiraParams.RANGING_DEVICE_ROLE_INITIATOR)
-                .setMultiNodeMode(FiraParams.MULTI_NODE_MODE_UNICAST)
-                .setDeviceAddress(UwbAddress.fromBytes(new byte[] {0x5, 6}))
-                .setDestAddressList(List.of(UwbAddress.fromBytes(new byte[] {0x5, 6})))
-                .build();
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.registerUwbOemExtensionCallback(
-                    Executors.newSingleThreadExecutor(), uwbOemExtensionCallback);
-            // Try to start a ranging session with invalid params, should fail.
-            cancellationSignal = mUwbManager.openRangingSession(
-                    firaOpenSessionParams.toBundle(),
-                    Executors.newSingleThreadExecutor(),
-                    rangingSessionCallback,
-                    mDefaultChipId);
-            // Wait for the on opened callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(uwbOemExtensionCallback.onSessionConfigCompleteCalled).isTrue();
-            assertThat(uwbOemExtensionCallback.mSessionConfig).isNotNull();
-
-            FiraOpenSessionParams openSessionParamsBundle = FiraOpenSessionParams
-                    .fromBundle(uwbOemExtensionCallback.mSessionConfig);
-            assertEquals(openSessionParamsBundle.getSessionId(), sessionId);
-            assertEquals(openSessionParamsBundle.getStsConfig(), FiraParams.STS_CONFIG_STATIC);
-            assertEquals(openSessionParamsBundle.getDeviceType(),
-                    FiraParams.RANGING_DEVICE_TYPE_CONTROLLER);
-
-            assertThat(uwbOemExtensionCallback.onSessionChangedCalled).isTrue();
-            assertThat(uwbOemExtensionCallback.mSessionChangeNtf).isNotNull();
-
-            SessionStatus sessionStatusBundle = SessionStatus
-                    .fromBundle(uwbOemExtensionCallback.mSessionChangeNtf);
-            assertEquals(sessionStatusBundle.getSessionId(), sessionId);
-            assertEquals(sessionStatusBundle.getState(), UWB_SESSION_STATE_IDLE);
-            assertEquals(sessionStatusBundle.getReasonCode(),
-                    REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS);
-
-            countDownLatch = new CountDownLatch(1);
-            rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-            rangingSessionCallback.rangingSession.start(new PersistableBundle());
-            // Wait for the on started callback.
-            assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(uwbOemExtensionCallback.onSessionChangedCalled).isTrue();
-            assertThat(uwbOemExtensionCallback.mSessionChangeNtf).isNotNull();
-            assertThat(uwbOemExtensionCallback.onDeviceStatusNtfCalled).isTrue();
-            assertThat(uwbOemExtensionCallback.mDeviceStatusNtf).isNotNull();
-
-            DeviceStatus deviceStatusBundle = DeviceStatus
-                    .fromBundle(uwbOemExtensionCallback.mDeviceStatusNtf);
-            assertEquals(deviceStatusBundle.getDeviceState(), DEVICE_STATE_ACTIVE);
-
-            // Wait for the on ranging report callback.
-            assertThat(resultCountDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-            assertThat(rangingSessionCallback.rangingReport).isNotNull();
-            assertThat(uwbOemExtensionCallback.onRangingReportReceivedCalled).isTrue();
-            assertThat(uwbOemExtensionCallback.mRangingReport).isNotNull();
-            PersistableBundle reportMetadataBundle = uwbOemExtensionCallback
-                    .mRangingReport.getRangingReportMetadata();
-            RangingReportMetadata reportMetadata = RangingReportMetadata
-                    .fromBundle(reportMetadataBundle);
-            assertEquals(reportMetadata.getSessionId(), sessionId);
-            assertThat(reportMetadata.getRawNtfData()).isNotEmpty();
-
-            // Check the UWB state.
-            assertThat(mUwbManager.getAdapterState()).isEqualTo(STATE_ENABLED_ACTIVE);
-
-            // Stop ongoing session.
-            rangingSessionCallback.rangingSession.stop();
-        } finally {
-            if (cancellationSignal != null) {
-                countDownLatch = new CountDownLatch(1);
-                rangingSessionCallback.replaceCtrlCountDownLatch(countDownLatch);
-
-                // Close session.
-                cancellationSignal.cancel();
-
-                // Wait for the on closed callback.
-                assertThat(countDownLatch.await(1, TimeUnit.SECONDS)).isTrue();
-                assertThat(rangingSessionCallback.onClosedCalled).isTrue();
-            }
-            try {
-                mUwbManager.unregisterUwbOemExtensionCallback(uwbOemExtensionCallback);
-            } catch (SecurityException e) {
-                /* pass */
-                fail();
-            }
-            uiAutomation.dropShellPermissionIdentity();
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testRegisterUwbOemExtensionCallbackWithoutUwbPrivileged() {
-        Assume.assumeTrue(SdkLevel.isAtLeastU());
-        UwbManager.UwbOemExtensionCallback cb = new UwbOemExtensionCallback();
-        try {
-            mUwbManager.registerUwbOemExtensionCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-    }
-
-    @Test
-    @CddTest(requirements = {"7.3.13/C-1-1,C-1-2"})
-    public void testUnregisterUwbOemExtensionCallbackWithoutUwbPrivileged() {
-        Assume.assumeTrue(SdkLevel.isAtLeastU());
-        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
-        UwbManager.UwbOemExtensionCallback cb = new UwbOemExtensionCallback();
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.registerUwbOemExtensionCallback(
-                    Executors.newSingleThreadExecutor(), cb);
-        } catch (SecurityException e) {
-            /* fail */
-            fail();
-        } finally {
-            uiAutomation.dropShellPermissionIdentity();
-        }
-        try {
-            mUwbManager.unregisterUwbOemExtensionCallback(cb);
-            // should fail if the call was successful without UWB_PRIVILEGED permission.
-            fail();
-        } catch (SecurityException e) {
-            /* pass */
-            Log.i(TAG, "Failed with expected security exception: " + e);
-        }
-        try {
-            // Needs UWB_PRIVILEGED & UWB_RANGING permission which is held by shell.
-            uiAutomation.adoptShellPermissionIdentity();
-            mUwbManager.unregisterUwbOemExtensionCallback(cb);
-        } catch (SecurityException e) {
-            /* pass */
-            fail();
-        }
-    }
-}
diff --git a/tests/uwb/src/android/uwb/cts/UwbTestUtils.java b/tests/uwb/src/android/uwb/cts/UwbTestUtils.java
deleted file mode 100644
index a7689de..0000000
--- a/tests/uwb/src/android/uwb/cts/UwbTestUtils.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.
- */
-
-package android.uwb.cts;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.uwb.AngleMeasurement;
-import android.uwb.AngleOfArrivalMeasurement;
-import android.uwb.DistanceMeasurement;
-import android.uwb.RangingMeasurement;
-import android.uwb.RangingReport;
-import android.uwb.UwbAddress;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-public class UwbTestUtils {
-    private UwbTestUtils() {}
-
-    public static boolean isUwbSupported(Context context) {
-        PackageManager packageManager = context.getPackageManager();
-        return packageManager.hasSystemFeature(PackageManager.FEATURE_UWB);
-    }
-
-    public static AngleMeasurement getAngleMeasurement() {
-        return new AngleMeasurement(
-                getDoubleInRange(-Math.PI, Math.PI),
-                getDoubleInRange(0, Math.PI),
-                getDoubleInRange(0, 1));
-    }
-
-    public static AngleOfArrivalMeasurement getAngleOfArrivalMeasurement() {
-        return new AngleOfArrivalMeasurement.Builder(getAngleMeasurement())
-                .setAltitude(getAngleMeasurement())
-                .build();
-    }
-
-    public static DistanceMeasurement getDistanceMeasurement() {
-        return new DistanceMeasurement.Builder()
-                .setMeters(getDoubleInRange(0, 100))
-                .setErrorMeters(getDoubleInRange(0, 10))
-                .setConfidenceLevel(getDoubleInRange(0, 1))
-                .build();
-    }
-
-    public static RangingMeasurement getRangingMeasurement() {
-        return getRangingMeasurement(getUwbAddress(false));
-    }
-
-    public static PersistableBundle getTestRangingMetadata() {
-        PersistableBundle bundle = new PersistableBundle();
-        bundle.putInt("TEST_KEY", 1);
-        return bundle;
-    }
-
-    public static RangingMeasurement getRangingMeasurement(UwbAddress address) {
-        return new RangingMeasurement.Builder()
-                .setDistanceMeasurement(getDistanceMeasurement())
-                .setAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement())
-                .setDestinationAngleOfArrivalMeasurement(getAngleOfArrivalMeasurement())
-                .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos())
-                .setRemoteDeviceAddress(address != null ? address : getUwbAddress(false))
-                .setStatus(RangingMeasurement.RANGING_STATUS_SUCCESS)
-                .setLineOfSight(RangingMeasurement.NLOS)
-                .setMeasurementFocus(RangingMeasurement.MEASUREMENT_FOCUS_RANGE)
-                .setRssiDbm(-85)
-                .setRangingMeasurementMetadata(getTestRangingMetadata())
-                .build();
-    }
-
-    public static List<RangingMeasurement> getRangingMeasurements(int num) {
-        List<RangingMeasurement> result = new ArrayList<>();
-        for (int i = 0; i < num; i++) {
-            result.add(getRangingMeasurement());
-        }
-        return result;
-    }
-
-    public static RangingReport getRangingReports(int numMeasurements) {
-        RangingReport.Builder builder = new RangingReport.Builder();
-        for (int i = 0; i < numMeasurements; i++) {
-            builder.addMeasurement(getRangingMeasurement());
-        }
-        return builder.build();
-    }
-
-    private static double getDoubleInRange(double min, double max) {
-        return min + (max - min) * Math.random();
-    }
-
-    public static UwbAddress getUwbAddress(boolean isShortAddress) {
-        byte[] addressBytes = new byte[isShortAddress ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH :
-                UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH];
-        for (int i = 0; i < addressBytes.length; i++) {
-            addressBytes[i] = (byte) getDoubleInRange(1, 255);
-        }
-        return UwbAddress.fromBytes(addressBytes);
-    }
-
-    public static Executor getExecutor() {
-        return new Executor() {
-            @Override
-            public void execute(Runnable command) {
-                command.run();
-            }
-        };
-    }
-}