Merge "API Review] Removed unnecessary SystemApi annotations" into tm-dev
diff --git a/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py b/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
index 7caebd2..be22003 100644
--- a/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
+++ b/apps/CameraITS/tests/scene1_2/test_yuv_plus_jpeg.py
@@ -84,6 +84,8 @@
       else:
         w, h = capture_request_utils.get_available_output_sizes(
             'yuv', props, max_size=MAX_IMG_SIZE)[0]
+      logging.debug('YUV size: (%d, %d)', w, h)
+      logging.debug('JPEG size: %s', max_jpeg_size)
       fmt_yuv = {'format': 'yuv', 'width': w, 'height': h}
       fmt_jpg = {'format': 'jpeg'}
 
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index df1813c..ccacfee 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -91,7 +91,6 @@
 _GYRO_POST_WAIT_TIME = 0.2  # Seconds to wait to capture some extra gyro data.
 _IMG_SIZE_MAX = 640 * 480  # Maximum image size.
 _NUM_FRAMES_MAX = 300  # fps*test_length should be < this for smooth captures.
-_NUM_GYRO_PTS_TO_AVG = 20  # Number of gyroscope events to average.
 
 
 def _collect_data(cam, fps, w, h, test_length, rot_rig, chart_dist, log_path):
@@ -194,51 +193,6 @@
   return events, frames
 
 
-def _plot_gyro_events(gyro_events, log_path):
-  """Plot x, y, and z on the gyro events.
-
-  Samples are grouped into NUM_GYRO_PTS_TO_AVG groups and averaged to minimize
-  random spikes in data.
-
-  Args:
-    gyro_events: List of gyroscope events.
-    log_path: Text to location to save data.
-  """
-
-  nevents = (len(gyro_events) // _NUM_GYRO_PTS_TO_AVG) * _NUM_GYRO_PTS_TO_AVG
-  gyro_events = gyro_events[:nevents]
-  times = np.array([(e['time'] - gyro_events[0]['time']) * _NSEC_TO_SEC
-                    for e in gyro_events])
-  x = np.array([e['x'] for e in gyro_events])
-  y = np.array([e['y'] for e in gyro_events])
-  z = np.array([e['z'] for e in gyro_events])
-
-  # Group samples into size-N groups & average each together to minimize random
-  # spikes in data.
-  times = times[_NUM_GYRO_PTS_TO_AVG//2::_NUM_GYRO_PTS_TO_AVG]
-  x = x.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
-  y = y.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
-  z = z.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
-
-  pylab.figure(_NAME)
-  # x & y on same axes
-  pylab.subplot(2, 1, 1)
-  pylab.title(_NAME + ' (mean of %d pts)' % _NUM_GYRO_PTS_TO_AVG)
-  pylab.plot(times, x, 'r', label='x')
-  pylab.plot(times, y, 'g', label='y')
-  pylab.ylabel('gyro x & y movement (rads/s)')
-  pylab.legend()
-
-  # z on separate axes
-  pylab.subplot(2, 1, 2)
-  pylab.plot(times, z, 'b', label='z')
-  pylab.xlabel('time (seconds)')
-  pylab.ylabel('gyro z movement (rads/s)')
-  pylab.legend()
-  matplotlib.pyplot.savefig(
-      '%s_gyro_events.png' % (os.path.join(log_path, _NAME)))
-
-
 def _get_cam_times(cam_events, fps):
   """Get the camera frame times.
 
@@ -543,7 +497,7 @@
                                        rot_rig, chart_distance, log_path)
     logging.debug('Start frame: %d', _START_FRAME)
 
-    _plot_gyro_events(events['gyro'], log_path)
+    sensor_fusion_utils.plot_gyro_events(events['gyro'], _NAME, log_path)
 
     # Validity check on gyro/camera timestamps
     cam_times = _get_cam_times(
diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py
index e7893fe..e1b3a07 100644
--- a/apps/CameraITS/utils/sensor_fusion_utils.py
+++ b/apps/CameraITS/utils/sensor_fusion_utils.py
@@ -17,10 +17,13 @@
 import bisect
 import codecs
 import logging
+import os
 import struct
 import time
 import unittest
 
+from matplotlib import pylab
+import matplotlib.pyplot
 import numpy as np
 import scipy.spatial
 import serial
@@ -63,6 +66,8 @@
 _NSEC_TO_SEC = 1E-9
 _SEC_TO_NSEC = int(1/_NSEC_TO_SEC)
 
+_NUM_GYRO_PTS_TO_AVG = 20
+
 
 def serial_port_def(name):
   """Determine the serial port and open.
@@ -405,6 +410,52 @@
   return exact_best_shift, fit_coeffs, shift_candidates, spatial_distances
 
 
+def plot_gyro_events(gyro_events, plot_name, log_path):
+  """Plot x, y, and z on the gyro events.
+
+  Samples are grouped into NUM_GYRO_PTS_TO_AVG groups and averaged to minimize
+  random spikes in data.
+
+  Args:
+    gyro_events: List of gyroscope events.
+    plot_name:  name of plot(s).
+    log_path: location to save data.
+  """
+
+  nevents = (len(gyro_events) // _NUM_GYRO_PTS_TO_AVG) * _NUM_GYRO_PTS_TO_AVG
+  gyro_events = gyro_events[:nevents]
+  times = np.array([(e['time'] - gyro_events[0]['time']) * _NSEC_TO_SEC
+                    for e in gyro_events])
+  x = np.array([e['x'] for e in gyro_events])
+  y = np.array([e['y'] for e in gyro_events])
+  z = np.array([e['z'] for e in gyro_events])
+
+  # Group samples into size-N groups & average each together to minimize random
+  # spikes in data.
+  times = times[_NUM_GYRO_PTS_TO_AVG//2::_NUM_GYRO_PTS_TO_AVG]
+  x = x.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
+  y = y.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
+  z = z.reshape(nevents//_NUM_GYRO_PTS_TO_AVG, _NUM_GYRO_PTS_TO_AVG).mean(1)
+
+  pylab.figure(plot_name)
+  # x & y on same axes
+  pylab.subplot(2, 1, 1)
+  pylab.title(f'{plot_name}(mean of {_NUM_GYRO_PTS_TO_AVG} pts)')
+  pylab.plot(times, x, 'r', label='x')
+  pylab.plot(times, y, 'g', label='y')
+  pylab.ylabel('gyro x & y movement (rads/s)')
+  pylab.legend()
+
+  # z on separate axes
+  pylab.subplot(2, 1, 2)
+  pylab.plot(times, z, 'b', label='z')
+  pylab.xlabel('time (seconds)')
+  pylab.ylabel('gyro z movement (rads/s)')
+  pylab.legend()
+  file_name = os.path.join(log_path, plot_name)
+  matplotlib.pyplot.savefig(f'{file_name}_gyro_events.png')
+
+
 class SensorFusionUtilsTests(unittest.TestCase):
   """Run a suite of unit tests on this module."""
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
index 336a923..3f27a2d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
@@ -592,7 +592,11 @@
         shutdownCamera();
 
         mCurrentCameraIndex = index;
-        mCameraId = mCameraIdList[index];
+
+        Set<String> cameraIdSet = mTestCases.keySet();
+        List<String> stringsList = new ArrayList<>(cameraIdSet);
+
+        mCameraId = stringsList.get(index);
         try {
             mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
             mCameraDevice = mBlockingCameraManager.openCamera(mCameraId,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 61f0ea8..588f061 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -177,7 +177,7 @@
     private CameraCaptureSession mSession = null;
     private ImageReader[] mOutputImageReaders = null;
     private SparseArray<String> mPhysicalStreamMap = new SparseArray<String>();
-    private SparseArray<Integer> mStreamUseCaseMap = new SparseArray<Integer>();
+    private SparseArray<Long> mStreamUseCaseMap = new SparseArray<Long>();
     private ImageReader mInputImageReader = null;
     private CameraCharacteristics mCameraCharacteristics = null;
     private HashMap<String, CameraCharacteristics> mPhysicalCameraChars =
@@ -1604,7 +1604,7 @@
 
                     outputSizes[i] = new Size(width, height);
                     if (!surfaceObj.isNull("useCase")) {
-                        mStreamUseCaseMap.put(i, surfaceObj.optInt("useCase"));
+                        mStreamUseCaseMap.put(i, surfaceObj.optLong("useCase"));
                     }
                 }
             } catch (org.json.JSONException e) {
diff --git a/apps/VpnApp/latest/AndroidManifest.xml b/apps/VpnApp/latest/AndroidManifest.xml
index 76c5e35..959ceda7 100644
--- a/apps/VpnApp/latest/AndroidManifest.xml
+++ b/apps/VpnApp/latest/AndroidManifest.xml
@@ -26,6 +26,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <action android:name="com.android.cts.vpnfirewall.action.CONNECT_AND_FINISH"/>
+                <action android:name="com.android.cts.vpnfirewall.action.DISCONNECT_AND_FINISH"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
diff --git a/common/device-side/bedstead/deviceadminapp/src/main/AndroidManifest.xml b/common/device-side/bedstead/deviceadminapp/src/main/AndroidManifest.xml
index 7733f55..c880395 100644
--- a/common/device-side/bedstead/deviceadminapp/src/main/AndroidManifest.xml
+++ b/common/device-side/bedstead/deviceadminapp/src/main/AndroidManifest.xml
@@ -29,5 +29,27 @@
                 <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
             </intent-filter>
         </receiver>
+
+        <receiver android:name="com.android.eventlib.premade.EventLibDelegatedAdminReceiver"
+                  android:permission="android.permission.BIND_DEVICE_ADMIN"
+                  android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS"/>
+                <action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
+                <action android:name="android.app.action.SECURITY_LOGS_AVAILABLE"/>
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.eventlib.premade.EventLibDelegatedAdminReceiver"
+                  android:permission="android.permission.BIND_DEVICE_ADMIN"
+                  android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS"/>
+                <action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
+                <action android:name="android.app.action.SECURITY_LOGS_AVAILABLE"/>
+            </intent-filter>
+        </receiver>
     </application>
 </manifest>
diff --git a/common/device-side/bedstead/deviceadminapp/src/main/java/com/android/bedstead/deviceadminapp/DeviceAdminApp.java b/common/device-side/bedstead/deviceadminapp/src/main/java/com/android/bedstead/deviceadminapp/DeviceAdminApp.java
index 4312217..acfe7f9 100644
--- a/common/device-side/bedstead/deviceadminapp/src/main/java/com/android/bedstead/deviceadminapp/DeviceAdminApp.java
+++ b/common/device-side/bedstead/deviceadminapp/src/main/java/com/android/bedstead/deviceadminapp/DeviceAdminApp.java
@@ -16,10 +16,12 @@
 
 package com.android.bedstead.deviceadminapp;
 
+import android.app.admin.DelegatedAdminReceiver;
 import android.app.admin.DeviceAdminReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 
+import com.android.eventlib.premade.EventLibDelegatedAdminReceiver;
 import com.android.eventlib.premade.EventLibDeviceAdminReceiver;
 
 /**
@@ -32,4 +34,10 @@
         return new ComponentName(
                 context.getPackageName(), EventLibDeviceAdminReceiver.class.getName());
     }
+
+    /** Get the {@link ComponentName} for the {@link DelegatedAdminReceiver} subclass. */
+    public static ComponentName delegatedAdminComponentName(Context context) {
+        return new ComponentName(
+                context.getPackageName(), EventLibDelegatedAdminReceiver.class.getName());
+    }
 }
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
index e2a4c84..cbc83a4 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/Events.java
@@ -38,7 +38,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /** Event store for the current package. */
-class Events {
+final class Events {
 
     private static final String TAG = "EventLibEvents";
     private static final String EVENT_LOG_FILE_NAME = "Events";
@@ -87,28 +87,30 @@
     }
 
     private void loadEventsFromFile() {
-        mEventList.clear();
-        Instant now = Instant.now();
-        Deque<Event> eventQueue = new ArrayDeque<>();
-        try (FileInputStream fileInputStream = mContext.openFileInput(EVENT_LOG_FILE_NAME)) {
-            Event event = readEvent(fileInputStream);
+        synchronized (mEventList) {
+            mEventList.clear();
+            Instant now = Instant.now();
+            Deque<Event> eventQueue = new ArrayDeque<>();
+            try (FileInputStream fileInputStream = mContext.openFileInput(EVENT_LOG_FILE_NAME)) {
+                Event event = readEvent(fileInputStream);
 
-            while (event != null) {
-                // I'm not sure if we need this
-                if (event.mTimestamp.plus(MAX_LOG_AGE).isAfter(now)) {
-                    eventQueue.addFirst(event);
+                while (event != null) {
+                    // I'm not sure if we need this
+                    if (event.mTimestamp.plus(MAX_LOG_AGE).isAfter(now)) {
+                        eventQueue.addFirst(event);
+                    }
+                    event = readEvent(fileInputStream);
                 }
-                event = readEvent(fileInputStream);
-            }
 
-            for (Event e : eventQueue) {
-                mEventList.addFirst(e);
+                for (Event e : eventQueue) {
+                    mEventList.addFirst(e);
+                }
+            } catch (FileNotFoundException e) {
+                // Ignore this exception as if there's no file there's nothing to load
+                Log.i(TAG, "No existing event file");
+            } catch (IOException e) {
+                Log.e(TAG, "Error when loading events from file", e);
             }
-        } catch (FileNotFoundException e) {
-            // Ignore this exception as if there's no file there's nothing to load
-            Log.i(TAG, "No existing event file");
-        } catch (IOException e) {
-            Log.e(TAG, "Error when loading events from file", e);
         }
     }
 
@@ -163,13 +165,17 @@
 
     /** Get all logged events. */
     public Queue<Event> getEvents() {
-            return mEventList;
+        return mEventList;
     }
 
     /** Register an {@link EventListener} to be called when a new {@link Event} is logged. */
-    public void registerEventListener(EventListener listener) {
-        synchronized (mEventListeners) {
-            mEventListeners.add(listener);
+    public Queue<Event> registerEventListener(EventListener listener) {
+        synchronized (mEventList) {
+            synchronized (mEventListeners) {
+                mEventListeners.add(listener);
+
+                return getEvents();
+            }
         }
     }
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
index 1b51899..c1be192 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/LocalEventQuerier.java
@@ -36,8 +36,7 @@
     LocalEventQuerier(Context context, EventLogsQuery<E, F> eventLogsQuery) {
         mEventLogsQuery = eventLogsQuery;
         mEvents = Events.getInstance(context, /* needsHistory= */ true);
-        mFetchedEvents = new LinkedBlockingDeque<>(mEvents.getEvents());
-        mEvents.registerEventListener(this);
+        mFetchedEvents = new LinkedBlockingDeque<>(mEvents.registerEventListener(this));
     }
 
     @Override
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminChoosePrivateKeyAliasEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminChoosePrivateKeyAliasEvent.java
new file mode 100644
index 0000000..31d4fcd
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminChoosePrivateKeyAliasEvent.java
@@ -0,0 +1,271 @@
+/*
+ * 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 com.android.eventlib.events.delegatedadminreceivers;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.annotation.CheckResult;
+
+import com.android.eventlib.Event;
+import com.android.eventlib.EventLogger;
+import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.info.DelegatedAdminReceiverInfo;
+import com.android.queryable.queries.DelegatedAdminReceiverQuery;
+import com.android.queryable.queries.DelegatedAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntegerQuery;
+import com.android.queryable.queries.IntegerQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.StringQuery;
+import com.android.queryable.queries.StringQueryHelper;
+import com.android.queryable.queries.UriQuery;
+import com.android.queryable.queries.UriQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
+
+/**
+ * Event logged when
+ * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)} is
+ * called.
+ */
+public final class DelegatedAdminChoosePrivateKeyAliasEvent extends Event {
+
+    private static final long serialVersionUID = 1;
+
+    /** Begins a query for {@link DelegatedAdminChoosePrivateKeyAliasEvent} events. */
+    public static DelegatedAdminChoosePrivateKeyAliasEventQuery queryPackage(String packageName) {
+        return new DelegatedAdminChoosePrivateKeyAliasEventQuery(packageName);
+    }
+
+    /** {@link EventLogsQuery} for {@link DelegatedAdminChoosePrivateKeyAliasEvent}. */
+    public static final class DelegatedAdminChoosePrivateKeyAliasEventQuery
+            extends EventLogsQuery<DelegatedAdminChoosePrivateKeyAliasEvent,
+            DelegatedAdminChoosePrivateKeyAliasEventQuery> {
+
+        private static final long serialVersionUID = 1;
+
+        DelegatedAdminReceiverQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> mDelegatedAdminReceiver =
+                new DelegatedAdminReceiverQueryHelper<>(this);
+        IntentQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> mIntent =
+                new IntentQueryHelper<>(this);
+        IntegerQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> mUid =
+                new IntegerQueryHelper<>(this);
+        UriQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> mUri =
+                new UriQueryHelper<>(this);
+        StringQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> mAlias =
+                new StringQueryHelper<>(this);
+
+        private DelegatedAdminChoosePrivateKeyAliasEventQuery(String packageName) {
+            super(DelegatedAdminChoosePrivateKeyAliasEvent.class, packageName);
+        }
+
+        /**
+         * Queries {@link Intent} passed into
+         * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String).
+         */
+        @CheckResult
+        public IntentQueryHelper<DelegatedAdminChoosePrivateKeyAliasEventQuery> whereIntent() {
+            return mIntent;
+        }
+
+        /** Queries {@link DelegatedAdminReceiver}. */
+        @CheckResult
+        public DelegatedAdminReceiverQuery<DelegatedAdminChoosePrivateKeyAliasEventQuery> whereDelegatedAdminReceiver() {
+            return mDelegatedAdminReceiver;
+        }
+
+        /** Query {@code uid}. */
+        @CheckResult
+        public IntegerQuery<DelegatedAdminChoosePrivateKeyAliasEventQuery> whereUid() {
+            return mUid;
+        }
+
+        /** Queries {@link Uri}. */
+        @CheckResult
+        public UriQuery<DelegatedAdminChoosePrivateKeyAliasEventQuery> whereUri() {
+            return mUri;
+        }
+
+        /** Query {@code alias}. */
+        @CheckResult
+        public StringQuery<DelegatedAdminChoosePrivateKeyAliasEventQuery> whereAlias() {
+            return mAlias;
+        }
+
+        @Override
+        protected boolean filter(DelegatedAdminChoosePrivateKeyAliasEvent event) {
+            if (!mIntent.matches(event.mIntent)) {
+                return false;
+            }
+            if (!mDelegatedAdminReceiver.matches(event.mDelegatedAdminReceiver)) {
+                return false;
+            }
+            if (!mUid.matches(event.mUid)) {
+                return false;
+            }
+            if (!mUri.matches(event.mUri)) {
+                return false;
+            }
+            if (!mAlias.matches(event.mAlias)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String describeQuery(String fieldName) {
+            return toStringBuilder(DelegatedAdminChoosePrivateKeyAliasEvent.class, this)
+                    .field("intent", mIntent)
+                    .field("delegatedAdminReceiver", mDelegatedAdminReceiver)
+                    .field("uid", mUid)
+                    .field("uri", mUri)
+                    .field("alias", mAlias)
+                    .toString();
+        }
+    }
+
+    /** Begins logging a {@link DelegatedAdminChoosePrivateKeyAliasEvent}. */
+    public static DelegatedAdminChoosePrivateKeyAliasEventLogger logger(
+            DelegatedAdminReceiver delegatedAdminReceiver, Context context,
+            Intent intent, int uid, Uri uri, String alias) {
+        return new DelegatedAdminChoosePrivateKeyAliasEventLogger(
+                delegatedAdminReceiver, context, intent, uid, uri, alias);
+    }
+
+    /** {@link EventLogger} for {@link DelegatedAdminChoosePrivateKeyAliasEvent}. */
+    public static final class DelegatedAdminChoosePrivateKeyAliasEventLogger
+            extends EventLogger<DelegatedAdminChoosePrivateKeyAliasEvent> {
+        private DelegatedAdminChoosePrivateKeyAliasEventLogger(
+                DelegatedAdminReceiver delegatedAdminReceiver, Context context, Intent intent,
+                int uid, Uri uri, String alias) {
+            super(context, new DelegatedAdminChoosePrivateKeyAliasEvent());
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            mEvent.mUid = uid;
+            mEvent.mUri = new SerializableParcelWrapper<>(uri);
+            mEvent.mAlias = alias;
+            setDelegatedAdminReceiver(delegatedAdminReceiver);
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setDelegatedAdminReceiver(
+                DelegatedAdminReceiver delegatedAdminReceiver) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(delegatedAdminReceiver);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setDelegatedAdminReceiver(
+                Class<? extends DelegatedAdminReceiver> delegatedAdminReceiverClass) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(delegatedAdminReceiverClass);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setDelegatedAdminReceiver(
+                String delegatedAdminReceiverClassName) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(delegatedAdminReceiverClassName);
+            return this;
+        }
+
+        /** Sets the {@link Intent} which was received. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setIntent(Intent intent) {
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            return this;
+        }
+
+        /** Sets the {@code uid} which was received. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setUid(int uid) {
+            mEvent.mUid = uid;
+            return this;
+        }
+
+        /** Sets the {@link Uri} which was received. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setUri(Uri uri) {
+            mEvent.mUri = new SerializableParcelWrapper<>(uri);
+            return this;
+        }
+
+        /** Sets the {@code alias} which was received. */
+        public DelegatedAdminChoosePrivateKeyAliasEventLogger setAlias(String alias) {
+            mEvent.mAlias = alias;
+            return this;
+        }
+    }
+
+    protected SerializableParcelWrapper<Intent> mIntent;
+    protected DelegatedAdminReceiverInfo mDelegatedAdminReceiver;
+    protected int mUid;
+    protected SerializableParcelWrapper<Uri> mUri;
+    protected String mAlias;
+
+    /**
+     * The {@link Intent} passed into
+     * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)
+     */
+    public Intent intent() {
+        if (mIntent == null) {
+            return null;
+        }
+        return mIntent.get();
+    }
+
+    /** Information about the {@link DelegatedAdminReceiver} which received the intent. */
+    public DelegatedAdminReceiverInfo delegatedAdminReceiver() {
+        return mDelegatedAdminReceiver;
+    }
+
+    /**
+     * The {@code uid} passed into
+     * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)
+     */
+    public int uid() {
+        return mUid;
+    }
+
+    /**
+     * The {@link Uri} passed into
+     * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)
+     */
+    public Uri uri() {
+        if (mUri == null) {
+            return null;
+        }
+        return mUri.get();
+    }
+
+    /**
+     * The {@code alias} passed into
+     * {@link DelegatedAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)
+     */
+    public String alias() {
+        return mAlias;
+    }
+
+    @Override
+    public String toString() {
+        return "DelegatedAdminChoosePrivateKeyAliasEvent{"
+                + " intent=" + intent()
+                + ", uid=" + mUid
+                + ", uri=" + uri()
+                + ", alias=" + mAlias
+                + ", delegatedAdminReceiver=" + mDelegatedAdminReceiver
+                + ", packageName='" + mPackageName + "'"
+                + ", timestamp=" + mTimestamp
+                + "}";
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEvent.java
new file mode 100644
index 0000000..39b61d3
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEvent.java
@@ -0,0 +1,240 @@
+/*
+ * 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 com.android.eventlib.events.deviceadminreceivers;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.CheckResult;
+
+import com.android.eventlib.Event;
+import com.android.eventlib.EventLogger;
+import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.info.DelegatedAdminReceiverInfo;
+import com.android.queryable.queries.DelegatedAdminReceiverQuery;
+import com.android.queryable.queries.DelegatedAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntegerQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.queries.LongQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
+
+/**
+ * Event logged when {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long,
+ * int)}
+ * is called.
+ */
+public final class DelegatedAdminNetworkLogsAvailableEvent extends Event {
+
+    private static final long serialVersionUID = 1;
+    protected SerializableParcelWrapper<Intent> mIntent;
+    protected DelegatedAdminReceiverInfo mDelegatedAdminReceiver;
+    protected long mBatchToken;
+    protected int mNetworkLogsCount;
+
+    /** Begins a query for {@link DelegatedAdminNetworkLogsAvailableEvent} events. */
+    public static DelegatedAdminNetworkLogsAvailableEventQuery queryPackage(String packageName) {
+        return new DelegatedAdminNetworkLogsAvailableEventQuery(packageName);
+    }
+
+    /** Begins logging a {@link DelegatedAdminNetworkLogsAvailableEvent}. */
+    public static DelegatedAdminNetworkLogsAvailableEventLogger logger(
+            DelegatedAdminReceiver delegatedAdminReceiver, Context context, Intent intent,
+            long batchToken, int networkLogsCount) {
+        return new DelegatedAdminNetworkLogsAvailableEventLogger(
+                delegatedAdminReceiver, context, intent, batchToken, networkLogsCount);
+    }
+
+    /**
+     * The {@link Intent} passed into
+     * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+     */
+    public Intent intent() {
+        if (mIntent == null) {
+            return null;
+        }
+        return mIntent.get();
+    }
+
+    /** Information about the {@link DelegatedAdminReceiver} which received the intent. */
+    public DelegatedAdminReceiverInfo delegatedAdminReceiver() {
+        return mDelegatedAdminReceiver;
+    }
+
+    /**
+     * The {@code batchToken} passed into
+     * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+     */
+    public long batchToken() {
+        return mBatchToken;
+    }
+
+    /**
+     * The {@code networkLogsCount} passed into
+     * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+     */
+    public int networkLogsCount() {
+        return mNetworkLogsCount;
+    }
+
+    @Override
+    public String toString() {
+        return "DelegatedAdminNetworkLogsAvailableEvent{"
+                + " intent=" + intent()
+                + ", batchToken=" + mBatchToken
+                + ", networkLogsCount=" + mNetworkLogsCount
+                + ", delegatedAdminReceiver=" + mDelegatedAdminReceiver
+                + ", packageName='" + mPackageName + "'"
+                + ", timestamp=" + mTimestamp
+                + "}";
+    }
+
+    /** {@link EventLogsQuery} for {@link DelegatedAdminNetworkLogsAvailableEvent}. */
+    public static final class DelegatedAdminNetworkLogsAvailableEventQuery
+            extends EventLogsQuery<DelegatedAdminNetworkLogsAvailableEvent,
+            DelegatedAdminNetworkLogsAvailableEventQuery> {
+
+        private static final long serialVersionUID = 1;
+
+        DelegatedAdminReceiverQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery>
+                mDelegatedAdminReceiver =
+                new DelegatedAdminReceiverQueryHelper<>(this);
+        IntentQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> mIntent =
+                new IntentQueryHelper<>(this);
+        LongQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> mBatchToken =
+                new LongQueryHelper<>(this);
+        IntegerQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> mNetworkLogsCount =
+                new IntegerQueryHelper<>(this);
+
+        private DelegatedAdminNetworkLogsAvailableEventQuery(String packageName) {
+            super(DelegatedAdminNetworkLogsAvailableEvent.class, packageName);
+        }
+
+        /**
+         * Queries {@link Intent} passed into
+         * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+         */
+        @CheckResult
+        public IntentQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> whereIntent() {
+            return mIntent;
+        }
+
+        /** Queries {@link DelegatedAdminReceiver}. */
+        @CheckResult
+        public DelegatedAdminReceiverQuery<DelegatedAdminNetworkLogsAvailableEventQuery> whereDelegatedAdminReceiver() {
+            return mDelegatedAdminReceiver;
+        }
+
+        /**
+         * Query {@code batchToken} passed into
+         * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+         */
+        @CheckResult
+        public LongQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> whereBatchToken() {
+            return mBatchToken;
+        }
+
+        /**
+         * Query {@code networkLogsCount} passed into
+         * {@link DelegatedAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}.
+         */
+        @CheckResult
+        public IntegerQueryHelper<DelegatedAdminNetworkLogsAvailableEventQuery> whereNetworkLogsCount() {
+            return mNetworkLogsCount;
+        }
+
+        @Override
+        protected boolean filter(DelegatedAdminNetworkLogsAvailableEvent event) {
+            if (!mIntent.matches(event.mIntent)) {
+                return false;
+            }
+            if (!mDelegatedAdminReceiver.matches(event.mDelegatedAdminReceiver)) {
+                return false;
+            }
+            if (!mBatchToken.matches(event.mBatchToken)) {
+                return false;
+            }
+            return mNetworkLogsCount.matches(event.mNetworkLogsCount);
+        }
+
+        @Override
+        public String describeQuery(String fieldName) {
+            return toStringBuilder(DelegatedAdminNetworkLogsAvailableEvent.class, this)
+                    .field("intent", mIntent)
+                    .field("delegatedAdminReceiver", mDelegatedAdminReceiver)
+                    .field("batchToken", mBatchToken)
+                    .field("networkLogsCount", mNetworkLogsCount)
+                    .toString();
+        }
+    }
+
+    /** {@link EventLogger} for {@link DelegatedAdminNetworkLogsAvailableEvent}. */
+    public static final class DelegatedAdminNetworkLogsAvailableEventLogger
+            extends EventLogger<DelegatedAdminNetworkLogsAvailableEvent> {
+        private DelegatedAdminNetworkLogsAvailableEventLogger(
+                DelegatedAdminReceiver delegatedAdminReceiver, Context context, Intent intent,
+                long batchToken, int networkLogsCount) {
+            super(context, new DelegatedAdminNetworkLogsAvailableEvent());
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            mEvent.mBatchToken = batchToken;
+            mEvent.mNetworkLogsCount = networkLogsCount;
+            setDelegatedAdminReceiver(delegatedAdminReceiver);
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setDelegatedAdminReceiver(
+                DelegatedAdminReceiver delegatedAdminReceiver) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(delegatedAdminReceiver);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setDelegatedAdminReceiver(
+                Class<? extends DelegatedAdminReceiver> delegatedAdminReceiverClass) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(
+                    delegatedAdminReceiverClass);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setDelegatedAdminReceiver(
+                String delegatedAdminReceiverClassName) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(
+                    delegatedAdminReceiverClassName);
+            return this;
+        }
+
+        /** Sets the {@link Intent} which was received. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setIntent(Intent intent) {
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            return this;
+        }
+
+        /** Sets the {@code batchToken} which was received. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setBatchToken(long batchToken) {
+            mEvent.mBatchToken = batchToken;
+            return this;
+        }
+
+        /** Sets the {@code networkLogsCount} which was received. */
+        public DelegatedAdminNetworkLogsAvailableEventLogger setNetworkLogsCount(
+                int networkLogsCount) {
+            mEvent.mNetworkLogsCount = networkLogsCount;
+            return this;
+        }
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminReceiverEvents.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminReceiverEvents.java
new file mode 100644
index 0000000..9bb0552
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminReceiverEvents.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.android.eventlib.events.delegatedadminreceivers;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent.DelegatedAdminChoosePrivateKeyAliasEventQuery;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent.DelegatedAdminSecurityLogsAvailableEventQuery;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent.DelegatedAdminNetworkLogsAvailableEventQuery;
+
+/**
+ * Quick access to event queries about device admin receivers.
+ */
+public interface DelegatedAdminReceiverEvents {
+
+    /**
+     * Query for when {@link DeviceAdminReceiver#onChoosePrivateKeyAlias(Context, Intent, int, Uri, String)}
+     * is called on a device admin receiver.
+     *
+     * <p>Additional filters can be added to the returned object.
+     *
+     * <p>{@code #poll} can be used to fetch results, and the result can be asserted on.
+     */
+    DelegatedAdminChoosePrivateKeyAliasEventQuery delegateChoosePrivateKeyAlias();
+
+    /**
+     * Query for when {@link DeviceAdminReceiver#onNetworkLogsAvailable(Context, Intent, long, int)}
+     * is called on a device admin receiver.
+     *
+     * <p>Additional filters can be added to the returned object.
+     *
+     * <p>{@code #poll} can be used to fetch results, and the result can be asserted on.
+     */
+    DelegatedAdminNetworkLogsAvailableEventQuery delegateNetworkLogsAvailable();
+
+    /**
+     * Query for when {@link DeviceAdminReceiver#onSecurityLogsAvailable(Context, Intent)} is called
+     * on a device admin receiver.
+     *
+     * <p>Additional filters can be added to the returned object.
+     *
+     * <p>{@code #poll} can be used to fetch results, and the result can be asserted on.
+     */
+    DelegatedAdminSecurityLogsAvailableEventQuery delegateSecurityLogsAvailable();
+}
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEvent.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEvent.java
new file mode 100644
index 0000000..fa6689d
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEvent.java
@@ -0,0 +1,170 @@
+/*
+ * 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 com.android.eventlib.events.delegatedadminreceivers;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.annotation.CheckResult;
+
+import com.android.eventlib.Event;
+import com.android.eventlib.EventLogger;
+import com.android.eventlib.EventLogsQuery;
+import com.android.queryable.info.DelegatedAdminReceiverInfo;
+import com.android.queryable.queries.DelegatedAdminReceiverQuery;
+import com.android.queryable.queries.DelegatedAdminReceiverQueryHelper;
+import com.android.queryable.queries.IntentQueryHelper;
+import com.android.queryable.util.SerializableParcelWrapper;
+
+/**
+ * Event logged when {@link DelegatedAdminReceiver#onSecurityLogsAvailable(Context, Intent)}
+ * is called.
+ */
+public final class DelegatedAdminSecurityLogsAvailableEvent extends Event {
+
+    private static final long serialVersionUID = 1;
+    protected SerializableParcelWrapper<Intent> mIntent;
+    protected DelegatedAdminReceiverInfo mDelegatedAdminReceiver;
+
+    /** Begins a query for {@link DelegatedAdminSecurityLogsAvailableEvent} events. */
+    public static DelegatedAdminSecurityLogsAvailableEventQuery queryPackage(String packageName) {
+        return new DelegatedAdminSecurityLogsAvailableEventQuery(packageName);
+    }
+
+    /** Begins logging a {@link DelegatedAdminSecurityLogsAvailableEvent}. */
+    public static DelegatedAdminSecurityLogsAvailableEventLogger logger(
+            DelegatedAdminReceiver delegatedAdminReceiver, Context context, Intent intent) {
+        return new DelegatedAdminSecurityLogsAvailableEventLogger(delegatedAdminReceiver, context,
+                intent);
+    }
+
+    /**
+     * The {@link Intent} passed into
+     * {@link DelegatedAdminReceiver#onSecurityLogsAvailable(Context, Intent)}.
+     */
+    public Intent intent() {
+        if (mIntent == null) {
+            return null;
+        }
+        return mIntent.get();
+    }
+
+    /** Information about the {@link DelegatedAdminReceiver} which received the intent. */
+    public DelegatedAdminReceiverInfo delegatedAdminReceiver() {
+        return mDelegatedAdminReceiver;
+    }
+
+    @Override
+    public String toString() {
+        return "DelegatedAdminSecurityLogsAvailableEvent{"
+                + " intent=" + intent()
+                + ", delegatedAdminReceiver=" + mDelegatedAdminReceiver
+                + ", packageName='" + mPackageName + "'"
+                + ", timestamp=" + mTimestamp
+                + "}";
+    }
+
+    /** {@link EventLogsQuery} for {@link DelegatedAdminSecurityLogsAvailableEvent}. */
+    public static final class DelegatedAdminSecurityLogsAvailableEventQuery
+            extends EventLogsQuery<DelegatedAdminSecurityLogsAvailableEvent,
+            DelegatedAdminSecurityLogsAvailableEventQuery> {
+
+        private static final long serialVersionUID = 1;
+
+        DelegatedAdminReceiverQueryHelper<DelegatedAdminSecurityLogsAvailableEventQuery>
+                mDelegatedAdminReceiver =
+                new DelegatedAdminReceiverQueryHelper<>(this);
+        IntentQueryHelper<DelegatedAdminSecurityLogsAvailableEventQuery> mIntent =
+                new IntentQueryHelper<>(this);
+
+        private DelegatedAdminSecurityLogsAvailableEventQuery(String packageName) {
+            super(DelegatedAdminSecurityLogsAvailableEvent.class, packageName);
+        }
+
+        /**
+         * Queries {@link Intent} passed into
+         * {@link DelegatedAdminReceiver#onSecurityLogsAvailable(Context, Intent)}.
+         */
+        @CheckResult
+        public IntentQueryHelper<DelegatedAdminSecurityLogsAvailableEventQuery> whereIntent() {
+            return mIntent;
+        }
+
+        /** Queries {@link DelegatedAdminReceiver}. */
+        @CheckResult
+        public DelegatedAdminReceiverQuery<DelegatedAdminSecurityLogsAvailableEventQuery> whereDelegatedAdminReceiver() {
+            return mDelegatedAdminReceiver;
+        }
+
+        @Override
+        protected boolean filter(DelegatedAdminSecurityLogsAvailableEvent event) {
+            if (!mIntent.matches(event.mIntent)) {
+                return false;
+            }
+            return mDelegatedAdminReceiver.matches(event.mDelegatedAdminReceiver);
+        }
+
+        @Override
+        public String describeQuery(String fieldName) {
+            return toStringBuilder(DelegatedAdminSecurityLogsAvailableEvent.class, this)
+                    .field("intent", mIntent)
+                    .field("delegatedAdminReceiver", mDelegatedAdminReceiver)
+                    .toString();
+        }
+    }
+
+    /** {@link EventLogger} for {@link DelegatedAdminSecurityLogsAvailableEvent}. */
+    public static final class DelegatedAdminSecurityLogsAvailableEventLogger
+            extends EventLogger<DelegatedAdminSecurityLogsAvailableEvent> {
+        private DelegatedAdminSecurityLogsAvailableEventLogger(
+                DelegatedAdminReceiver delegatedAdminReceiver, Context context, Intent intent) {
+            super(context, new DelegatedAdminSecurityLogsAvailableEvent());
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            setDelegatedAdminReceiver(delegatedAdminReceiver);
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminSecurityLogsAvailableEventLogger setDelegatedAdminReceiver(
+                DelegatedAdminReceiver delegatedAdminReceiver) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(delegatedAdminReceiver);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminSecurityLogsAvailableEventLogger setDelegatedAdminReceiver(
+                Class<? extends DelegatedAdminReceiver> delegatedAdminReceiverClass) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(
+                    delegatedAdminReceiverClass);
+            return this;
+        }
+
+        /** Sets the {@link DelegatedAdminReceiver} which received this event. */
+        public DelegatedAdminSecurityLogsAvailableEventLogger setDelegatedAdminReceiver(
+                String delegatedAdminReceiverClassName) {
+            mEvent.mDelegatedAdminReceiver = new DelegatedAdminReceiverInfo(
+                    delegatedAdminReceiverClassName);
+            return this;
+        }
+
+        /** Sets the {@link Intent} which was received. */
+        public DelegatedAdminSecurityLogsAvailableEventLogger setIntent(Intent intent) {
+            mEvent.mIntent = new SerializableParcelWrapper<>(intent);
+            return this;
+        }
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibAppComponentFactory.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibAppComponentFactory.java
index 9d304b9..7cdfabc 100644
--- a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibAppComponentFactory.java
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibAppComponentFactory.java
@@ -54,6 +54,26 @@
         try {
             return super.instantiateReceiver(classLoader, className, intent);
         } catch (ClassNotFoundException e) {
+            if (className.endsWith("DeviceAdminReceiver")) {
+                Log.d(LOG_TAG, "Broadcast Receiver class (" + className
+                        + ") not found, routing to TestAppDeviceAdminReceiver");
+                EventLibDeviceAdminReceiver receiver = (EventLibDeviceAdminReceiver)
+                        super.instantiateReceiver(
+                                classLoader, EventLibDeviceAdminReceiver.class.getName(),
+                                intent);
+                receiver.setOverrideDeviceAdminReceiverClassName(className);
+                return receiver;
+            } else if (className.endsWith("DelegatedAdminReceiver")) {
+                Log.d(LOG_TAG, "Broadcast Receiver class (" + className
+                        + ") not found, routing to EventLibDelegatedAdminReceiver");
+                EventLibDelegatedAdminReceiver receiver = (EventLibDelegatedAdminReceiver)
+                        super.instantiateReceiver(
+                                classLoader, EventLibDelegatedAdminReceiver.class.getName(),
+                                intent);
+                receiver.setOverrideDelegatedAdminReceiverClassName(className);
+                return receiver;
+            }
+
             Log.d(LOG_TAG, "Broadcast Receiver class (" + className
                     + ") not found, routing to EventLibBroadcastReceiver");
 
diff --git a/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiver.java b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiver.java
new file mode 100644
index 0000000..891819d
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/main/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiver.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.android.eventlib.premade;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent.DelegatedAdminChoosePrivateKeyAliasEventLogger;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent.DelegatedAdminSecurityLogsAvailableEventLogger;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent.DelegatedAdminNetworkLogsAvailableEventLogger;
+
+/**
+ * {@link DelegatedAdminReceiver} which logs all callbacks using EventLib.
+ */
+@SuppressWarnings("NewApi")
+public class EventLibDelegatedAdminReceiver extends DelegatedAdminReceiver {
+
+    private String mOverrideDelegatedAdminReceiverClassName;
+
+    public void setOverrideDelegatedAdminReceiverClassName(
+            String overrideDelegatedAdminReceiverClassName) {
+        mOverrideDelegatedAdminReceiverClassName = overrideDelegatedAdminReceiverClassName;
+    }
+
+    /**
+     * Get the class name for this {@link DelegatedAdminReceiver}.
+     *
+     * <p>This will account for the name being overridden.
+     */
+    public String className() {
+        if (mOverrideDelegatedAdminReceiverClassName != null) {
+            return mOverrideDelegatedAdminReceiverClassName;
+        } else {
+            return EventLibDelegatedAdminReceiver.class.getName();
+        }
+    }
+
+    @Override
+    public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
+            String alias) {
+        DelegatedAdminChoosePrivateKeyAliasEventLogger logger =
+                DelegatedAdminChoosePrivateKeyAliasEvent
+                        .logger(this, context, intent, uid, uri, alias);
+
+        if (mOverrideDelegatedAdminReceiverClassName != null) {
+            logger.setDelegatedAdminReceiver(mOverrideDelegatedAdminReceiverClassName);
+        }
+
+        logger.log();
+
+        // TODO(b/198280332) Allow TestApp to return values for methods.
+        if (uri == null) {
+            return null;
+        }
+        return uri.getQueryParameter("alias");
+    }
+
+    @Override
+    public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
+            int networkLogsCount) {
+        DelegatedAdminNetworkLogsAvailableEventLogger logger =
+                DelegatedAdminNetworkLogsAvailableEvent
+                        .logger(this, context, intent, batchToken, networkLogsCount);
+
+        if (mOverrideDelegatedAdminReceiverClassName != null) {
+            logger.setDelegatedAdminReceiver(mOverrideDelegatedAdminReceiverClassName);
+        }
+
+        logger.log();
+    }
+
+    @Override
+    public void onSecurityLogsAvailable(Context context, Intent intent) {
+        DelegatedAdminSecurityLogsAvailableEventLogger logger =
+                DelegatedAdminSecurityLogsAvailableEvent.logger(this, context, intent);
+
+        if (mOverrideDelegatedAdminReceiverClassName != null) {
+            logger.setDelegatedAdminReceiver(mOverrideDelegatedAdminReceiverClassName);
+        }
+
+        logger.log();
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/test/AndroidManifest.xml b/common/device-side/bedstead/eventlib/src/test/AndroidManifest.xml
index bca5f18..a626be8 100644
--- a/common/device-side/bedstead/eventlib/src/test/AndroidManifest.xml
+++ b/common/device-side/bedstead/eventlib/src/test/AndroidManifest.xml
@@ -52,6 +52,17 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.eventlib.premade.EventLibDelegatedAdminReceiver"
+                  android:permission="android.permission.BIND_DEVICE_ADMIN"
+                  android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS"/>
+                <action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
+                <action android:name="android.app.action.SECURITY_LOGS_AVAILABLE"/>
+            </intent-filter>
+        </receiver>
+
         <service android:name="com.android.eventlib.premade.EventLibService"
                  android:exported="true" />
         <service android:name="com.android.generatedEventLibService" />
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEventTest.java
new file mode 100644
index 0000000..dc6c057
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminNetworkLogsAvailableEventTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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 com.android.eventlib.events.delegatedadminreceivers;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.eventlib.EventLogs;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class DelegatedAdminNetworkLogsAvailableEventTest {
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+    private static final String STRING_VALUE = "Value";
+    private static final String DIFFERENT_STRING_VALUE = "Value2";
+    private static final Intent INTENT = new Intent();
+
+    private static final String DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            TestDelegatedAdminReceiver.class.getName();
+    private static final String CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDelegatedAdminReceiver";
+    private static final String DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDelegatedAdminReceiver2";
+    private static final DelegatedAdminReceiver DEVICE_ADMIN_RECEIVER = new TestDelegatedAdminReceiver();
+    private static final long BATCH_TOKEN = 1;
+    private static final long DIFFERENT_BATCH_TOKEN = 2;
+    private static final int NETWORK_LOGS_COUNT = 1;
+    private static final int DIFFERENT_NETWORK_LOGS_COUNT = 2;
+
+    private static class TestDelegatedAdminReceiver extends DelegatedAdminReceiver {
+    }
+
+    @Before
+    public void setUp() {
+        EventLogs.resetLogs();
+    }
+
+    @Test
+    public void whereIntent_works() {
+        Intent intent = new Intent(STRING_VALUE);
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, intent, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereIntent_skipsNonMatching() {
+        Intent intent = new Intent(STRING_VALUE);
+        Intent differentIntent = new Intent();
+        differentIntent.setAction(DIFFERENT_STRING_VALUE);
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, differentIntent, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, intent, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_customValueOnLogger_works() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
+                                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className()).isEqualTo(
+                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_customValueOnLogger_skipsNonMatching() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                        DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT)
+                .setDelegatedAdminReceiver(DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                        DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className().isEqualTo(
+                                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className()).isEqualTo(
+                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_defaultValue_works() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_defaultValue_skipsNonMatching() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                        DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                        DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT)
+                .log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereBatchToken_works() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereBatchToken().isEqualTo(BATCH_TOKEN);
+
+        assertThat(eventLogs.poll().batchToken()).isEqualTo(BATCH_TOKEN);
+    }
+
+    @Test
+    public void whereBatchToken_skipsNonMatching() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, DIFFERENT_BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereBatchToken().isEqualTo(BATCH_TOKEN);
+
+        assertThat(eventLogs.poll().batchToken()).isEqualTo(BATCH_TOKEN);
+    }
+
+    @Test
+    public void whereNetworkLogsCount_works() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereNetworkLogsCount().isEqualTo(NETWORK_LOGS_COUNT);
+
+        assertThat(eventLogs.poll().networkLogsCount()).isEqualTo(NETWORK_LOGS_COUNT);
+    }
+
+    @Test
+    public void whereNetworkLogsCount_skipsNonMatching() {
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, DIFFERENT_NETWORK_LOGS_COUNT).log();
+        DelegatedAdminNetworkLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, INTENT, BATCH_TOKEN, NETWORK_LOGS_COUNT).log();
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereNetworkLogsCount().isEqualTo(NETWORK_LOGS_COUNT);
+
+        assertThat(eventLogs.poll().networkLogsCount()).isEqualTo(NETWORK_LOGS_COUNT);
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEventTest.java
new file mode 100644
index 0000000..42a5565
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/delegatedadminreceivers/DelegatedAdminSecurityLogsAvailableEventTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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 com.android.eventlib.events.delegatedadminreceivers;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.eventlib.EventLogs;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class DelegatedAdminSecurityLogsAvailableEventTest {
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+    private static final String STRING_VALUE = "Value";
+    private static final String DIFFERENT_STRING_VALUE = "Value2";
+    private static final Intent INTENT = new Intent();
+
+    private static final String DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            TestDelegatedAdminReceiver.class.getName();
+    private static final String CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDelegatedAdminReceiver";
+    private static final String DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            "customDelegatedAdminReceiver2";
+    private static final DelegatedAdminReceiver DEVICE_ADMIN_RECEIVER = new TestDelegatedAdminReceiver();
+
+    private static class TestDelegatedAdminReceiver extends DelegatedAdminReceiver {
+    }
+
+    @Before
+    public void setUp() {
+        EventLogs.resetLogs();
+    }
+
+    @Test
+    public void whereIntent_works() {
+        Intent intent = new Intent(STRING_VALUE);
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, intent).log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereIntent_skipsNonMatching() {
+        Intent intent = new Intent(STRING_VALUE);
+        Intent differentIntent = new Intent();
+        differentIntent.setAction(DIFFERENT_STRING_VALUE);
+        DelegatedAdminSecurityLogsAvailableEvent.logger(
+                DEVICE_ADMIN_RECEIVER, sContext, differentIntent).log();
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, intent).log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereIntent().action().isEqualTo(STRING_VALUE);
+
+        assertThat(eventLogs.poll().intent()).isEqualTo(intent);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_customValueOnLogger_works() {
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className()).isEqualTo(
+                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_customValueOnLogger_skipsNonMatching() {
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT)
+                .setDelegatedAdminReceiver(DIFFERENT_CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className()).isEqualTo(
+                CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_defaultValue_works() {
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT).log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void whereDelegatedAdminReceiver_defaultValue_skipsNonMatching() {
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT)
+                .setDelegatedAdminReceiver(CUSTOM_DEVICE_ADMIN_RECEIVER_CLASS_NAME)
+                .log();
+        DelegatedAdminSecurityLogsAvailableEvent.logger(DEVICE_ADMIN_RECEIVER, sContext, INTENT)
+                .log();
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName())
+                        .whereDelegatedAdminReceiver().broadcastReceiver().receiverClass().className()
+                        .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(eventLogs.poll().delegatedAdminReceiver().className())
+                .isEqualTo(DEFAULT_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceConfigurationChangedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceConfigurationChangedEventTest.java
index a4f0493..a51c57b 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceConfigurationChangedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceConfigurationChangedEventTest.java
@@ -16,10 +16,6 @@
 
 package com.android.eventlib.events.services;
 
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
 //TODO(b/204770471) Currently unable to create these tests without an instrumented service.
-@RunWith(JUnit4.class)
+//@RunWith(JUnit4.class)
 public class ServiceConfigurationChangedEventTest {}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceLowMemoryEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceLowMemoryEventTest.java
index 4808a5b..edd15e8 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceLowMemoryEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceLowMemoryEventTest.java
@@ -16,10 +16,6 @@
 
 package com.android.eventlib.events.services;
 
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
 //TODO(b/204770471) Currently unable to create these tests without an instrumented service.
-@RunWith(JUnit4.class)
+//@RunWith(JUnit4.class)
 public class ServiceLowMemoryEventTest {}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceMemoryTrimmedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceMemoryTrimmedEventTest.java
index 53a69cf..c633e3e 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceMemoryTrimmedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceMemoryTrimmedEventTest.java
@@ -16,10 +16,6 @@
 
 package com.android.eventlib.events.services;
 
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
 //TODO(b/204770471) Currently unable to create these tests without an instrumented service.
-@RunWith(JUnit4.class)
+//@RunWith(JUnit4.class)
 public class ServiceMemoryTrimmedEventTest {}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceReboundEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceReboundEventTest.java
index 9776bfa..0c09f39 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceReboundEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceReboundEventTest.java
@@ -16,10 +16,6 @@
 
 package com.android.eventlib.events.services;
 
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
 //TODO(b/204770471) Currently unable to create these tests without an instrumented service.
-@RunWith(JUnit4.class)
+//@RunWith(JUnit4.class)
 public class ServiceReboundEventTest {}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceTaskRemovedEventTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceTaskRemovedEventTest.java
index 40f1807..878a41a 100644
--- a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceTaskRemovedEventTest.java
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/events/services/ServiceTaskRemovedEventTest.java
@@ -16,10 +16,6 @@
 
 package com.android.eventlib.events.services;
 
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-
 //TODO(b/204770471) Currently unable to create these tests without an instrumented service.
-@RunWith(JUnit4.class)
+//@RunWith(JUnit4.class)
 public class ServiceTaskRemovedEventTest {}
diff --git a/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiverTest.java b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiverTest.java
new file mode 100644
index 0000000..5959f15
--- /dev/null
+++ b/common/device-side/bedstead/eventlib/src/test/java/com/android/eventlib/premade/EventLibDelegatedAdminReceiverTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.android.eventlib.premade;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.nene.TestApis;
+import com.android.eventlib.EventLogs;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public class EventLibDelegatedAdminReceiverTest {
+
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+    private static final Intent sIntent = new Intent();
+    private static final int UID = 1;
+    private static final Uri URI = Uri.parse("http://uri");
+    private static final String ALIAS = "alias";
+    private static final long BATCH_TOKEN = 1;
+    private static final int NETWORK_LOGS_COUNT = 1;
+
+    @Before
+    public void setUp() {
+        EventLogs.resetLogs();
+    }
+
+    @Test
+    public void choosePrivateKeyAlias_logsChoosePrivateKeyAliasEvent() {
+        EventLibDelegatedAdminReceiver receiver = new EventLibDelegatedAdminReceiver();
+
+        receiver.onChoosePrivateKeyAlias(sContext, sIntent, UID, URI, ALIAS);
+
+        EventLogs<DelegatedAdminChoosePrivateKeyAliasEvent> eventLogs =
+                DelegatedAdminChoosePrivateKeyAliasEvent.queryPackage(sContext.getPackageName());
+        assertThat(eventLogs.poll().intent()).isEqualTo(sIntent);
+    }
+
+    @Test
+    public void securityLogsAvailable_logsSecurityLogsAvailableEvent() {
+        EventLibDelegatedAdminReceiver receiver = new EventLibDelegatedAdminReceiver();
+
+        receiver.onSecurityLogsAvailable(sContext, sIntent);
+
+        EventLogs<DelegatedAdminSecurityLogsAvailableEvent> eventLogs =
+                DelegatedAdminSecurityLogsAvailableEvent.queryPackage(sContext.getPackageName());
+        assertThat(eventLogs.poll().intent()).isEqualTo(sIntent);
+    }
+
+    @Test
+    public void networkLogsAvailable_logsNetworksLogsAvailableEvent() {
+        EventLibDelegatedAdminReceiver receiver = new EventLibDelegatedAdminReceiver();
+
+        receiver.onNetworkLogsAvailable(sContext, sIntent, BATCH_TOKEN, NETWORK_LOGS_COUNT);
+
+        EventLogs<DelegatedAdminNetworkLogsAvailableEvent> eventLogs =
+                DelegatedAdminNetworkLogsAvailableEvent.queryPackage(sContext.getPackageName());
+        assertThat(eventLogs.poll().intent()).isEqualTo(sIntent);
+    }
+
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/BlockUninstall.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/BlockUninstall.java
new file mode 100644
index 0000000..a74583e
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/BlockUninstall.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CAN_BE_DELEGATED;
+import static com.android.bedstead.nene.devicepolicy.CommonDevicePolicy.DELEGATION_BLOCK_UNINSTALL;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for setting uninstall blocked.
+ *
+ * <p>This is used by methods such as
+ * {@code DevicePolicyManager#setUninstallBlocked(ComponentName, String, boolean)} and
+ * {@code DevicePolicyManager#isUninstallBlocked(ComponentName)}.
+ */
+@EnterprisePolicy(
+        dpc = APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER
+                | APPLIES_TO_OWN_USER | CAN_BE_DELEGATED,
+        delegatedScopes = DELEGATION_BLOCK_UNINSTALL
+)
+public final class BlockUninstall {
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/EnableSystemApp.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/EnableSystemApp.java
new file mode 100644
index 0000000..3d0943c
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/EnableSystemApp.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CAN_BE_DELEGATED;
+import static com.android.bedstead.nene.devicepolicy.CommonDevicePolicy.DELEGATION_ENABLE_SYSTEM_APP;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for enabling system apps.
+ *
+ * <p>See {@code DevicePolicyManager#enableSystemApp(ComponentName, String)} for more
+ * detail.
+ */
+@EnterprisePolicy(dpc = {
+        APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
+                | APPLIED_BY_DEVICE_OWNER | APPLIES_TO_OWN_USER | CAN_BE_DELEGATED},
+        delegatedScopes = DELEGATION_ENABLE_SYSTEM_APP)
+public final class EnableSystemApp {
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/HideApplication.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/HideApplication.java
new file mode 100644
index 0000000..5abed15
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/HideApplication.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CAN_BE_DELEGATED;
+import static com.android.bedstead.nene.devicepolicy.CommonDevicePolicy.DELEGATION_PACKAGE_ACCESS;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for hiding applications.
+ * See {@code DevicePolicyManager#setApplicationHidden(ComponentName, String, boolean)} for more
+ * detail.
+ */
+@EnterprisePolicy(dpc = {
+        APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
+                | APPLIED_BY_DEVICE_OWNER | APPLIES_TO_OWN_USER | CAN_BE_DELEGATED},
+        delegatedScopes = DELEGATION_PACKAGE_ACCESS)
+public final class HideApplication {
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NetworkLogging.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NetworkLogging.java
new file mode 100644
index 0000000..986c4dd
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NetworkLogging.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER_PROFILE;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CAN_BE_DELEGATED;
+import static com.android.bedstead.nene.devicepolicy.CommonDevicePolicy.DELEGATION_NETWORK_LOGGING;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for retrieving network logs.
+ */
+@EnterprisePolicy(dpc = {APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER_PROFILE
+        | APPLIES_TO_OWN_USER | CAN_BE_DELEGATED},
+        delegatedScopes = DELEGATION_NETWORK_LOGGING)
+public final class NetworkLogging {
+    // There's a special case where for DO if there is an unaffiliated
+    // user on the device a SecurityException will be thrown. For now we deal with this by
+    // not having any PolicyDoesNotApplyTest
+}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/SuspendPackage.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/SuspendPackage.java
new file mode 100644
index 0000000..324848f
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/SuspendPackage.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_PROFILE_OWNER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CAN_BE_DELEGATED;
+import static com.android.bedstead.nene.devicepolicy.CommonDevicePolicy.DELEGATION_PACKAGE_ACCESS;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/**
+ * Policy for hiding applications.
+ * See {@code DevicePolicyManager#setPackagesSuspended(ComponentName, String[], boolean)} for more
+ * detail.
+ */
+@EnterprisePolicy(dpc = {
+        APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
+                | APPLIED_BY_DEVICE_OWNER | APPLIES_TO_OWN_USER | CAN_BE_DELEGATED},
+        delegatedScopes = DELEGATION_PACKAGE_ACCESS)
+public final class SuspendPackage {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index 73fc2ac..f45db02 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -38,12 +38,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
-import android.os.Bundle;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
 import androidx.test.core.app.ApplicationProvider;
-import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.bedstead.harrier.annotations.AfterClass;
 import com.android.bedstead.harrier.annotations.BeforeClass;
@@ -95,6 +93,7 @@
 import com.android.bedstead.nene.devicepolicy.ProfileOwner;
 import com.android.bedstead.nene.exceptions.AdbException;
 import com.android.bedstead.nene.exceptions.NeneException;
+import com.android.bedstead.nene.logging.Logger;
 import com.android.bedstead.nene.packages.Package;
 import com.android.bedstead.nene.permissions.PermissionContext;
 import com.android.bedstead.nene.permissions.PermissionContextImpl;
@@ -139,6 +138,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -185,7 +185,7 @@
     private String mSkipTestsReason;
     private String mFailTestsReason;
     // The minimum version supported by tests, defaults to current version
-    private final int mMinSdkVersion;
+    private int mMinSdkVersion;
     private int mMinSdkVersionCurrentTest;
     private @Nullable String mPermissionsInstrumentationPackage;
     private final Set<String> mPermissionsInstrumentationPackagePermissions = new HashSet<>();
@@ -200,711 +200,753 @@
     // We are allowed 11 minutes before the entire test run fails
     private static final Duration MAX_TEST_DURATION = Duration.ofMinutes(10);
     private final ExecutorService mTestExecutor = Executors.newSingleThreadExecutor();
+    private Thread mTestThread;
+
+    private final Logger mLogger = Logger.forInstance(this);
 
     public DeviceState() {
-        Bundle arguments = InstrumentationRegistry.getArguments();
-        mSkipTestTeardown = Boolean.parseBoolean(
-                arguments.getString(SKIP_TEST_TEARDOWN_KEY, "false"));
-        mSkipClassTeardown = Boolean.parseBoolean(
-                arguments.getString(SKIP_CLASS_TEARDOWN_KEY, "false"));
-        mSkipTestsReason = arguments.getString(SKIP_TESTS_REASON_KEY, "");
-        mSkipTests = !mSkipTestsReason.isEmpty();
-        mMinSdkVersion = arguments.getInt(MIN_SDK_VERSION_KEY, SDK_INT);
-        mPermissionsInstrumentationPackage =
-                arguments.getString(PERMISSIONS_INSTRUMENTATION_PACKAGE_KEY);
-        if (mPermissionsInstrumentationPackage != null) {
-            mPermissionsInstrumentationPackagePermissions.addAll(
-                    TestApis.packages().find(mPermissionsInstrumentationPackage)
-                            .requestedPermissions());
-        }
+        mLogger.constructor(() -> {
+            Future<Thread> testThreadFuture = mTestExecutor.submit(Thread::currentThread);
+
+            mSkipTestTeardown = TestApis.instrumentation().arguments().getBoolean(SKIP_TEST_TEARDOWN_KEY, false);
+            mSkipClassTeardown = TestApis.instrumentation().arguments().getBoolean(SKIP_CLASS_TEARDOWN_KEY, false);
+
+            mSkipTestsReason = TestApis.instrumentation().arguments().getString(SKIP_TESTS_REASON_KEY, "");
+            mSkipTests = !mSkipTestsReason.isEmpty();
+            mMinSdkVersion = TestApis.instrumentation().arguments().getInt(MIN_SDK_VERSION_KEY, SDK_INT);
+            mPermissionsInstrumentationPackage = TestApis.instrumentation().arguments().getString(PERMISSIONS_INSTRUMENTATION_PACKAGE_KEY);
+            if (mPermissionsInstrumentationPackage != null) {
+                mPermissionsInstrumentationPackagePermissions.addAll(
+                        TestApis.packages().find(mPermissionsInstrumentationPackage)
+                                .requestedPermissions());
+            }
+
+            try {
+                mTestThread = testThreadFuture.get();
+            } catch (InterruptedException | ExecutionException e) {
+                throw new AssertionError(
+                        "Error setting up DeviceState. Interrupted getting test thread", e);
+            }
+        });
     }
 
     @Override
     void setSkipTestTeardown(boolean skipTestTeardown) {
-        mSkipTestTeardown = skipTestTeardown;
+        mLogger.method("setSkipTestTeardown", skipTestTeardown, () -> {
+            mSkipTestTeardown = skipTestTeardown;
+        });
     }
 
     @Override
     void setUsingBedsteadJUnit4(boolean usingBedsteadJUnit4) {
-        mUsingBedsteadJUnit4 = usingBedsteadJUnit4;
+        mLogger.method("setUsingBedsteadJUnit4", usingBedsteadJUnit4, () -> {
+            mUsingBedsteadJUnit4 = usingBedsteadJUnit4;
+        });
     }
 
-    @Override public Statement apply(final Statement base,
-            final Description description) {
-
-        if (description.isTest()) {
-            return applyTest(base, description);
-        } else if (description.isSuite()) {
-            return applySuite(base, description);
-        }
-        throw new IllegalStateException("Unknown description type: " + description);
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return mLogger.method("apply", base, description, () -> {
+            if (description.isTest()) {
+                return applyTest(base, description);
+            } else if (description.isSuite()) {
+                return applySuite(base, description);
+            }
+            throw new IllegalStateException("Unknown description type: " + description);
+        });
     }
 
     private Statement applyTest(Statement base, Description description) {
-        return new Statement() {
-            @Override public void evaluate() throws Throwable {
+        return mLogger.method("applyTest", base, description, () -> {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    Future<Throwable> future = mTestExecutor.submit(() -> {
+                        try {
+                            executeTest(base, description);
+                            return null;
+                        } catch (Throwable e) {
+                            return e;
+                        }
+                    });
 
-                Future<Throwable> future = mTestExecutor.submit(() -> {
                     try {
-                        executeTest(base, description);
-                        return null;
-                    } catch (Throwable e) {
-                        return e;
-                    }
-                });
+                        Throwable t = future.get(MAX_TEST_DURATION.getSeconds(), TimeUnit.SECONDS);
+                        if (t != null) {
+                            if (t instanceof AssertionError
+                                    || t instanceof AssumptionViolatedException) {
+                                throw t;
+                            } else {
+                                // We wrap the failure in an AssertionError so it doesn't crash
+                                throw new AssertionError("Exception while executing test", t);
+                            }
+                        }
+                    } catch (TimeoutException e) {
+                        StackTraceElement[] stack = mTestThread.getStackTrace();
+                        future.cancel(true);
 
-                try {
-                    Throwable t = future.get(MAX_TEST_DURATION.getSeconds(), TimeUnit.SECONDS);
-                    if (t != null) {
-                        throw t;
+                        AssertionError assertionError = new AssertionError(
+                                "Timed out executing test " + description.getDisplayName());
+                        assertionError.setStackTrace(stack);
+                        throw assertionError;
                     }
-                } catch (TimeoutException e) {
-                    future.cancel(true);
-
-                    throw new AssertionError(
-                            "Timed out executing test " + description.getDisplayName());
                 }
-            }};
+            };
+        });
     }
 
     private void executeTest(Statement base, Description description) throws Throwable {
-        PermissionContextImpl permissionContext = null;
+        mLogger.method(Throwable.class, "executeTest", base, description, () -> {
+            PermissionContextImpl permissionContext = null;
 
-        try {
-            Log.d(LOG_TAG, "Preparing state for test " + description.getMethodName());
+            String testName = description.getMethodName();
 
-            testApps().snapshot();
-            Tags.clearTags();
-            Tags.addTag(Tags.USES_DEVICESTATE);
-            assumeFalse(mSkipTestsReason, mSkipTests);
-            assertFalse(mFailTestsReason, mFailTests);
+            try {
+                Log.d(LOG_TAG, "Preparing state for test " + testName);
 
-            // Ensure that tests only see events from the current test
-            EventLogs.resetLogs();
+                testApps().snapshot();
+                Tags.clearTags();
+                Tags.addTag(Tags.USES_DEVICESTATE);
+                assumeFalse(mSkipTestsReason, mSkipTests);
+                assertFalse(mFailTestsReason, mFailTests);
 
-            mMinSdkVersionCurrentTest = mMinSdkVersion;
-            List<Annotation> annotations = getAnnotations(description);
-            permissionContext = applyAnnotations(annotations, /* isTest= */ true);
+                // Ensure that tests only see events from the current test
+                EventLogs.resetLogs();
 
-            Log.d(LOG_TAG,
-                    "Finished preparing state for test " + description.getMethodName());
+                mMinSdkVersionCurrentTest = mMinSdkVersion;
+                List<Annotation> annotations = getAnnotations(description);
+                permissionContext = applyAnnotations(annotations, /* isTest= */ true);
 
-            base.evaluate();
-        } finally {
-            Log.d(LOG_TAG,
-                    "Tearing down state for test " + description.getMethodName());
+                Log.d(LOG_TAG, "Finished preparing state for test " + testName);
 
-            if (permissionContext != null) {
-                permissionContext.close();
+                base.evaluate();
+            } finally {
+                Log.d(LOG_TAG, "Tearing down state for test " + testName);
+
+                if (permissionContext != null) {
+                    permissionContext.close();
+                }
+
+                teardownNonShareableState();
+                if (!mSkipTestTeardown) {
+                    teardownShareableState();
+                }
+                Log.d(LOG_TAG, "Finished tearing down state for test " + testName);
             }
-
-            teardownNonShareableState();
-            if (!mSkipTestTeardown) {
-                teardownShareableState();
-            }
-            Log.d(LOG_TAG,
-                    "Finished tearing down state for test "
-                            + description.getMethodName());
-        }
+        });
     }
 
     private PermissionContextImpl applyAnnotations(List<Annotation> annotations, boolean isTest)
             throws Throwable {
-        PermissionContextImpl permissionContext = null;
-        Log.i(LOG_TAG, "Applying annotations: " + annotations);
-        for (Annotation annotation : annotations) {
-            Log.i(LOG_TAG, "Applying annotation " + annotation);
+        return mLogger.method(Throwable.class, "applyAnnotations", annotations, isTest, () -> {
+            PermissionContextImpl permissionContext = null;
+            Log.i(LOG_TAG, "Applying annotations: " + annotations);
+            for (Annotation annotation : annotations) {
+                Log.i(LOG_TAG, "Applying annotation " + annotation);
 
-            Class<? extends Annotation> annotationType = annotation.annotationType();
+                Class<? extends Annotation> annotationType = annotation.annotationType();
 
-            EnsureHasNoProfileAnnotation ensureHasNoProfileAnnotation =
-                    annotationType.getAnnotation(EnsureHasNoProfileAnnotation.class);
-            if (ensureHasNoProfileAnnotation != null) {
-                UserType userType = (UserType) annotation.annotationType()
-                        .getMethod(FOR_USER).invoke(annotation);
-                ensureHasNoProfile(ensureHasNoProfileAnnotation.value(), userType);
-                continue;
-            }
+                EnsureHasNoProfileAnnotation ensureHasNoProfileAnnotation =
+                        annotationType.getAnnotation(EnsureHasNoProfileAnnotation.class);
+                if (ensureHasNoProfileAnnotation != null) {
+                    UserType userType = (UserType) annotation.annotationType()
+                            .getMethod(FOR_USER).invoke(annotation);
+                    ensureHasNoProfile(ensureHasNoProfileAnnotation.value(), userType);
+                    continue;
+                }
 
-            EnsureHasProfileAnnotation ensureHasProfileAnnotation =
-                    annotationType.getAnnotation(EnsureHasProfileAnnotation.class);
-            if (ensureHasProfileAnnotation != null) {
-                UserType forUser = (UserType) annotation.annotationType()
-                        .getMethod(FOR_USER).invoke(annotation);
-                OptionalBoolean installInstrumentedApp = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(INSTALL_INSTRUMENTED_APP).invoke(annotation);
-
-                boolean dpcIsPrimary = false;
-                boolean useParentInstance = false;
-                if (ensureHasProfileAnnotation.hasProfileOwner()) {
-                    dpcIsPrimary = (boolean)
+                EnsureHasProfileAnnotation ensureHasProfileAnnotation =
+                        annotationType.getAnnotation(EnsureHasProfileAnnotation.class);
+                if (ensureHasProfileAnnotation != null) {
+                    UserType forUser = (UserType) annotation.annotationType()
+                            .getMethod(FOR_USER).invoke(annotation);
+                    OptionalBoolean installInstrumentedApp = (OptionalBoolean)
                             annotation.annotationType()
-                                    .getMethod(DPC_IS_PRIMARY).invoke(annotation);
+                                    .getMethod(INSTALL_INSTRUMENTED_APP).invoke(annotation);
 
-                    if (dpcIsPrimary) {
-                        useParentInstance = (boolean)
+                    boolean dpcIsPrimary = false;
+                    boolean useParentInstance = false;
+                    if (ensureHasProfileAnnotation.hasProfileOwner()) {
+                        dpcIsPrimary = (boolean)
                                 annotation.annotationType()
-                                        .getMethod(USE_PARENT_INSTANCE_OF_DPC).invoke(annotation);
+                                        .getMethod(DPC_IS_PRIMARY).invoke(annotation);
 
+                        if (dpcIsPrimary) {
+                            useParentInstance = (boolean)
+                                    annotation.annotationType()
+                                            .getMethod(USE_PARENT_INSTANCE_OF_DPC).invoke(
+                                                    annotation);
+
+                        }
                     }
-                }
 
-                OptionalBoolean switchedToParentUser = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(SWITCHED_TO_PARENT_USER).invoke(annotation);
-
-                ensureHasProfile(
-                        ensureHasProfileAnnotation.value(), installInstrumentedApp,
-                        forUser, ensureHasProfileAnnotation.hasProfileOwner(),
-                        dpcIsPrimary, useParentInstance, switchedToParentUser);
-                continue;
-            }
-
-            EnsureHasNoUserAnnotation ensureHasNoUserAnnotation =
-                    annotationType.getAnnotation(EnsureHasNoUserAnnotation.class);
-            if (ensureHasNoUserAnnotation != null) {
-                ensureHasNoUser(ensureHasNoUserAnnotation.value());
-                continue;
-            }
-
-            EnsureHasUserAnnotation ensureHasUserAnnotation =
-                    annotationType.getAnnotation(EnsureHasUserAnnotation.class);
-            if (ensureHasUserAnnotation != null) {
-                OptionalBoolean installInstrumentedApp = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(INSTALL_INSTRUMENTED_APP).invoke(annotation);
-                OptionalBoolean switchedToUser = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(SWITCHED_TO_USER).invoke(annotation);
-                ensureHasUser(
-                        ensureHasUserAnnotation.value(), installInstrumentedApp, switchedToUser);
-                continue;
-            }
-
-            RequireRunOnUserAnnotation requireRunOnUserAnnotation =
-                    annotationType.getAnnotation(RequireRunOnUserAnnotation.class);
-            if (requireRunOnUserAnnotation != null) {
-                OptionalBoolean switchedToUser = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(SWITCHED_TO_USER).invoke(annotation);
-                requireRunOnUser(requireRunOnUserAnnotation.value(), switchedToUser);
-                continue;
-            }
-
-            if (annotation instanceof TestTag) {
-                TestTag testTagAnnotation = (TestTag) annotation;
-                Tags.addTag(testTagAnnotation.value());
-            }
-
-            RequireRunOnProfileAnnotation requireRunOnProfileAnnotation =
-                    annotationType.getAnnotation(RequireRunOnProfileAnnotation.class);
-            if (requireRunOnProfileAnnotation != null) {
-                OptionalBoolean installInstrumentedAppInParent = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod("installInstrumentedAppInParent")
-                                .invoke(annotation);
-
-                OptionalBoolean switchedToParentUser = (OptionalBoolean)
-                        annotation.annotationType()
-                                .getMethod(SWITCHED_TO_PARENT_USER).invoke(annotation);
-
-
-                boolean dpcIsPrimary = false;
-                Set<String> affiliationIds = null;
-                if (requireRunOnProfileAnnotation.hasProfileOwner()) {
-                    dpcIsPrimary = (boolean)
+                    OptionalBoolean switchedToParentUser = (OptionalBoolean)
                             annotation.annotationType()
-                                    .getMethod(DPC_IS_PRIMARY).invoke(annotation);
-                    affiliationIds = new HashSet<>(Arrays.asList((String[])
+                                    .getMethod(SWITCHED_TO_PARENT_USER).invoke(annotation);
+
+                    ensureHasProfile(
+                            ensureHasProfileAnnotation.value(), installInstrumentedApp,
+                            forUser, ensureHasProfileAnnotation.hasProfileOwner(),
+                            dpcIsPrimary, useParentInstance, switchedToParentUser);
+                    continue;
+                }
+
+                EnsureHasNoUserAnnotation ensureHasNoUserAnnotation =
+                        annotationType.getAnnotation(EnsureHasNoUserAnnotation.class);
+                if (ensureHasNoUserAnnotation != null) {
+                    ensureHasNoUser(ensureHasNoUserAnnotation.value());
+                    continue;
+                }
+
+                EnsureHasUserAnnotation ensureHasUserAnnotation =
+                        annotationType.getAnnotation(EnsureHasUserAnnotation.class);
+                if (ensureHasUserAnnotation != null) {
+                    OptionalBoolean installInstrumentedApp = (OptionalBoolean)
                             annotation.annotationType()
-                                    .getMethod(AFFILIATION_IDS).invoke(annotation)));
-                }
-
-                requireRunOnProfile(requireRunOnProfileAnnotation.value(),
-                        installInstrumentedAppInParent,
-                        requireRunOnProfileAnnotation.hasProfileOwner(),
-                        /* useParentInstance= */ false,
-                        dpcIsPrimary, switchedToParentUser, affiliationIds);
-                continue;
-            }
-
-            if (annotation instanceof EnsureTestAppInstalled) {
-                EnsureTestAppInstalled ensureTestAppInstalledAnnotation =
-                        (EnsureTestAppInstalled) annotation;
-                ensureTestAppInstalled(
-                        ensureTestAppInstalledAnnotation.key(),
-                        ensureTestAppInstalledAnnotation.packageName(),
-                        ensureTestAppInstalledAnnotation.onUser(),
-                        ensureTestAppInstalledAnnotation.isPrimary()
-                );
-                continue;
-            }
-
-            if (annotation instanceof EnsureTestAppHasPermission) {
-                EnsureTestAppHasPermission ensureTestAppHasPermissionAnnotation =
-                        (EnsureTestAppHasPermission) annotation;
-                ensureTestAppHasPermission(
-                        ensureTestAppHasPermissionAnnotation.testAppKey(),
-                        ensureTestAppHasPermissionAnnotation.value(),
-                        ensureTestAppHasPermissionAnnotation.minVersion(),
-                        ensureTestAppHasPermissionAnnotation.maxVersion()
-                );
-                continue;
-            }
-
-            if (annotation instanceof EnsureTestAppHasAppOp) {
-                EnsureTestAppHasAppOp ensureTestAppHasAppOpAnnotation =
-                        (EnsureTestAppHasAppOp) annotation;
-                ensureTestAppHasAppOp(
-                        ensureTestAppHasAppOpAnnotation.testAppKey(),
-                        ensureTestAppHasAppOpAnnotation.value(),
-                        ensureTestAppHasAppOpAnnotation.minVersion(),
-                        ensureTestAppHasAppOpAnnotation.maxVersion()
-                );
-                continue;
-            }
-
-            if (annotation instanceof EnsureHasDelegate) {
-                EnsureHasDelegate ensureHasDelegateAnnotation =
-                        (EnsureHasDelegate) annotation;
-                ensureHasDelegate(
-                        ensureHasDelegateAnnotation.admin(),
-                        Arrays.asList(ensureHasDelegateAnnotation.scopes()),
-                        ensureHasDelegateAnnotation.isPrimary());
-                continue;
-            }
-
-
-            if (annotation instanceof EnsureHasDeviceOwner) {
-                EnsureHasDeviceOwner ensureHasDeviceOwnerAnnotation =
-                        (EnsureHasDeviceOwner) annotation;
-                ensureHasDeviceOwner(ensureHasDeviceOwnerAnnotation.failureMode(),
-                        ensureHasDeviceOwnerAnnotation.isPrimary(),
-                        new HashSet<>(
-                                Arrays.asList(ensureHasDeviceOwnerAnnotation.affiliationIds())));
-                continue;
-            }
-
-            if (annotation instanceof EnsureHasNoDelegate) {
-                EnsureHasNoDelegate ensureHasNoDelegateAnnotation =
-                        (EnsureHasNoDelegate) annotation;
-                ensureHasNoDelegate(ensureHasNoDelegateAnnotation.admin());
-                continue;
-            }
-
-            if (annotation instanceof EnsureHasNoDeviceOwner) {
-                ensureHasNoDeviceOwner();
-                continue;
-            }
-
-            if (annotation instanceof RequireFeature) {
-                RequireFeature requireFeatureAnnotation = (RequireFeature) annotation;
-                requireFeature(
-                        requireFeatureAnnotation.value(),
-                        requireFeatureAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof RequireDoesNotHaveFeature) {
-                RequireDoesNotHaveFeature requireDoesNotHaveFeatureAnnotation =
-                        (RequireDoesNotHaveFeature) annotation;
-                requireDoesNotHaveFeature(
-                        requireDoesNotHaveFeatureAnnotation.value(),
-                        requireDoesNotHaveFeatureAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof EnsureHasProfileOwner) {
-                EnsureHasProfileOwner ensureHasProfileOwnerAnnotation =
-                        (EnsureHasProfileOwner) annotation;
-                ensureHasProfileOwner(ensureHasProfileOwnerAnnotation.onUser(),
-                        ensureHasProfileOwnerAnnotation.isPrimary(),
-                        ensureHasProfileOwnerAnnotation.useParentInstance(),
-                        new HashSet<>(Arrays.asList(ensureHasProfileOwnerAnnotation.affiliationIds())));
-                continue;
-            }
-
-            if (annotationType.equals(EnsureHasNoProfileOwner.class)) {
-                EnsureHasNoProfileOwner ensureHasNoProfileOwnerAnnotation =
-                        (EnsureHasNoProfileOwner) annotation;
-                ensureHasNoProfileOwner(ensureHasNoProfileOwnerAnnotation.onUser());
-                continue;
-            }
-
-            if (annotation instanceof RequireUserSupported) {
-                RequireUserSupported requireUserSupportedAnnotation =
-                        (RequireUserSupported) annotation;
-                requireUserSupported(
-                        requireUserSupportedAnnotation.value(),
-                        requireUserSupportedAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof RequireLowRamDevice) {
-                RequireLowRamDevice requireLowRamDeviceAnnotation =
-                        (RequireLowRamDevice) annotation;
-                requireLowRamDevice(requireLowRamDeviceAnnotation.reason(),
-                        requireLowRamDeviceAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof RequireNotLowRamDevice) {
-                RequireNotLowRamDevice requireNotLowRamDeviceAnnotation =
-                        (RequireNotLowRamDevice) annotation;
-                requireNotLowRamDevice(requireNotLowRamDeviceAnnotation.reason(),
-                        requireNotLowRamDeviceAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof RequireTargetSdkVersion) {
-                RequireTargetSdkVersion requireTargetSdkVersionAnnotation =
-                        (RequireTargetSdkVersion) annotation;
-
-                requireTargetSdkVersion(
-                        requireTargetSdkVersionAnnotation.min(),
-                        requireTargetSdkVersionAnnotation.max(),
-                        requireTargetSdkVersionAnnotation.failureMode());
-
-                continue;
-            }
-
-            if (annotation instanceof RequireSdkVersion) {
-                RequireSdkVersion requireSdkVersionAnnotation =
-                        (RequireSdkVersion) annotation;
-
-                if (requireSdkVersionAnnotation.reason().isEmpty()) {
-                    requireSdkVersion(
-                            requireSdkVersionAnnotation.min(),
-                            requireSdkVersionAnnotation.max(),
-                            requireSdkVersionAnnotation.failureMode());
-                } else {
-                    requireSdkVersion(
-                            requireSdkVersionAnnotation.min(),
-                            requireSdkVersionAnnotation.max(),
-                            requireSdkVersionAnnotation.failureMode(),
-                            requireSdkVersionAnnotation.reason());
-                }
-
-                continue;
-            }
-
-            if (annotation instanceof RequirePackageInstalled) {
-                RequirePackageInstalled requirePackageInstalledAnnotation =
-                        (RequirePackageInstalled) annotation;
-                requirePackageInstalled(
-                        requirePackageInstalledAnnotation.value(),
-                        requirePackageInstalledAnnotation.onUser(),
-                        requirePackageInstalledAnnotation.failureMode());
-                continue;
-            }
-
-            if (annotation instanceof RequirePackageNotInstalled) {
-                RequirePackageNotInstalled requirePackageNotInstalledAnnotation =
-                        (RequirePackageNotInstalled) annotation;
-                requirePackageNotInstalled(
-                        requirePackageNotInstalledAnnotation.value(),
-                        requirePackageNotInstalledAnnotation.onUser(),
-                        requirePackageNotInstalledAnnotation.failureMode()
-                );
-                continue;
-            }
-
-            if (annotation instanceof EnsurePackageNotInstalled) {
-                EnsurePackageNotInstalled ensurePackageNotInstalledAnnotation =
-                        (EnsurePackageNotInstalled) annotation;
-                ensurePackageNotInstalled(
-                        ensurePackageNotInstalledAnnotation.value(),
-                        ensurePackageNotInstalledAnnotation.onUser()
-                );
-                continue;
-            }
-
-            if (annotation instanceof RequireNotHeadlessSystemUserMode) {
-                requireNotHeadlessSystemUserMode();
-                continue;
-            }
-
-            if (annotation instanceof RequireHeadlessSystemUserMode) {
-                requireHeadlessSystemUserMode();
-                continue;
-            }
-
-            if (annotation instanceof EnsureCanGetPermission) {
-                EnsureCanGetPermission ensureCanGetPermissionAnnotation =
-                        (EnsureCanGetPermission) annotation;
-
-                if (!meetsSdkVersionRequirements(
-                        ensureCanGetPermissionAnnotation.minVersion(),
-                        ensureCanGetPermissionAnnotation.maxVersion())) {
-                    Log.d(LOG_TAG,
-                            "Version " + SDK_INT +  " does not need to get permissions "
-                                    + Arrays.toString(ensureCanGetPermissionAnnotation.value()));
+                                    .getMethod(INSTALL_INSTRUMENTED_APP).invoke(annotation);
+                    OptionalBoolean switchedToUser = (OptionalBoolean)
+                            annotation.annotationType()
+                                    .getMethod(SWITCHED_TO_USER).invoke(annotation);
+                    ensureHasUser(
+                            ensureHasUserAnnotation.value(), installInstrumentedApp,
+                            switchedToUser);
                     continue;
                 }
 
-                for (String permission : ensureCanGetPermissionAnnotation.value()) {
-                    ensureCanGetPermission(permission);
-                }
-                continue;
-            }
-
-            if (annotation instanceof EnsureHasAppOp) {
-                EnsureHasAppOp ensureHasAppOpAnnotation = (EnsureHasAppOp) annotation;
-
-                if (!meetsSdkVersionRequirements(
-                        ensureHasAppOpAnnotation.minVersion(),
-                        ensureHasAppOpAnnotation.maxVersion())) {
-                    Log.d(LOG_TAG,
-                            "Version " + SDK_INT +  " does not need to get appOp "
-                                    + ensureHasAppOpAnnotation.value());
+                RequireRunOnUserAnnotation requireRunOnUserAnnotation =
+                        annotationType.getAnnotation(RequireRunOnUserAnnotation.class);
+                if (requireRunOnUserAnnotation != null) {
+                    OptionalBoolean switchedToUser = (OptionalBoolean)
+                            annotation.annotationType()
+                                    .getMethod(SWITCHED_TO_USER).invoke(annotation);
+                    requireRunOnUser(requireRunOnUserAnnotation.value(), switchedToUser);
                     continue;
                 }
 
-                try {
-                    if (permissionContext == null) {
-                        permissionContext = TestApis.permissions().withAppOp(
-                                ensureHasAppOpAnnotation.value());
-                    } else {
-                        permissionContext = permissionContext.withAppOp(
-                                ensureHasAppOpAnnotation.value());
-                    }
-                } catch (NeneException e) {
-                    failOrSkip("Error getting appOp: " + e,
-                            ensureHasAppOpAnnotation.failureMode());
+                if (annotation instanceof TestTag) {
+                    TestTag testTagAnnotation = (TestTag) annotation;
+                    Tags.addTag(testTagAnnotation.value());
                 }
-                continue;
-            }
 
-            if (annotation instanceof EnsureDoesNotHaveAppOp) {
-                EnsureDoesNotHaveAppOp ensureDoesNotHaveAppOpAnnotation =
-                        (EnsureDoesNotHaveAppOp) annotation;
+                RequireRunOnProfileAnnotation requireRunOnProfileAnnotation =
+                        annotationType.getAnnotation(RequireRunOnProfileAnnotation.class);
+                if (requireRunOnProfileAnnotation != null) {
+                    OptionalBoolean installInstrumentedAppInParent = (OptionalBoolean)
+                            annotation.annotationType()
+                                    .getMethod("installInstrumentedAppInParent")
+                                    .invoke(annotation);
 
-                try {
-                    if (permissionContext == null) {
-                        permissionContext = TestApis.permissions().withoutAppOp(
-                                ensureDoesNotHaveAppOpAnnotation.value());
-                    } else {
-                        permissionContext = permissionContext.withoutAppOp(
-                                ensureDoesNotHaveAppOpAnnotation.value());
+                    OptionalBoolean switchedToParentUser = (OptionalBoolean)
+                            annotation.annotationType()
+                                    .getMethod(SWITCHED_TO_PARENT_USER).invoke(annotation);
+
+
+                    boolean dpcIsPrimary = false;
+                    Set<String> affiliationIds = null;
+                    if (requireRunOnProfileAnnotation.hasProfileOwner()) {
+                        dpcIsPrimary = (boolean)
+                                annotation.annotationType()
+                                        .getMethod(DPC_IS_PRIMARY).invoke(annotation);
+                        affiliationIds = new HashSet<>(Arrays.asList((String[])
+                                annotation.annotationType()
+                                        .getMethod(AFFILIATION_IDS).invoke(annotation)));
                     }
-                } catch (NeneException e) {
-                    failOrSkip("Error denying appOp: " + e,
-                            ensureDoesNotHaveAppOpAnnotation.failureMode());
-                }
-                continue;
-            }
 
-            if (annotation instanceof EnsureHasPermission) {
-                EnsureHasPermission ensureHasPermissionAnnotation =
-                        (EnsureHasPermission) annotation;
-
-                if (!meetsSdkVersionRequirements(
-                        ensureHasPermissionAnnotation.minVersion(),
-                        ensureHasPermissionAnnotation.maxVersion())) {
-                    Log.d(LOG_TAG,
-                            "Version " + SDK_INT +  " does not need to get permission "
-                                    + Arrays.toString(ensureHasPermissionAnnotation.value()));
+                    requireRunOnProfile(requireRunOnProfileAnnotation.value(),
+                            installInstrumentedAppInParent,
+                            requireRunOnProfileAnnotation.hasProfileOwner(),
+                            dpcIsPrimary, /* useParentInstance= */ false,
+                            switchedToParentUser, affiliationIds);
                     continue;
                 }
 
-                for (String permission : ensureHasPermissionAnnotation.value()) {
-                    ensureCanGetPermission(permission);
+                if (annotation instanceof EnsureTestAppInstalled) {
+                    EnsureTestAppInstalled ensureTestAppInstalledAnnotation =
+                            (EnsureTestAppInstalled) annotation;
+                    ensureTestAppInstalled(
+                            ensureTestAppInstalledAnnotation.key(),
+                            ensureTestAppInstalledAnnotation.packageName(),
+                            ensureTestAppInstalledAnnotation.onUser(),
+                            ensureTestAppInstalledAnnotation.isPrimary()
+                    );
+                    continue;
                 }
 
-                try {
-                    if (permissionContext == null) {
-                        permissionContext = TestApis.permissions().withPermission(
-                                ensureHasPermissionAnnotation.value());
+                if (annotation instanceof EnsureTestAppHasPermission) {
+                    EnsureTestAppHasPermission ensureTestAppHasPermissionAnnotation =
+                            (EnsureTestAppHasPermission) annotation;
+                    ensureTestAppHasPermission(
+                            ensureTestAppHasPermissionAnnotation.testAppKey(),
+                            ensureTestAppHasPermissionAnnotation.value(),
+                            ensureTestAppHasPermissionAnnotation.minVersion(),
+                            ensureTestAppHasPermissionAnnotation.maxVersion()
+                    );
+                    continue;
+                }
+
+                if (annotation instanceof EnsureTestAppHasAppOp) {
+                    EnsureTestAppHasAppOp ensureTestAppHasAppOpAnnotation =
+                            (EnsureTestAppHasAppOp) annotation;
+                    ensureTestAppHasAppOp(
+                            ensureTestAppHasAppOpAnnotation.testAppKey(),
+                            ensureTestAppHasAppOpAnnotation.value(),
+                            ensureTestAppHasAppOpAnnotation.minVersion(),
+                            ensureTestAppHasAppOpAnnotation.maxVersion()
+                    );
+                    continue;
+                }
+
+                if (annotation instanceof EnsureHasDelegate) {
+                    EnsureHasDelegate ensureHasDelegateAnnotation =
+                            (EnsureHasDelegate) annotation;
+                    ensureHasDelegate(
+                            ensureHasDelegateAnnotation.admin(),
+                            Arrays.asList(ensureHasDelegateAnnotation.scopes()),
+                            ensureHasDelegateAnnotation.isPrimary());
+                    continue;
+                }
+
+
+                if (annotation instanceof EnsureHasDeviceOwner) {
+                    EnsureHasDeviceOwner ensureHasDeviceOwnerAnnotation =
+                            (EnsureHasDeviceOwner) annotation;
+                    ensureHasDeviceOwner(ensureHasDeviceOwnerAnnotation.failureMode(),
+                            ensureHasDeviceOwnerAnnotation.isPrimary(),
+                            new HashSet<>(
+                                    Arrays.asList(
+                                            ensureHasDeviceOwnerAnnotation.affiliationIds())));
+                    continue;
+                }
+
+                if (annotation instanceof EnsureHasNoDelegate) {
+                    EnsureHasNoDelegate ensureHasNoDelegateAnnotation =
+                            (EnsureHasNoDelegate) annotation;
+                    ensureHasNoDelegate(ensureHasNoDelegateAnnotation.admin());
+                    continue;
+                }
+
+                if (annotation instanceof EnsureHasNoDeviceOwner) {
+                    ensureHasNoDeviceOwner();
+                    continue;
+                }
+
+                if (annotation instanceof RequireFeature) {
+                    RequireFeature requireFeatureAnnotation = (RequireFeature) annotation;
+                    requireFeature(
+                            requireFeatureAnnotation.value(),
+                            requireFeatureAnnotation.failureMode());
+                    continue;
+                }
+
+                if (annotation instanceof RequireDoesNotHaveFeature) {
+                    RequireDoesNotHaveFeature requireDoesNotHaveFeatureAnnotation =
+                            (RequireDoesNotHaveFeature) annotation;
+                    requireDoesNotHaveFeature(
+                            requireDoesNotHaveFeatureAnnotation.value(),
+                            requireDoesNotHaveFeatureAnnotation.failureMode());
+                    continue;
+                }
+
+                if (annotation instanceof EnsureHasProfileOwner) {
+                    EnsureHasProfileOwner ensureHasProfileOwnerAnnotation =
+                            (EnsureHasProfileOwner) annotation;
+                    ensureHasProfileOwner(ensureHasProfileOwnerAnnotation.onUser(),
+                            ensureHasProfileOwnerAnnotation.isPrimary(),
+                            ensureHasProfileOwnerAnnotation.useParentInstance(),
+                            new HashSet<>(Arrays.asList(
+                                    ensureHasProfileOwnerAnnotation.affiliationIds())));
+                    continue;
+                }
+
+                if (annotationType.equals(EnsureHasNoProfileOwner.class)) {
+                    EnsureHasNoProfileOwner ensureHasNoProfileOwnerAnnotation =
+                            (EnsureHasNoProfileOwner) annotation;
+                    ensureHasNoProfileOwner(ensureHasNoProfileOwnerAnnotation.onUser());
+                    continue;
+                }
+
+                if (annotation instanceof RequireUserSupported) {
+                    RequireUserSupported requireUserSupportedAnnotation =
+                            (RequireUserSupported) annotation;
+                    requireUserSupported(
+                            requireUserSupportedAnnotation.value(),
+                            requireUserSupportedAnnotation.failureMode());
+                    continue;
+                }
+
+                if (annotation instanceof RequireLowRamDevice) {
+                    RequireLowRamDevice requireLowRamDeviceAnnotation =
+                            (RequireLowRamDevice) annotation;
+                    requireLowRamDevice(requireLowRamDeviceAnnotation.reason(),
+                            requireLowRamDeviceAnnotation.failureMode());
+                    continue;
+                }
+
+                if (annotation instanceof RequireNotLowRamDevice) {
+                    RequireNotLowRamDevice requireNotLowRamDeviceAnnotation =
+                            (RequireNotLowRamDevice) annotation;
+                    requireNotLowRamDevice(requireNotLowRamDeviceAnnotation.reason(),
+                            requireNotLowRamDeviceAnnotation.failureMode());
+                    continue;
+                }
+
+                if (annotation instanceof RequireTargetSdkVersion) {
+                    RequireTargetSdkVersion requireTargetSdkVersionAnnotation =
+                            (RequireTargetSdkVersion) annotation;
+
+                    requireTargetSdkVersion(
+                            requireTargetSdkVersionAnnotation.min(),
+                            requireTargetSdkVersionAnnotation.max(),
+                            requireTargetSdkVersionAnnotation.failureMode());
+
+                    continue;
+                }
+
+                if (annotation instanceof RequireSdkVersion) {
+                    RequireSdkVersion requireSdkVersionAnnotation =
+                            (RequireSdkVersion) annotation;
+
+                    if (requireSdkVersionAnnotation.reason().isEmpty()) {
+                        requireSdkVersion(
+                                requireSdkVersionAnnotation.min(),
+                                requireSdkVersionAnnotation.max(),
+                                requireSdkVersionAnnotation.failureMode());
                     } else {
-                        permissionContext = permissionContext.withPermission(
-                                ensureHasPermissionAnnotation.value());
+                        requireSdkVersion(
+                                requireSdkVersionAnnotation.min(),
+                                requireSdkVersionAnnotation.max(),
+                                requireSdkVersionAnnotation.failureMode(),
+                                requireSdkVersionAnnotation.reason());
                     }
-                } catch (NeneException e) {
-                    failOrSkip("Error getting permission: " + e,
-                            ensureHasPermissionAnnotation.failureMode());
+
+                    continue;
                 }
-                continue;
-            }
 
-            if (annotation instanceof EnsureDoesNotHavePermission) {
-                EnsureDoesNotHavePermission ensureDoesNotHavePermission =
-                        (EnsureDoesNotHavePermission) annotation;
+                if (annotation instanceof RequirePackageInstalled) {
+                    RequirePackageInstalled requirePackageInstalledAnnotation =
+                            (RequirePackageInstalled) annotation;
+                    requirePackageInstalled(
+                            requirePackageInstalledAnnotation.value(),
+                            requirePackageInstalledAnnotation.onUser(),
+                            requirePackageInstalledAnnotation.failureMode());
+                    continue;
+                }
 
-                try {
-                    if (permissionContext == null) {
-                        permissionContext = TestApis.permissions().withoutPermission(
-                                ensureDoesNotHavePermission.value());
-                    } else {
-                        permissionContext = permissionContext.withoutPermission(
-                                ensureDoesNotHavePermission.value());
+                if (annotation instanceof RequirePackageNotInstalled) {
+                    RequirePackageNotInstalled requirePackageNotInstalledAnnotation =
+                            (RequirePackageNotInstalled) annotation;
+                    requirePackageNotInstalled(
+                            requirePackageNotInstalledAnnotation.value(),
+                            requirePackageNotInstalledAnnotation.onUser(),
+                            requirePackageNotInstalledAnnotation.failureMode()
+                    );
+                    continue;
+                }
+
+                if (annotation instanceof EnsurePackageNotInstalled) {
+                    EnsurePackageNotInstalled ensurePackageNotInstalledAnnotation =
+                            (EnsurePackageNotInstalled) annotation;
+                    ensurePackageNotInstalled(
+                            ensurePackageNotInstalledAnnotation.value(),
+                            ensurePackageNotInstalledAnnotation.onUser()
+                    );
+                    continue;
+                }
+
+                if (annotation instanceof RequireNotHeadlessSystemUserMode) {
+                    requireNotHeadlessSystemUserMode();
+                    continue;
+                }
+
+                if (annotation instanceof RequireHeadlessSystemUserMode) {
+                    requireHeadlessSystemUserMode();
+                    continue;
+                }
+
+                if (annotation instanceof EnsureCanGetPermission) {
+                    EnsureCanGetPermission ensureCanGetPermissionAnnotation =
+                            (EnsureCanGetPermission) annotation;
+
+                    if (!meetsSdkVersionRequirements(
+                            ensureCanGetPermissionAnnotation.minVersion(),
+                            ensureCanGetPermissionAnnotation.maxVersion())) {
+                        Log.d(LOG_TAG,
+                                "Version " + SDK_INT + " does not need to get permissions "
+                                        + Arrays.toString(
+                                        ensureCanGetPermissionAnnotation.value()));
+                        continue;
                     }
-                } catch (NeneException e) {
-                    failOrSkip("Error denying permission: " + e,
-                            ensureDoesNotHavePermission.failureMode());
+
+                    for (String permission : ensureCanGetPermissionAnnotation.value()) {
+                        ensureCanGetPermission(permission);
+                    }
+                    continue;
                 }
-                continue;
+
+                if (annotation instanceof EnsureHasAppOp) {
+                    EnsureHasAppOp ensureHasAppOpAnnotation = (EnsureHasAppOp) annotation;
+
+                    if (!meetsSdkVersionRequirements(
+                            ensureHasAppOpAnnotation.minVersion(),
+                            ensureHasAppOpAnnotation.maxVersion())) {
+                        Log.d(LOG_TAG,
+                                "Version " + SDK_INT + " does not need to get appOp "
+                                        + ensureHasAppOpAnnotation.value());
+                        continue;
+                    }
+
+                    try {
+                        if (permissionContext == null) {
+                            permissionContext = TestApis.permissions().withAppOp(
+                                    ensureHasAppOpAnnotation.value());
+                        } else {
+                            permissionContext = permissionContext.withAppOp(
+                                    ensureHasAppOpAnnotation.value());
+                        }
+                    } catch (NeneException e) {
+                        failOrSkip("Error getting appOp: " + e,
+                                ensureHasAppOpAnnotation.failureMode());
+                    }
+                    continue;
+                }
+
+                if (annotation instanceof EnsureDoesNotHaveAppOp) {
+                    EnsureDoesNotHaveAppOp ensureDoesNotHaveAppOpAnnotation =
+                            (EnsureDoesNotHaveAppOp) annotation;
+
+                    try {
+                        if (permissionContext == null) {
+                            permissionContext = TestApis.permissions().withoutAppOp(
+                                    ensureDoesNotHaveAppOpAnnotation.value());
+                        } else {
+                            permissionContext = permissionContext.withoutAppOp(
+                                    ensureDoesNotHaveAppOpAnnotation.value());
+                        }
+                    } catch (NeneException e) {
+                        failOrSkip("Error denying appOp: " + e,
+                                ensureDoesNotHaveAppOpAnnotation.failureMode());
+                    }
+                    continue;
+                }
+
+                if (annotation instanceof EnsureHasPermission) {
+                    EnsureHasPermission ensureHasPermissionAnnotation =
+                            (EnsureHasPermission) annotation;
+
+                    if (!meetsSdkVersionRequirements(
+                            ensureHasPermissionAnnotation.minVersion(),
+                            ensureHasPermissionAnnotation.maxVersion())) {
+                        Log.d(LOG_TAG,
+                                "Version " + SDK_INT + " does not need to get permission "
+                                        + Arrays.toString(ensureHasPermissionAnnotation.value()));
+                        continue;
+                    }
+
+                    for (String permission : ensureHasPermissionAnnotation.value()) {
+                        ensureCanGetPermission(permission);
+                    }
+
+                    try {
+                        if (permissionContext == null) {
+                            permissionContext = TestApis.permissions().withPermission(
+                                    ensureHasPermissionAnnotation.value());
+                        } else {
+                            permissionContext = permissionContext.withPermission(
+                                    ensureHasPermissionAnnotation.value());
+                        }
+                    } catch (NeneException e) {
+                        failOrSkip("Error getting permission: " + e,
+                                ensureHasPermissionAnnotation.failureMode());
+                    }
+                    continue;
+                }
+
+                if (annotation instanceof EnsureDoesNotHavePermission) {
+                    EnsureDoesNotHavePermission ensureDoesNotHavePermission =
+                            (EnsureDoesNotHavePermission) annotation;
+
+                    try {
+                        if (permissionContext == null) {
+                            permissionContext = TestApis.permissions().withoutPermission(
+                                    ensureDoesNotHavePermission.value());
+                        } else {
+                            permissionContext = permissionContext.withoutPermission(
+                                    ensureDoesNotHavePermission.value());
+                        }
+                    } catch (NeneException e) {
+                        failOrSkip("Error denying permission: " + e,
+                                ensureDoesNotHavePermission.failureMode());
+                    }
+                    continue;
+                }
+
+                if (annotation instanceof EnsureScreenIsOn) {
+                    ensureScreenIsOn();
+                    continue;
+                }
+
+                if (annotation instanceof EnsurePasswordSet) {
+                    EnsurePasswordSet ensurePasswordSetAnnotation =
+                            (EnsurePasswordSet) annotation;
+                    ensurePasswordSet(
+                            ensurePasswordSetAnnotation.forUser(),
+                            ensurePasswordSetAnnotation.password());
+                    continue;
+                }
+
+                if (annotation instanceof EnsurePasswordNotSet) {
+                    EnsurePasswordNotSet ensurePasswordNotSetAnnotation =
+                            (EnsurePasswordNotSet) annotation;
+                    ensurePasswordNotSet(ensurePasswordNotSetAnnotation.forUser());
+                    continue;
+                }
+
+                if (annotation instanceof OtherUser) {
+                    OtherUser otherUserAnnotation = (OtherUser) annotation;
+                    mOtherUserType = otherUserAnnotation.value();
+                    continue;
+                }
+
+                if (annotation instanceof EnsureBluetoothEnabled) {
+                    ensureBluetoothEnabled();
+                    continue;
+                }
+
+                if (annotation instanceof EnsureBluetoothDisabled) {
+                    ensureBluetoothDisabled();
+                    continue;
+                }
             }
 
-            if (annotation instanceof EnsureScreenIsOn) {
-                ensureScreenIsOn();
-                continue;
+            requireSdkVersion(/* min= */ mMinSdkVersionCurrentTest,
+                    /* max= */ Integer.MAX_VALUE, FailureMode.SKIP);
+
+            if (isTest && mPermissionsInstrumentationPackage != null
+                    && !mHasRequirePermissionInstrumentation) {
+                requireNoPermissionsInstrumentation("No reason to use instrumentation");
             }
 
-            if (annotation instanceof EnsurePasswordSet) {
-                EnsurePasswordSet ensurePasswordSetAnnotation =
-                        (EnsurePasswordSet) annotation;
-                ensurePasswordSet(
-                        ensurePasswordSetAnnotation.forUser(),
-                        ensurePasswordSetAnnotation.password());
-                continue;
-            }
-
-            if (annotation instanceof EnsurePasswordNotSet) {
-                EnsurePasswordNotSet ensurePasswordNotSetAnnotation =
-                        (EnsurePasswordNotSet) annotation;
-                ensurePasswordNotSet(ensurePasswordNotSetAnnotation.forUser());
-                continue;
-            }
-
-            if (annotation instanceof OtherUser) {
-                OtherUser otherUserAnnotation = (OtherUser) annotation;
-                mOtherUserType = otherUserAnnotation.value();
-                continue;
-            }
-
-            if (annotation instanceof EnsureBluetoothEnabled) {
-                ensureBluetoothEnabled();
-                continue;
-            }
-
-            if (annotation instanceof EnsureBluetoothDisabled) {
-                ensureBluetoothDisabled();
-                continue;
-            }
-        }
-
-        requireSdkVersion(/* min= */ mMinSdkVersionCurrentTest,
-                /* max= */ Integer.MAX_VALUE, FailureMode.SKIP);
-
-        if (isTest && mPermissionsInstrumentationPackage != null
-                && !mHasRequirePermissionInstrumentation) {
-            requireNoPermissionsInstrumentation("No reason to use instrumentation");
-        }
-
-        return permissionContext;
+            return permissionContext;
+        });
     }
 
     private List<Annotation> getAnnotations(Description description) {
-        if (mUsingBedsteadJUnit4 && description.isTest()) {
-            // The annotations are already exploded for tests
-            return new ArrayList<>(description.getAnnotations());
-        }
+        return mLogger.method("getAnnotations", description, () -> {
+            if (mUsingBedsteadJUnit4 && description.isTest()) {
+                // The annotations are already exploded for tests
+                return new ArrayList<>(description.getAnnotations());
+            }
 
-        // Otherwise we should build a new collection by recursively gathering annotations
-        // if we find any which don't work without the runner we should error and fail the test
-        List<Annotation> annotations = new ArrayList<>();
+            // Otherwise we should build a new collection by recursively gathering annotations
+            // if we find any which don't work without the runner we should error and fail the test
+            List<Annotation> annotations = new ArrayList<>();
 
-        if (description.isTest()) {
-            annotations =
-                    new ArrayList<>(Arrays.asList(description.getTestClass().getAnnotations()));
-        }
+            if (description.isTest()) {
+                annotations =
+                        new ArrayList<>(Arrays.asList(description.getTestClass().getAnnotations()));
+            }
 
-        annotations.addAll(description.getAnnotations());
+            annotations.addAll(description.getAnnotations());
 
-        checkAnnotations(annotations);
+            checkAnnotations(annotations);
 
-        BedsteadJUnit4.resolveRecursiveAnnotations(annotations,
-                /* parameterizedAnnotation= */ null);
+            BedsteadJUnit4.resolveRecursiveAnnotations(annotations,
+                    /* parameterizedAnnotation= */ null);
 
-        checkAnnotations(annotations);
+            checkAnnotations(annotations);
 
-        return annotations;
+            return annotations;
+        });
     }
 
     private void checkAnnotations(Collection<Annotation> annotations) {
-        for (Annotation annotation : annotations) {
-            if (annotation.annotationType().getAnnotation(RequiresBedsteadJUnit4.class) != null
-                    || annotation.annotationType().getAnnotation(
-                            ParameterizedAnnotation.class) != null) {
-                throw new AssertionFailedError("Test is annotated "
-                        + annotation.annotationType().getSimpleName()
-                        + " which requires using the BedsteadJUnit4 test runner");
+        mLogger.method("checkAnnotations", annotations, () -> {
+            for (Annotation annotation : annotations) {
+                if (annotation.annotationType().getAnnotation(RequiresBedsteadJUnit4.class) != null
+                        || annotation.annotationType().getAnnotation(
+                        ParameterizedAnnotation.class) != null) {
+                    throw new AssertionFailedError("Test is annotated "
+                            + annotation.annotationType().getSimpleName()
+                            + " which requires using the BedsteadJUnit4 test runner");
+                }
             }
-        }
+        });
     }
 
     private Statement applySuite(Statement base, Description description) {
-        return new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-                checkValidAnnotations(description);
+        return mLogger.method("applySuite", base, description, () -> {
+            return new Statement() {
+                @Override
+                public void evaluate() throws Throwable {
+                    checkValidAnnotations(description);
 
-                TestClass testClass = new TestClass(description.getTestClass());
+                    TestClass testClass = new TestClass(description.getTestClass());
 
-                PermissionContextImpl permissionContext = null;
+                    PermissionContextImpl permissionContext = null;
 
-                if (mSkipTests || mFailTests) {
-                    Log.d(LOG_TAG, "Skipping suite setup and teardown due to skipTests: "
-                            + mSkipTests + ", failTests: " + mFailTests);
-                    base.evaluate();
-                    return;
-                }
+                    if (mSkipTests || mFailTests) {
+                        Log.d(LOG_TAG, "Skipping suite setup and teardown due to skipTests: "
+                                + mSkipTests + ", failTests: " + mFailTests);
+                        base.evaluate();
+                        return;
+                    }
 
-                Log.d(LOG_TAG, "Preparing state for suite " + description.getClassName());
+                    Log.d(LOG_TAG, "Preparing state for suite " + description.getClassName());
 
-                Tags.clearTags();
-                Tags.addTag(Tags.USES_DEVICESTATE);
-                if (TestApis.packages().instrumented().isInstantApp()) {
-                    Tags.addTag(Tags.INSTANT_APP);
-                }
-
-                try {
-                    TestApis.users().setStopBgUsersOnSwitch(STOP_USER_ON_SWITCH_FALSE);
+                    Tags.clearTags();
+                    Tags.addTag(Tags.USES_DEVICESTATE);
+                    if (TestApis.packages().instrumented().isInstantApp()) {
+                        Tags.addTag(Tags.INSTANT_APP);
+                    }
 
                     try {
-                        List<Annotation> annotations =
-                                new ArrayList<>(getAnnotations(description));
-                        permissionContext = applyAnnotations(annotations, /* isTest= */ false);
-                    } catch (AssumptionViolatedException e) {
-                        Log.i(LOG_TAG, "Assumption failed during class setup", e);
-                        mSkipTests = true;
-                        mSkipTestsReason = e.getMessage();
-                    } catch (AssertionError e) {
-                        Log.i(LOG_TAG, "Assertion failed during class setup", e);
-                        mFailTests = true;
-                        mFailTestsReason = e.getMessage();
+                        TestApis.users().setStopBgUsersOnSwitch(STOP_USER_ON_SWITCH_FALSE);
+
+                        try {
+                            List<Annotation> annotations =
+                                    new ArrayList<>(getAnnotations(description));
+                            permissionContext = applyAnnotations(annotations, /* isTest= */ false);
+                        } catch (AssumptionViolatedException e) {
+                            Log.i(LOG_TAG, "Assumption failed during class setup", e);
+                            mSkipTests = true;
+                            mSkipTestsReason = e.getMessage();
+                        } catch (AssertionError e) {
+                            Log.i(LOG_TAG, "Assertion failed during class setup", e);
+                            mFailTests = true;
+                            mFailTestsReason = e.getMessage();
+                        }
+
+                        Log.d(LOG_TAG,
+                                "Finished preparing state for suite "
+                                        + description.getClassName());
+
+                        if (!mSkipTests && !mFailTests) {
+                            // Tests may be skipped during the class setup
+                            runAnnotatedMethods(testClass, BeforeClass.class);
+                        }
+
+                        base.evaluate();
+                    } finally {
+                        runAnnotatedMethods(testClass, AfterClass.class);
+
+                        if (permissionContext != null) {
+                            permissionContext.close();
+                        }
+
+                        if (!mSkipClassTeardown) {
+                            teardownShareableState();
+                        }
+
+                        TestApis.users().setStopBgUsersOnSwitch(STOP_USER_ON_SWITCH_DEFAULT);
                     }
-
-                    Log.d(LOG_TAG,
-                            "Finished preparing state for suite "
-                                    + description.getClassName());
-
-                    if (!mSkipTests && !mFailTests) {
-                        // Tests may be skipped during the class setup
-                        runAnnotatedMethods(testClass, BeforeClass.class);
-                    }
-
-                    base.evaluate();
-                } finally {
-                    runAnnotatedMethods(testClass, AfterClass.class);
-
-                    if (permissionContext != null) {
-                        permissionContext.close();
-                    }
-
-                    if (!mSkipClassTeardown) {
-                        teardownShareableState();
-                    }
-
-                    TestApis.users().setStopBgUsersOnSwitch(STOP_USER_ON_SWITCH_DEFAULT);
                 }
-            }
-        };
+            };
+        });
     }
 
     private static final Map<Class<? extends Annotation>, Class<? extends Annotation>>
             BANNED_ANNOTATIONS_TO_REPLACEMENTS = getBannedAnnotationsToReplacements();
+
     private static Map<
             Class<? extends Annotation>,
             Class<? extends Annotation>> getBannedAnnotationsToReplacements() {
@@ -917,206 +959,243 @@
     }
 
     private void checkValidAnnotations(Description classDescription) {
-        for (Method method : classDescription.getTestClass().getMethods()) {
-            for (Map.Entry<
-                    Class<? extends Annotation>,
-                    Class<? extends Annotation>> bannedAnnotation
-                    : BANNED_ANNOTATIONS_TO_REPLACEMENTS.entrySet()) {
-                if (method.isAnnotationPresent(bannedAnnotation.getKey())) {
-                    throw new IllegalStateException("Do not use "
-                            + bannedAnnotation.getKey().getCanonicalName()
-                            + " when using DeviceState, replace with "
-                            + bannedAnnotation.getValue().getCanonicalName());
+        mLogger.method("checkValidAnnotations", classDescription, () -> {
+            for (Method method : classDescription.getTestClass().getMethods()) {
+                for (Map.Entry<
+                        Class<? extends Annotation>,
+                        Class<? extends Annotation>> bannedAnnotation
+                        : BANNED_ANNOTATIONS_TO_REPLACEMENTS.entrySet()) {
+                    if (method.isAnnotationPresent(bannedAnnotation.getKey())) {
+                        throw new IllegalStateException("Do not use "
+                                + bannedAnnotation.getKey().getCanonicalName()
+                                + " when using DeviceState, replace with "
+                                + bannedAnnotation.getValue().getCanonicalName());
+                    }
+                }
+
+                if (method.getAnnotation(BeforeClass.class) != null
+                        || method.getAnnotation(AfterClass.class) != null) {
+                    checkPublicStaticVoidNoArgs(method);
                 }
             }
-
-            if (method.getAnnotation(BeforeClass.class) != null
-                    || method.getAnnotation(AfterClass.class) != null) {
-                checkPublicStaticVoidNoArgs(method);
-            }
-        }
+        });
     }
 
     private void checkPublicStaticVoidNoArgs(Method method) {
-        if (method.getParameterTypes().length > 0) {
-            throw new IllegalStateException(
-                    "Method " + method.getName() + " should have no parameters");
-        }
-        if (method.getReturnType() != Void.TYPE) {
-            throw new IllegalStateException("Method " + method.getName() + "() should be void");
-        }
-        if (!Modifier.isStatic(method.getModifiers())) {
-            throw new IllegalStateException("Method " + method.getName() + "() should be static");
-        }
-        if (!Modifier.isPublic(method.getModifiers())) {
-            throw new IllegalStateException("Method " + method.getName() + "() should be public");
-        }
+        mLogger.method("checkPublicStaticVoidNoArgs", method, () -> {
+            if (method.getParameterTypes().length > 0) {
+                throw new IllegalStateException(
+                        "Method " + method.getName() + " should have no parameters");
+            }
+            if (method.getReturnType() != Void.TYPE) {
+                throw new IllegalStateException("Method " + method.getName() + "() should be void");
+            }
+            if (!Modifier.isStatic(method.getModifiers())) {
+                throw new IllegalStateException(
+                        "Method " + method.getName() + "() should be static");
+            }
+            if (!Modifier.isPublic(method.getModifiers())) {
+                throw new IllegalStateException(
+                        "Method " + method.getName() + "() should be public");
+            }
+        });
     }
 
     private void runAnnotatedMethods(
             TestClass testClass, Class<? extends Annotation> annotation) throws Throwable {
-
-        List<FrameworkMethod> methods = new ArrayList<>(testClass.getAnnotatedMethods(annotation));
-        Collections.reverse(methods);
-        for (FrameworkMethod method : methods) {
-            try {
-                method.invokeExplosively(testClass.getJavaClass());
-            } catch (InvocationTargetException e) {
-                throw e.getCause();
+        mLogger.method(Throwable.class, "runAnnotatedMethods", testClass, annotation, () -> {
+            List<FrameworkMethod> methods = new ArrayList<>(
+                    testClass.getAnnotatedMethods(annotation));
+            Collections.reverse(methods);
+            for (FrameworkMethod method : methods) {
+                try {
+                    method.invokeExplosively(testClass.getJavaClass());
+                } catch (InvocationTargetException e) {
+                    throw e.getCause();
+                }
             }
-        }
+        });
     }
 
     private void requireRunOnUser(String[] userTypes, OptionalBoolean switchedToUser) {
-        UserReference instrumentedUser = TestApis.users().instrumented();
+        mLogger.method("requireRunOnUser", userTypes, switchedToUser, () -> {
+            UserReference instrumentedUser = TestApis.users().instrumented();
 
-        assumeTrue("This test only runs on users of type " + Arrays.toString(userTypes),
-                Arrays.stream(userTypes).anyMatch(i -> i.equals(instrumentedUser.type().name())));
+            assumeTrue("This test only runs on users of type " + Arrays.toString(userTypes),
+                    Arrays.stream(userTypes).anyMatch(
+                            i -> i.equals(instrumentedUser.type().name())));
 
-        mUsers.put(instrumentedUser.type(), instrumentedUser);
+            mUsers.put(instrumentedUser.type(), instrumentedUser);
 
-        ensureSwitchedToUser(switchedToUser, instrumentedUser);
+            ensureSwitchedToUser(switchedToUser, instrumentedUser);
+        });
     }
 
     private void requireRunOnProfile(String userType,
             OptionalBoolean installInstrumentedAppInParent,
             boolean hasProfileOwner, boolean dpcIsPrimary, boolean useParentInstance,
             OptionalBoolean switchedToParentUser, Set<String> affiliationIds) {
-        UserReference instrumentedUser = TestApis.users().instrumented();
+        mLogger.method("requireRunOnProfile", userType, installInstrumentedAppInParent,
+                hasProfileOwner, dpcIsPrimary, useParentInstance, switchedToParentUser,
+                affiliationIds, () -> {
+                    UserReference instrumentedUser = TestApis.users().instrumented();
 
-        assumeTrue("This test only runs on users of type " + userType,
-                instrumentedUser.type().name().equals(userType));
+                    assumeTrue("This test only runs on users of type " + userType,
+                            instrumentedUser.type().name().equals(userType));
 
-        if (!mProfiles.containsKey(instrumentedUser.type())) {
-            mProfiles.put(instrumentedUser.type(), new HashMap<>());
-        }
+                    if (!mProfiles.containsKey(instrumentedUser.type())) {
+                        mProfiles.put(instrumentedUser.type(), new HashMap<>());
+                    }
 
-        mProfiles.get(instrumentedUser.type()).put(instrumentedUser.parent(), instrumentedUser);
+                    mProfiles.get(instrumentedUser.type()).put(instrumentedUser.parent(),
+                            instrumentedUser);
 
-        if (installInstrumentedAppInParent.equals(OptionalBoolean.TRUE)) {
-            TestApis.packages().find(sContext.getPackageName()).installExisting(
-                    instrumentedUser.parent());
-        } else if (installInstrumentedAppInParent.equals(OptionalBoolean.FALSE)) {
-            TestApis.packages().find(sContext.getPackageName()).uninstall(
-                    instrumentedUser.parent());
-        }
+                    if (installInstrumentedAppInParent.equals(OptionalBoolean.TRUE)) {
+                        TestApis.packages().find(sContext.getPackageName()).installExisting(
+                                instrumentedUser.parent());
+                    } else if (installInstrumentedAppInParent.equals(OptionalBoolean.FALSE)) {
+                        TestApis.packages().find(sContext.getPackageName()).uninstall(
+                                instrumentedUser.parent());
+                    }
 
-        if (hasProfileOwner) {
-            ensureHasProfileOwner(
-                    instrumentedUser, dpcIsPrimary, useParentInstance, affiliationIds);
-        } else {
-            ensureHasNoProfileOwner(instrumentedUser);
-        }
+                    if (hasProfileOwner) {
+                        ensureHasProfileOwner(
+                                instrumentedUser, dpcIsPrimary, useParentInstance, affiliationIds);
+                    } else {
+                        ensureHasNoProfileOwner(instrumentedUser);
+                    }
 
-        ensureSwitchedToUser(switchedToParentUser, instrumentedUser.parent());
+                    ensureSwitchedToUser(switchedToParentUser, instrumentedUser.parent());
+                });
     }
 
     private void ensureSwitchedToUser(OptionalBoolean switchedtoUser, UserReference user) {
-        if (switchedtoUser.equals(OptionalBoolean.TRUE)) {
-            switchToUser(user);
-        } else if (switchedtoUser.equals(OptionalBoolean.FALSE)) {
-            switchFromUser(user);
-        }
+        mLogger.method("ensureSwitchedToUser", switchedtoUser, user, () -> {
+            if (switchedtoUser.equals(OptionalBoolean.TRUE)) {
+                switchToUser(user);
+            } else if (switchedtoUser.equals(OptionalBoolean.FALSE)) {
+                switchFromUser(user);
+            }
+        });
     }
 
     private void requireFeature(String feature, FailureMode failureMode) {
-        checkFailOrSkip("Device must have feature " + feature,
-                TestApis.packages().features().contains(feature), failureMode);
+        mLogger.method("requireFeature", feature, failureMode, () -> {
+            checkFailOrSkip("Device must have feature " + feature,
+                    TestApis.packages().features().contains(feature), failureMode);
+        });
     }
 
     private void requireDoesNotHaveFeature(String feature, FailureMode failureMode) {
-        checkFailOrSkip("Device must not have feature " + feature,
-                !TestApis.packages().features().contains(feature), failureMode);
+        mLogger.method("requireDoesNotHaveFeature", feature, failureMode, () -> {
+            checkFailOrSkip("Device must not have feature " + feature,
+                    !TestApis.packages().features().contains(feature), failureMode);
+        });
     }
 
     private void requireNoPermissionsInstrumentation(String reason) {
-        boolean instrumentingPermissions =
-                TestApis.context()
-                        .instrumentedContext().getPackageName()
-                        .equals(mPermissionsInstrumentationPackage);
+        mLogger.method("requireNoPermissionsInstrumentation", reason, () -> {
+            boolean instrumentingPermissions =
+                    TestApis.context()
+                            .instrumentedContext().getPackageName()
+                            .equals(mPermissionsInstrumentationPackage);
 
-        checkFailOrSkip(
-                "This test never runs using permissions instrumentation on this version"
-                        + " of Android: " + reason,
-                !instrumentingPermissions,
-                FailureMode.SKIP
-        );
+            checkFailOrSkip(
+                    "This test never runs using permissions instrumentation on this version"
+                            + " of Android: " + reason,
+                    !instrumentingPermissions,
+                    FailureMode.SKIP
+            );
+        });
     }
 
     private void requirePermissionsInstrumentation(String reason) {
-        mHasRequirePermissionInstrumentation = true;
-        boolean instrumentingPermissions =
-                TestApis.context()
-                        .instrumentedContext().getPackageName()
-                        .equals(mPermissionsInstrumentationPackage);
+        mLogger.method("requirePermissionsInstrumentation", reason, () -> {
+            mHasRequirePermissionInstrumentation = true;
+            boolean instrumentingPermissions =
+                    TestApis.context()
+                            .instrumentedContext().getPackageName()
+                            .equals(mPermissionsInstrumentationPackage);
 
-        checkFailOrSkip(
-                "This test only runs when using permissions instrumentation on this"
-                        + " version of Android: " + reason,
-                instrumentingPermissions,
-                FailureMode.SKIP
-        );
+            checkFailOrSkip(
+                    "This test only runs when using permissions instrumentation on this"
+                            + " version of Android: " + reason,
+                    instrumentingPermissions,
+                    FailureMode.SKIP
+            );
+        });
     }
 
     private void requireTargetSdkVersion(
             int min, int max, FailureMode failureMode) {
+        mLogger.method("requireTargetSdkVersion", min, max, failureMode, () -> {
+            int targetSdkVersion = TestApis.packages().instrumented().targetSdkVersion();
 
-        int targetSdkVersion = TestApis.packages().instrumented().targetSdkVersion();
-
-        checkFailOrSkip(
-                "TargetSdkVersion must be between " + min + " and " + max
-                        + " (inclusive) (version is " + targetSdkVersion + ")",
-                min <= targetSdkVersion && max >= targetSdkVersion,
-                failureMode
-        );
+            checkFailOrSkip(
+                    "TargetSdkVersion must be between " + min + " and " + max
+                            + " (inclusive) (version is " + targetSdkVersion + ")",
+                    min <= targetSdkVersion && max >= targetSdkVersion,
+                    failureMode
+            );
+        });
     }
 
     private void requireSdkVersion(int min, int max, FailureMode failureMode) {
-        requireSdkVersion(min, max, failureMode,
-                "Sdk version must be between " + min +  " and " + max + " (inclusive)");
+        mLogger.method("requireSdkVersion", min, max, failureMode, () -> {
+            requireSdkVersion(min, max, failureMode,
+                    "Sdk version must be between " + min + " and " + max + " (inclusive)");
+        });
     }
 
     private void requireSdkVersion(
             int min, int max, FailureMode failureMode, String failureMessage) {
-        mMinSdkVersionCurrentTest = min;
-        checkFailOrSkip(
-                failureMessage + " (version is " + SDK_INT + ")",
-                meetsSdkVersionRequirements(min, max),
-                failureMode
-        );
+        mLogger.method("requireSdkVersion", min, max, failureMode, failureMessage, () -> {
+            mMinSdkVersionCurrentTest = min;
+            checkFailOrSkip(
+                    failureMessage + " (version is " + SDK_INT + ")",
+                    meetsSdkVersionRequirements(min, max),
+                    failureMode
+            );
+        });
     }
 
     private com.android.bedstead.nene.users.UserType requireUserSupported(
             String userType, FailureMode failureMode) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                TestApis.users().supportedType(userType);
+        return mLogger.method("requireUserSupported", userType, failureMode, () -> {
+            com.android.bedstead.nene.users.UserType resolvedUserType =
+                    TestApis.users().supportedType(userType);
 
-        checkFailOrSkip(
-                "Device must support user type " + userType
-                + " only supports: " + TestApis.users().supportedTypes(),
-                resolvedUserType != null, failureMode);
+            checkFailOrSkip(
+                    "Device must support user type " + userType
+                            + " only supports: " + TestApis.users().supportedTypes(),
+                    resolvedUserType != null, failureMode);
 
-        return resolvedUserType;
+            return resolvedUserType;
+        });
     }
 
     private void checkFailOrSkip(String message, boolean value, FailureMode failureMode) {
-        if (failureMode.equals(FailureMode.FAIL)) {
-            assertWithMessage(message).that(value).isTrue();
-        } else if (failureMode.equals(FailureMode.SKIP)) {
-            assumeTrue(message, value);
-        } else {
-            throw new IllegalStateException("Unknown failure mode: " + failureMode);
-        }
+        mLogger.method("checkFailOrSkip", message, value, failureMode, () -> {
+            if (failureMode.equals(FailureMode.FAIL)) {
+                assertWithMessage(message).that(value).isTrue();
+            } else if (failureMode.equals(FailureMode.SKIP)) {
+                assumeTrue(message, value);
+            } else {
+                throw new IllegalStateException("Unknown failure mode: " + failureMode);
+            }
+        });
     }
 
     private void failOrSkip(String message, FailureMode failureMode) {
-        if (failureMode.equals(FailureMode.FAIL)) {
-            throw new AssertionError(message);
-        } else if (failureMode.equals(FailureMode.SKIP)) {
-            throw new AssumptionViolatedException(message);
-        } else {
-            throw new IllegalStateException("Unknown failure mode: " + failureMode);
-        }
+        mLogger.method("failOrSkip", message, failureMode, () -> {
+            if (failureMode.equals(FailureMode.FAIL)) {
+                throw new AssertionError(message);
+            } else if (failureMode.equals(FailureMode.SKIP)) {
+                throw new AssumptionViolatedException(message);
+            } else {
+                throw new IllegalStateException("Unknown failure mode: " + failureMode);
+            }
+        });
     }
 
     private static final String LOG_TAG = "DeviceState";
@@ -1155,8 +1234,10 @@
      * @throws IllegalStateException if there is no harrier-managed work profile
      */
     public UserReference workProfile() {
-        // Work profiles are currently only supported on the primary user
-        return workProfile(/* forUser= */ UserType.PRIMARY_USER);
+        return mLogger.method("workProfile", () -> {
+            // Work profiles are currently only supported on the primary user
+            return workProfile(/* forUser= */ UserType.PRIMARY_USER);
+        });
     }
 
     /**
@@ -1168,7 +1249,9 @@
      * @throws IllegalStateException if there is no harrier-managed work profile for the given user
      */
     public UserReference workProfile(UserType forUser) {
-        return workProfile(resolveUserTypeToUser(forUser));
+        return mLogger.method("workProfile", forUser, () -> {
+            return workProfile(resolveUserTypeToUser(forUser));
+        });
     }
 
     /**
@@ -1180,7 +1263,9 @@
      * @throws IllegalStateException if there is no harrier-managed work profile for the given user
      */
     public UserReference workProfile(UserReference forUser) {
-        return profile(MANAGED_PROFILE_TYPE_NAME, forUser);
+        return mLogger.method("workProfile", forUser, () -> {
+            return profile(MANAGED_PROFILE_TYPE_NAME, forUser);
+        });
     }
 
     /**
@@ -1192,7 +1277,9 @@
      * @throws IllegalStateException if there is no harrier-managed profile for the given user
      */
     public UserReference profile(String profileType, UserType forUser) {
-        return profile(profileType, resolveUserTypeToUser(forUser));
+        return mLogger.method("profile", profileType, forUser, () -> {
+            return profile(profileType, resolveUserTypeToUser(forUser));
+        });
     }
 
     /**
@@ -1207,7 +1294,9 @@
      * @throws IllegalStateException if there is no harrier-managed profile
      */
     public UserReference profile(String profileType) {
-        return profile(profileType, /* forUser= */ UserType.INSTRUMENTED_USER);
+        return mLogger.method("profile", profileType, () -> {
+            return profile(profileType, /* forUser= */ UserType.INSTRUMENTED_USER);
+        });
     }
 
     /**
@@ -1219,15 +1308,17 @@
      * @throws IllegalStateException if there is no harrier-managed profile for the given user
      */
     public UserReference profile(String profileType, UserReference forUser) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                TestApis.users().supportedType(profileType);
+        return mLogger.method("profile", profileType, forUser, () -> {
+            com.android.bedstead.nene.users.UserType resolvedUserType =
+                    TestApis.users().supportedType(profileType);
 
-        if (resolvedUserType == null) {
-            throw new IllegalStateException("Can not have a profile of type " + profileType
-                    + " as they are not supported on this device");
-        }
+            if (resolvedUserType == null) {
+                throw new IllegalStateException("Can not have a profile of type " + profileType
+                        + " as they are not supported on this device");
+            }
 
-        return profile(resolvedUserType, forUser);
+            return profile(resolvedUserType, forUser);
+        });
     }
 
     /**
@@ -1240,26 +1331,29 @@
      */
     public UserReference profile(
             com.android.bedstead.nene.users.UserType userType, UserReference forUser) {
-        if (userType == null || forUser == null) {
-            throw new NullPointerException();
-        }
-
-        if (!mProfiles.containsKey(userType) || !mProfiles.get(userType).containsKey(forUser)) {
-            UserReference parentUser = TestApis.users().instrumented().parent();
-
-            if (parentUser != null) {
-                if (mProfiles.containsKey(userType)
-                        && mProfiles.get(userType).containsKey(parentUser)) {
-                    return mProfiles.get(userType).get(parentUser);
-                }
+        return mLogger.method("profile", userType, forUser, () -> {
+            if (userType == null || forUser == null) {
+                throw new NullPointerException();
             }
 
-            throw new IllegalStateException(
-                    "No harrier-managed profile of type " + userType + ". This method should only"
-                            + " be used when Harrier has been used to create the profile.");
-        }
+            if (!mProfiles.containsKey(userType) || !mProfiles.get(userType).containsKey(forUser)) {
+                UserReference parentUser = TestApis.users().instrumented().parent();
 
-        return mProfiles.get(userType).get(forUser);
+                if (parentUser != null) {
+                    if (mProfiles.containsKey(userType)
+                            && mProfiles.get(userType).containsKey(parentUser)) {
+                        return mProfiles.get(userType).get(parentUser);
+                    }
+                }
+
+                throw new IllegalStateException(
+                        "No harrier-managed profile of type " + userType
+                                + ". This method should only"
+                                + " be used when Harrier has been used to create the profile.");
+            }
+
+            return mProfiles.get(userType).get(forUser);
+        });
     }
 
     /**
@@ -1271,7 +1365,8 @@
      * @throws IllegalStateException if there is no harrier-managed tv profile
      */
     public UserReference tvProfile() {
-        return tvProfile(/* forUser= */ UserType.INSTRUMENTED_USER);
+        return mLogger.method("tvProfile", () ->
+                tvProfile(/* forUser= */ UserType.INSTRUMENTED_USER));
     }
 
     /**
@@ -1283,7 +1378,8 @@
      * @throws IllegalStateException if there is no harrier-managed tv profile
      */
     public UserReference tvProfile(UserType forUser) {
-        return tvProfile(resolveUserTypeToUser(forUser));
+        return mLogger.method("tvProfile", forUser, () ->
+                tvProfile(resolveUserTypeToUser(forUser)));
     }
 
     /**
@@ -1295,16 +1391,18 @@
      * @throws IllegalStateException if there is no harrier-managed tv profile
      */
     public UserReference tvProfile(UserReference forUser) {
-        return profile(TV_PROFILE_TYPE_NAME, forUser);
+        return mLogger.method("tvProfile", forUser, () ->
+                profile(TV_PROFILE_TYPE_NAME, forUser));
     }
 
     /**
      * Get the user ID of the first human user on the device.
      */
     public UserReference primaryUser() {
-        return TestApis.users().all()
-                .stream().filter(UserReference::isPrimary).findFirst()
-                .orElseThrow(IllegalStateException::new);
+        return mLogger.method("primaryUser", () ->
+                TestApis.users().all()
+                        .stream().filter(UserReference::isPrimary).findFirst()
+                        .orElseThrow(IllegalStateException::new));
     }
 
     /**
@@ -1316,7 +1414,7 @@
      * @throws IllegalStateException if there is no harrier-managed secondary user
      */
     public UserReference secondaryUser() {
-        return user(SECONDARY_USER_TYPE_NAME);
+        return mLogger.method("secondaryUser", () -> user(SECONDARY_USER_TYPE_NAME));
     }
 
     /**
@@ -1325,11 +1423,13 @@
      * @throws IllegalStateException if there is no "other" user
      */
     public UserReference otherUser() {
-        if (mOtherUserType == null) {
-            throw new IllegalStateException("No other user specified. Use @OtherUser");
-        }
+        return mLogger.method("otherUser", () -> {
+            if (mOtherUserType == null) {
+                throw new IllegalStateException("No other user specified. Use @OtherUser");
+            }
 
-        return resolveUserTypeToUser(mOtherUserType);
+            return resolveUserTypeToUser(mOtherUserType);
+        });
     }
 
     /**
@@ -1341,15 +1441,17 @@
      * @throws IllegalStateException if there is no harrier-managed user of the correct type
      */
     public UserReference user(String userType) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                TestApis.users().supportedType(userType);
+        return mLogger.method("user", userType, () -> {
+            com.android.bedstead.nene.users.UserType resolvedUserType =
+                    TestApis.users().supportedType(userType);
 
-        if (resolvedUserType == null) {
-            throw new IllegalStateException("Can not have a user of type " + userType
-                    + " as they are not supported on this device");
-        }
+            if (resolvedUserType == null) {
+                throw new IllegalStateException("Can not have a user of type " + userType
+                        + " as they are not supported on this device");
+            }
 
-        return user(resolvedUserType);
+            return user(resolvedUserType);
+        });
     }
 
     /**
@@ -1361,17 +1463,20 @@
      * @throws IllegalStateException if there is no harrier-managed user of the correct type
      */
     public UserReference user(com.android.bedstead.nene.users.UserType userType) {
-        if (userType == null) {
-            throw new NullPointerException();
-        }
+        return mLogger.method("user", userType, () -> {
+            if (userType == null) {
+                throw new NullPointerException();
+            }
 
-        if (!mUsers.containsKey(userType)) {
-            throw new IllegalStateException(
-                    "No harrier-managed user of type " + userType + ". This method should only be"
-                            + "used when Harrier has been used to create the user.");
-        }
+            if (!mUsers.containsKey(userType)) {
+                throw new IllegalStateException(
+                        "No harrier-managed user of type " + userType
+                                + ". This method should only be"
+                                + "used when Harrier has been used to create the user.");
+            }
 
-        return mUsers.get(userType);
+            return mUsers.get(userType);
+        });
     }
 
     private UserReference ensureHasProfile(
@@ -1382,134 +1487,152 @@
             boolean profileOwnerIsPrimary,
             boolean useParentInstance,
             OptionalBoolean switchedToParentUser) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                requireUserSupported(profileType, FailureMode.SKIP);
+        return mLogger.method("ensureHasProfile", profileType, installInstrumentedApp,
+                forUser, hasProfileOwner, profileOwnerIsPrimary, useParentInstance,
+                switchedToParentUser, () -> {
+                    com.android.bedstead.nene.users.UserType resolvedUserType =
+                            requireUserSupported(profileType, FailureMode.SKIP);
 
-        UserReference forUserReference = resolveUserTypeToUser(forUser);
+                    UserReference forUserReference = resolveUserTypeToUser(forUser);
 
-        UserReference profile =
-                TestApis.users().findProfileOfType(resolvedUserType, forUserReference);
-        if (profile == null) {
-            if (profileType.equals(MANAGED_PROFILE_TYPE_NAME)) {
-                // DO + work profile isn't a valid state
-                ensureHasNoDeviceOwner();
-            }
+                    UserReference profile =
+                            TestApis.users().findProfileOfType(resolvedUserType, forUserReference);
+                    if (profile == null) {
+                        if (profileType.equals(MANAGED_PROFILE_TYPE_NAME)) {
+                            // DO + work profile isn't a valid state
+                            ensureHasNoDeviceOwner();
+                        }
 
-            profile = createProfile(resolvedUserType, forUserReference);
-        }
+                        profile = createProfile(resolvedUserType, forUserReference);
+                    }
 
-        profile.start();
+                    profile.start();
 
-        if (installInstrumentedApp.equals(OptionalBoolean.TRUE)) {
-            TestApis.packages().find(sContext.getPackageName()).installExisting(profile);
-        } else if (installInstrumentedApp.equals(OptionalBoolean.FALSE)) {
-            TestApis.packages().find(sContext.getPackageName()).uninstall(profile);
-        }
+                    if (installInstrumentedApp.equals(OptionalBoolean.TRUE)) {
+                        TestApis.packages().find(sContext.getPackageName()).installExisting(
+                                profile);
+                    } else if (installInstrumentedApp.equals(OptionalBoolean.FALSE)) {
+                        TestApis.packages().find(sContext.getPackageName()).uninstall(profile);
+                    }
 
-        if (!mProfiles.containsKey(resolvedUserType)) {
-            mProfiles.put(resolvedUserType, new HashMap<>());
-        }
+                    if (!mProfiles.containsKey(resolvedUserType)) {
+                        mProfiles.put(resolvedUserType, new HashMap<>());
+                    }
 
-        mProfiles.get(resolvedUserType).put(forUserReference, profile);
+                    mProfiles.get(resolvedUserType).put(forUserReference, profile);
 
-        if (hasProfileOwner) {
-            ensureHasProfileOwner(
-                    profile, profileOwnerIsPrimary, useParentInstance, /* affiliationIds= */ null);
-        }
+                    if (hasProfileOwner) {
+                        ensureHasProfileOwner(
+                                profile, profileOwnerIsPrimary,
+                                useParentInstance, /* affiliationIds= */
+                                null);
+                    }
 
-        ensureSwitchedToUser(switchedToParentUser, forUserReference);
+                    ensureSwitchedToUser(switchedToParentUser, forUserReference);
 
-        return profile;
+                    return profile;
+                });
     }
 
     private void ensureHasNoProfile(String profileType, UserType forUser) {
-        UserReference forUserReference = resolveUserTypeToUser(forUser);
-        com.android.bedstead.nene.users.UserType resolvedProfileType =
-                TestApis.users().supportedType(profileType);
+        mLogger.method("ensureHasNoProfile", profileType, forUser, () -> {
+            UserReference forUserReference = resolveUserTypeToUser(forUser);
+            com.android.bedstead.nene.users.UserType resolvedProfileType =
+                    TestApis.users().supportedType(profileType);
 
-        if (resolvedProfileType == null) {
-            // These profile types don't exist so there can't be any
-            return;
-        }
+            if (resolvedProfileType == null) {
+                // These profile types don't exist so there can't be any
+                return;
+            }
 
-        UserReference profile =
-                TestApis.users().findProfileOfType(
-                        resolvedProfileType,
-                        forUserReference);
-        if (profile != null) {
-            removeAndRecordUser(profile);
-        }
+            UserReference profile =
+                    TestApis.users().findProfileOfType(
+                            resolvedProfileType,
+                            forUserReference);
+            if (profile != null) {
+                removeAndRecordUser(profile);
+            }
+        });
     }
 
     private void ensureHasUser(
             String userType, OptionalBoolean installInstrumentedApp,
             OptionalBoolean switchedToUser) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                requireUserSupported(userType, FailureMode.SKIP);
+        mLogger.method("ensureHasUser", userType, installInstrumentedApp, switchedToUser, () -> {
+            com.android.bedstead.nene.users.UserType resolvedUserType =
+                    requireUserSupported(userType, FailureMode.SKIP);
 
-        Collection<UserReference> users = TestApis.users().findUsersOfType(resolvedUserType);
+            Collection<UserReference> users = TestApis.users().findUsersOfType(resolvedUserType);
 
-        UserReference user = users.isEmpty() ? createUser(resolvedUserType)
-                : users.iterator().next();
+            UserReference user = users.isEmpty() ? createUser(resolvedUserType)
+                    : users.iterator().next();
 
-        user.start();
+            user.start();
 
-        if (installInstrumentedApp.equals(OptionalBoolean.TRUE)) {
-            TestApis.packages().find(sContext.getPackageName()).installExisting(user);
-        } else if (installInstrumentedApp.equals(OptionalBoolean.FALSE)) {
-            TestApis.packages().find(sContext.getPackageName()).uninstall(user);
-        }
+            if (installInstrumentedApp.equals(OptionalBoolean.TRUE)) {
+                TestApis.packages().find(sContext.getPackageName()).installExisting(user);
+            } else if (installInstrumentedApp.equals(OptionalBoolean.FALSE)) {
+                TestApis.packages().find(sContext.getPackageName()).uninstall(user);
+            }
 
-        ensureSwitchedToUser(switchedToUser, user);
+            ensureSwitchedToUser(switchedToUser, user);
 
-        mUsers.put(resolvedUserType, user);
+            mUsers.put(resolvedUserType, user);
+        });
     }
 
     /**
      * Ensure that there is no user of the given type.
      */
     private void ensureHasNoUser(String userType) {
-        com.android.bedstead.nene.users.UserType resolvedUserType =
-                TestApis.users().supportedType(userType);
+        mLogger.method("ensureHasNoUser", userType, () -> {
+            com.android.bedstead.nene.users.UserType resolvedUserType =
+                    TestApis.users().supportedType(userType);
 
-        if (resolvedUserType == null) {
-            // These user types don't exist so there can't be any
-            return;
-        }
-
-        for (UserReference secondaryUser : TestApis.users().findUsersOfType(resolvedUserType)) {
-            if (secondaryUser.equals(TestApis.users().instrumented())) {
-                throw new AssumptionViolatedException(
-                        "This test only runs on devices without a "
-                                + userType + " user. But the instrumented user is " + userType);
+            if (resolvedUserType == null) {
+                // These user types don't exist so there can't be any
+                return;
             }
-            removeAndRecordUser(secondaryUser);
-        }
+
+            for (UserReference secondaryUser : TestApis.users().findUsersOfType(resolvedUserType)) {
+                if (secondaryUser.equals(TestApis.users().instrumented())) {
+                    throw new AssumptionViolatedException(
+                            "This test only runs on devices without a "
+                                    + userType + " user. But the instrumented user is " + userType);
+                }
+                removeAndRecordUser(secondaryUser);
+            }
+        });
     }
 
     private void removeAndRecordUser(UserReference userReference) {
-        if (userReference == null) {
-            return; // Nothing to remove
-        }
+        mLogger.method("removeAndRecordUser", userReference, () -> {
+            if (userReference == null) {
+                return; // Nothing to remove
+            }
 
-        switchFromUser(userReference);
+            switchFromUser(userReference);
 
-        if (!mCreatedUsers.remove(userReference)) {
-            mRemovedUsers.add(TestApis.users().createUser()
-                    .name(userReference.name())
-                    .type(userReference.type())
-                    .parent(userReference.parent()));
-        }
+            if (!mCreatedUsers.remove(userReference)) {
+                mRemovedUsers.add(TestApis.users().createUser()
+                        .name(userReference.name())
+                        .type(userReference.type())
+                        .parent(userReference.parent()));
+            }
 
-        userReference.remove();
+            userReference.remove();
+        });
     }
 
     public void requireCanSupportAdditionalUser() {
-        int maxUsers = getMaxNumberOfUsersSupported();
-        int currentUsers = TestApis.users().all().size();
+        mLogger.method("requireCanSupportadditionalUser", () -> {
+            int maxUsers = getMaxNumberOfUsersSupported();
+            int currentUsers = TestApis.users().all().size();
 
-        assumeTrue("The device does not have space for an additional user (" + currentUsers +
-                " current users, " + maxUsers + " max users)", currentUsers + 1 <= maxUsers);
+            assumeTrue("The device does not have space for an additional user ("
+                            + currentUsers + " current users, " + maxUsers + " max users)",
+                    currentUsers + 1 <= maxUsers);
+        });
     }
 
     /**
@@ -1517,7 +1640,8 @@
      * test has run.
      */
     public BlockingBroadcastReceiver registerBroadcastReceiver(String action) {
-        return registerBroadcastReceiver(action, /* checker= */ null);
+        return mLogger.method("registerBroadcastReceiver", action, () ->
+                registerBroadcastReceiver(action, /* checker= */ null));
     }
 
     /**
@@ -1526,12 +1650,14 @@
      */
     public BlockingBroadcastReceiver registerBroadcastReceiver(
             String action, Function<Intent, Boolean> checker) {
-        BlockingBroadcastReceiver broadcastReceiver =
-                new BlockingBroadcastReceiver(mContext, action, checker);
-        broadcastReceiver.register();
-        mRegisteredBroadcastReceivers.add(broadcastReceiver);
+        return mLogger.method("registerBroadcastReceiver", action, checker, () -> {
+            BlockingBroadcastReceiver broadcastReceiver =
+                    new BlockingBroadcastReceiver(mContext, action, checker);
+            broadcastReceiver.register();
+            mRegisteredBroadcastReceivers.add(broadcastReceiver);
 
-        return broadcastReceiver;
+            return broadcastReceiver;
+        });
     }
 
     /**
@@ -1540,7 +1666,8 @@
      */
     public BlockingBroadcastReceiver registerBroadcastReceiverForUser(
             UserReference user, String action) {
-        return registerBroadcastReceiverForUser(user, action, /* checker= */ null);
+        return mLogger.method("registerBroadcastReceiverForUser", user, action,
+                () -> registerBroadcastReceiverForUser(user, action, /* checker= */ null));
     }
 
     /**
@@ -1549,16 +1676,18 @@
      */
     public BlockingBroadcastReceiver registerBroadcastReceiverForUser(
             UserReference user, String action, Function<Intent, Boolean> checker) {
-        try (PermissionContext p =
-                     TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
-            BlockingBroadcastReceiver broadcastReceiver =
-                    new BlockingBroadcastReceiver(
-                            TestApis.context().androidContextAsUser(user), action, checker);
-            broadcastReceiver.register();
-            mRegisteredBroadcastReceivers.add(broadcastReceiver);
+        return mLogger.method("registerBroadcastReceiverForUser", user, action, checker, () -> {
+            try (PermissionContext p =
+                         TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                BlockingBroadcastReceiver broadcastReceiver =
+                        new BlockingBroadcastReceiver(
+                                TestApis.context().androidContextAsUser(user), action, checker);
+                broadcastReceiver.register();
+                mRegisteredBroadcastReceivers.add(broadcastReceiver);
 
-            return broadcastReceiver;
-        }
+                return broadcastReceiver;
+            }
+        });
     }
 
     /**
@@ -1566,7 +1695,8 @@
      * test has run.
      */
     public BlockingBroadcastReceiver registerBroadcastReceiverForAllUsers(String action) {
-        return registerBroadcastReceiverForAllUsers(action, /* checker= */ null);
+        return mLogger.method("registerBroadcastReceiverForAllUsers", action,
+                () -> registerBroadcastReceiverForAllUsers(action, /* checker= */ null));
     }
 
     /**
@@ -1575,483 +1705,539 @@
      */
     public BlockingBroadcastReceiver registerBroadcastReceiverForAllUsers(
             String action, Function<Intent, Boolean> checker) {
+        return mLogger.method("registerBroadcastReceiverForAllUsers", () -> {
+            try (PermissionContext p =
+                         TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
+                BlockingBroadcastReceiver broadcastReceiver =
+                        new BlockingBroadcastReceiver(mContext, action, checker);
+                broadcastReceiver.registerForAllUsers();
 
-        try (PermissionContext p =
-                     TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
-            BlockingBroadcastReceiver broadcastReceiver =
-                    new BlockingBroadcastReceiver(mContext, action, checker);
-            broadcastReceiver.registerForAllUsers();
+                mRegisteredBroadcastReceivers.add(broadcastReceiver);
 
-            mRegisteredBroadcastReceivers.add(broadcastReceiver);
-
-            return broadcastReceiver;
-        }
+                return broadcastReceiver;
+            }
+        });
     }
 
     private UserReference resolveUserTypeToUser(UserType userType) {
-        switch (userType) {
-            case SYSTEM_USER:
-                return TestApis.users().system();
-            case INSTRUMENTED_USER:
-                return TestApis.users().instrumented();
-            case CURRENT_USER:
-                return TestApis.users().current();
-            case PRIMARY_USER:
-                return primaryUser();
-            case SECONDARY_USER:
-                return secondaryUser();
-            case WORK_PROFILE:
-                return workProfile();
-            case TV_PROFILE:
-                return tvProfile();
-            case DPC_USER:
-                return dpc().user();
-            case ANY:
-                throw new IllegalStateException("ANY UserType can not be used here");
-            default:
-                throw new IllegalArgumentException("Unknown user type " + userType);
-        }
+        return mLogger.method("resolveUserTypeToUser", userType, () -> {
+            switch (userType) {
+                case SYSTEM_USER:
+                    return TestApis.users().system();
+                case INSTRUMENTED_USER:
+                    return TestApis.users().instrumented();
+                case CURRENT_USER:
+                    return TestApis.users().current();
+                case PRIMARY_USER:
+                    return primaryUser();
+                case SECONDARY_USER:
+                    return secondaryUser();
+                case WORK_PROFILE:
+                    return workProfile();
+                case TV_PROFILE:
+                    return tvProfile();
+                case DPC_USER:
+                    return dpc().user();
+                case ANY:
+                    throw new IllegalStateException("ANY UserType can not be used here");
+                default:
+                    throw new IllegalArgumentException("Unknown user type " + userType);
+            }
+        });
     }
 
     private void teardownNonShareableState() {
-        mProfiles.clear();
-        mUsers.clear();
+        mLogger.method("teardownNonShareableState", () -> {
+            mProfiles.clear();
+            mUsers.clear();
 
-        for (BlockingBroadcastReceiver broadcastReceiver : mRegisteredBroadcastReceivers) {
-            broadcastReceiver.unregisterQuietly();
-        }
-        mRegisteredBroadcastReceivers.clear();
-        mPrimaryPolicyManager = null;
-        mOtherUserType = null;
-        mTestApps.clear();
+            for (BlockingBroadcastReceiver broadcastReceiver : mRegisteredBroadcastReceivers) {
+                broadcastReceiver.unregisterQuietly();
+            }
+            mRegisteredBroadcastReceivers.clear();
+            mPrimaryPolicyManager = null;
+            mOtherUserType = null;
+            mTestApps.clear();
 
-        mTestAppProvider.restore();
+            mTestAppProvider.restore();
+        });
     }
 
     private Set<TestAppInstance> mInstalledTestApps = new HashSet<>();
     private Set<TestAppInstance> mUninstalledTestApps = new HashSet<>();
 
     private void teardownShareableState() {
-        if (mOriginalSwitchedUser != null) {
-            if (!mOriginalSwitchedUser.exists()) {
-                Log.d(LOG_TAG, "Could not switch back to original user "
-                        + mOriginalSwitchedUser
-                        + " as it does not exist. Switching to initial instead.");
-                TestApis.users().initial().switchTo();
-            } else {
-                mOriginalSwitchedUser.switchTo();
-            }
-            mOriginalSwitchedUser = null;
-        }
-
-        if (mHasChangedDeviceOwner) {
-            if (mOriginalDeviceOwner == null) {
-                if (mDeviceOwner != null) {
-                    mDeviceOwner.remove();
+        mLogger.method("teardownShareableState", () -> {
+            if (mOriginalSwitchedUser != null) {
+                if (!mOriginalSwitchedUser.exists()) {
+                    Log.d(LOG_TAG, "Could not switch back to original user "
+                            + mOriginalSwitchedUser
+                            + " as it does not exist. Switching to initial instead.");
+                    TestApis.users().initial().switchTo();
+                } else {
+                    mOriginalSwitchedUser.switchTo();
                 }
-            } else if (!mOriginalDeviceOwner.equals(mDeviceOwner)) {
-                if (mDeviceOwner != null) {
-                    mDeviceOwner.remove();
+                mOriginalSwitchedUser = null;
+            }
+
+            if (mHasChangedDeviceOwner) {
+                if (mOriginalDeviceOwner == null) {
+                    if (mDeviceOwner != null) {
+                        mDeviceOwner.remove();
+                    }
+                } else if (!mOriginalDeviceOwner.equals(mDeviceOwner)) {
+                    if (mDeviceOwner != null) {
+                        mDeviceOwner.remove();
+                    }
+                    TestApis.devicePolicy().setDeviceOwner(
+                            mOriginalDeviceOwner.componentName());
                 }
-                TestApis.devicePolicy().setDeviceOwner(
-                        mOriginalDeviceOwner.componentName());
-            }
-            mHasChangedDeviceOwner = false;
-            mOriginalDeviceOwner = null;
-        }
-
-        for (Map.Entry<UserReference, DevicePolicyController> originalProfileOwner :
-                mChangedProfileOwners.entrySet()) {
-
-            ProfileOwner currentProfileOwner =
-                    TestApis.devicePolicy().getProfileOwner(originalProfileOwner.getKey());
-
-            if (Objects.equal(currentProfileOwner, originalProfileOwner.getValue())) {
-                continue; // No need to restore
+                mHasChangedDeviceOwner = false;
+                mOriginalDeviceOwner = null;
             }
 
-            if (currentProfileOwner != null) {
-                currentProfileOwner.remove();
+            for (Map.Entry<UserReference, DevicePolicyController> originalProfileOwner :
+                    mChangedProfileOwners.entrySet()) {
+
+                ProfileOwner currentProfileOwner =
+                        TestApis.devicePolicy().getProfileOwner(originalProfileOwner.getKey());
+
+                if (Objects.equal(currentProfileOwner, originalProfileOwner.getValue())) {
+                    continue; // No need to restore
+                }
+
+                if (currentProfileOwner != null) {
+                    currentProfileOwner.remove();
+                }
+
+                if (originalProfileOwner.getValue() != null) {
+                    TestApis.devicePolicy().setProfileOwner(originalProfileOwner.getKey(),
+                            originalProfileOwner.getValue().componentName());
+                }
+            }
+            mChangedProfileOwners.clear();
+
+            for (UserReference user : mUsersSetPasswords) {
+                if (mCreatedUsers.contains(user)) {
+                    continue; // Will be removed anyway
+                }
+                user.clearPassword();
             }
 
-            if (originalProfileOwner.getValue() != null) {
-                TestApis.devicePolicy().setProfileOwner(originalProfileOwner.getKey(),
-                        originalProfileOwner.getValue().componentName());
+            mUsersSetPasswords.clear();
+
+            for (UserReference user : mCreatedUsers) {
+                user.remove();
             }
-        }
-        mChangedProfileOwners.clear();
 
-        for (UserReference user : mUsersSetPasswords) {
-            if (mCreatedUsers.contains(user)) {
-                continue; // Will be removed anyway
+            mCreatedUsers.clear();
+
+            for (UserBuilder userBuilder : mRemovedUsers) {
+                userBuilder.create();
             }
-            user.clearPassword();
-        }
 
-        mUsersSetPasswords.clear();
+            mRemovedUsers.clear();
 
-        for (UserReference user : mCreatedUsers) {
-            user.remove();
-        }
+            for (TestAppInstance installedTestApp : mInstalledTestApps) {
+                installedTestApp.uninstall();
+            }
+            mInstalledTestApps.clear();
 
-        mCreatedUsers.clear();
+            for (TestAppInstance uninstalledTestApp : mUninstalledTestApps) {
+                uninstalledTestApp.testApp().install(uninstalledTestApp.user());
+            }
+            mUninstalledTestApps.clear();
 
-        for (UserBuilder userBuilder : mRemovedUsers) {
-            userBuilder.create();
-        }
-
-        mRemovedUsers.clear();
-
-        for (TestAppInstance installedTestApp : mInstalledTestApps) {
-            installedTestApp.uninstall();
-        }
-        mInstalledTestApps.clear();
-
-        for (TestAppInstance uninstalledTestApp : mUninstalledTestApps) {
-            uninstalledTestApp.testApp().install(uninstalledTestApp.user());
-        }
-        mUninstalledTestApps.clear();
-
-        if (mOriginalBluetoothEnabled != null) {
-            TestApis.bluetooth().setEnabled(mOriginalBluetoothEnabled);
-            mOriginalBluetoothEnabled = null;
-        }
+            if (mOriginalBluetoothEnabled != null) {
+                TestApis.bluetooth().setEnabled(mOriginalBluetoothEnabled);
+                mOriginalBluetoothEnabled = null;
+            }
+        });
     }
 
     private UserReference createProfile(
             com.android.bedstead.nene.users.UserType profileType, UserReference parent) {
-        requireCanSupportAdditionalUser();
-        try {
-            UserReference user = TestApis.users().createUser()
-                    .parent(parent)
-                    .type(profileType)
-                    .createAndStart();
-            mCreatedUsers.add(user);
-            return user;
-        } catch (NeneException e) {
-            throw new IllegalStateException("Error creating profile of type " + profileType, e);
-        }
+        return mLogger.method("createProfile", profileType, parent, () -> {
+            requireCanSupportAdditionalUser();
+            try {
+                UserReference user = TestApis.users().createUser()
+                        .parent(parent)
+                        .type(profileType)
+                        .createAndStart();
+                mCreatedUsers.add(user);
+                return user;
+            } catch (NeneException e) {
+                throw new IllegalStateException("Error creating profile of type " + profileType, e);
+            }
+        });
     }
 
     private UserReference createUser(com.android.bedstead.nene.users.UserType userType) {
-        requireCanSupportAdditionalUser();
-        try {
-            UserReference user = TestApis.users().createUser()
-                    .type(userType)
-                    .createAndStart();
-            mCreatedUsers.add(user);
-            return user;
-        } catch (NeneException e) {
-            throw new IllegalStateException("Error creating user of type " + userType, e);
-        }
+        return mLogger.method("createUser", userType, () -> {
+            requireCanSupportAdditionalUser();
+            try {
+                UserReference user = TestApis.users().createUser()
+                        .type(userType)
+                        .createAndStart();
+                mCreatedUsers.add(user);
+                return user;
+            } catch (NeneException e) {
+                throw new IllegalStateException("Error creating user of type " + userType, e);
+            }
+        });
     }
 
     private int getMaxNumberOfUsersSupported() {
-        try {
-            return ShellCommand.builder("pm get-max-users")
-                    .validate((output) -> output.startsWith("Maximum supported users:"))
-                    .executeAndParseOutput(
-                            (output) -> Integer.parseInt(output.split(": ", 2)[1].trim()));
-        } catch (AdbException e) {
-            throw new IllegalStateException("Invalid command output", e);
-        }
+        return mLogger.method("getMaxNumberOfUsersSupported", () -> {
+            try {
+                return ShellCommand.builder("pm get-max-users")
+                        .validate((output) -> output.startsWith("Maximum supported users:"))
+                        .executeAndParseOutput(
+                                (output) -> Integer.parseInt(output.split(": ", 2)[1]
+                                        .trim()));
+            } catch (AdbException e) {
+                throw new IllegalStateException("Invalid command output", e);
+            }
+        });
     }
 
     private void ensureHasDelegate(
             EnsureHasDelegate.AdminType adminType, List<String> scopes, boolean isPrimary) {
-        RemotePolicyManager dpc = getDeviceAdmin(adminType);
+        mLogger.method("ensureHasDelegate", adminType, scopes, isPrimary, () -> {
+            RemotePolicyManager dpc = getDeviceAdmin(adminType);
 
-        boolean specifiesAdminType = adminType != EnsureHasDelegate.AdminType.PRIMARY;
-        boolean currentPrimaryPolicyManagerIsNotDelegator = mPrimaryPolicyManager != dpc;
+            boolean specifiesAdminType = adminType != EnsureHasDelegate.AdminType.PRIMARY;
+            boolean currentPrimaryPolicyManagerIsNotDelegator =
+                    !Objects.equal(mPrimaryPolicyManager, dpc);
 
-        if (isPrimary && mPrimaryPolicyManager != null
-                && (specifiesAdminType || currentPrimaryPolicyManagerIsNotDelegator)) {
-            throw new IllegalStateException(
-                    "Only one DPC can be marked as primary per test (current primary is "
-                            + mPrimaryPolicyManager + ")");
-        }
-
-        if (!dpc.user().equals(TestApis.users().instrumented())) {
-            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
-            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
-        }
-
-        ensureTestAppInstalled(RemoteDelegate.sTestApp, dpc.user());
-        RemoteDelegate delegate = new RemoteDelegate(RemoteDelegate.sTestApp, dpc().user());
-        dpc.devicePolicyManager().setDelegatedScopes(
-                dpc.componentName(), delegate.packageName(), scopes);
-
-        if (isPrimary) {
-            mPrimaryPolicyManager = delegate;
-        }
-    }
-
-    private void ensureHasNoDelegate(EnsureHasNoDelegate.AdminType adminType) {
-        if (adminType == EnsureHasNoDelegate.AdminType.ANY) {
-            for (UserReference user : TestApis.users().all()) {
-                ensureTestAppNotInstalled(RemoteDelegate.sTestApp, user);
-            }
-            return;
-        }
-        RemotePolicyManager dpc =
-                adminType == EnsureHasNoDelegate.AdminType.PRIMARY ? mPrimaryPolicyManager
-                : adminType == EnsureHasNoDelegate.AdminType.DEVICE_OWNER ? deviceOwner()
-                : adminType == EnsureHasNoDelegate.AdminType.PROFILE_OWNER ? profileOwner() : null;
-        if (dpc == null) {
-            throw new IllegalStateException("Unknown Admin Type " + adminType);
-        }
-
-        ensureTestAppNotInstalled(RemoteDelegate.sTestApp, dpc.user());
-    }
-
-    private void ensureTestAppInstalled(
-            String key, String packageName, UserType onUser, boolean isPrimary) {
-        TestApp testApp = mTestAppProvider.query()
-                .wherePackageName().isEqualTo(packageName)
-                .get();
-
-        TestAppInstance testAppInstance = ensureTestAppInstalled(
-                testApp, resolveUserTypeToUser(onUser));
-
-        mTestApps.put(key, testAppInstance);
-
-        if (isPrimary) {
-            if (mPrimaryPolicyManager != null) {
+            if (isPrimary && mPrimaryPolicyManager != null
+                    && (specifiesAdminType || currentPrimaryPolicyManagerIsNotDelegator)) {
                 throw new IllegalStateException(
                         "Only one DPC can be marked as primary per test (current primary is "
                                 + mPrimaryPolicyManager + ")");
             }
 
-            mPrimaryPolicyManager = new RemoteTestApp(testAppInstance);
-        }
+            if (!dpc.user().equals(TestApis.users().instrumented())) {
+                // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+                ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
+            }
+
+            ensureTestAppInstalled(RemoteDelegate.sTestApp, dpc.user());
+            RemoteDelegate delegate = new RemoteDelegate(RemoteDelegate.sTestApp, dpc().user());
+            dpc.devicePolicyManager().setDelegatedScopes(
+                    dpc.componentName(), delegate.packageName(), scopes);
+
+            if (isPrimary) {
+                mPrimaryPolicyManager = delegate;
+            }
+        });
+    }
+
+    private void ensureHasNoDelegate(EnsureHasNoDelegate.AdminType adminType) {
+        mLogger.method("ensureHasNoDelegate", adminType, () -> {
+            if (adminType == EnsureHasNoDelegate.AdminType.ANY) {
+                for (UserReference user : TestApis.users().all()) {
+                    ensureTestAppNotInstalled(RemoteDelegate.sTestApp, user);
+                }
+                return;
+            }
+            RemotePolicyManager dpc =
+                    adminType == EnsureHasNoDelegate.AdminType.PRIMARY ? mPrimaryPolicyManager
+                            : adminType == EnsureHasNoDelegate.AdminType.DEVICE_OWNER
+                                    ? deviceOwner()
+                                    : adminType == EnsureHasNoDelegate.AdminType.PROFILE_OWNER
+                                            ? profileOwner() : null;
+            if (dpc == null) {
+                throw new IllegalStateException("Unknown Admin Type " + adminType);
+            }
+
+            ensureTestAppNotInstalled(RemoteDelegate.sTestApp, dpc.user());
+        });
+    }
+
+    private void ensureTestAppInstalled(
+            String key, String packageName, UserType onUser, boolean isPrimary) {
+        mLogger.method("ensureTestAppInstalled", key, packageName, onUser, isPrimary, () -> {
+            TestApp testApp = mTestAppProvider.query()
+                    .wherePackageName().isEqualTo(packageName)
+                    .get();
+
+            TestAppInstance testAppInstance = ensureTestAppInstalled(
+                    testApp, resolveUserTypeToUser(onUser));
+
+            mTestApps.put(key, testAppInstance);
+
+            if (isPrimary) {
+                if (mPrimaryPolicyManager != null) {
+                    throw new IllegalStateException(
+                            "Only one DPC can be marked as primary per test (current primary is "
+                                    + mPrimaryPolicyManager + ")");
+                }
+
+                mPrimaryPolicyManager = new RemoteTestApp(testAppInstance);
+            }
+        });
     }
 
     private void ensureTestAppHasPermission(
             String testAppKey, String[] permissions, int minVersion, int maxVersion) {
-        if (!mTestApps.containsKey(testAppKey)) {
-            throw new NeneException("No testapp with given key. Use @EnsureTestAppInstalled");
-        }
+        mLogger.method("ensureTestAppHasPermission", testAppKey, permissions, minVersion,
+                maxVersion, () -> {
+                    checkTestAppExistsWithKey(testAppKey);
 
-        mTestApps.get(testAppKey).permissions()
-                .withPermissionOnVersionBetween(minVersion, maxVersion, permissions);
-
+                    mTestApps.get(testAppKey).permissions()
+                            .withPermissionOnVersionBetween(minVersion, maxVersion, permissions);
+                });
     }
 
     private void ensureTestAppHasAppOp(
             String testAppKey, String[] appOps, int minVersion, int maxVersion) {
-        if (!mTestApps.containsKey(testAppKey)) {
-            throw new NeneException("No testapp with given key. Use @EnsureTestAppInstalled");
-        }
+        mLogger.method("ensureTestAppHasAppOp", testAppKey, appOps, minVersion, maxVersion, () -> {
+            checkTestAppExistsWithKey(testAppKey);
 
-        mTestApps.get(testAppKey).permissions()
-                .withAppOpOnVersionBetween(minVersion, maxVersion, appOps);
+            mTestApps.get(testAppKey).permissions()
+                    .withAppOpOnVersionBetween(minVersion, maxVersion, appOps);
+        });
+    }
+
+    private void checkTestAppExistsWithKey(String testAppKey) {
+        if (!mTestApps.containsKey(testAppKey)) {
+            throw new NeneException(
+                    "No testapp with key " + testAppKey + ". Use @EnsureTestAppInstalled."
+                            + "Valid Test apps: " + mTestApps);
+        }
     }
 
     private RemotePolicyManager getDeviceAdmin(EnsureHasDelegate.AdminType adminType) {
-        switch (adminType) {
-            case DEVICE_OWNER:
-                return deviceOwner();
-            case PROFILE_OWNER:
-                return profileOwner();
-            case PRIMARY:
-                return dpc();
-            default:
-                throw new IllegalStateException("Unknown device admin type " + adminType);
-        }
+        return mLogger.method("getDeviceAdmin", adminType, () -> {
+            switch (adminType) {
+                case DEVICE_OWNER:
+                    return deviceOwner();
+                case PROFILE_OWNER:
+                    return profileOwner();
+                case PRIMARY:
+                    return dpc();
+                default:
+                    throw new IllegalStateException("Unknown device admin type " + adminType);
+            }
+        });
     }
 
     private TestAppInstance ensureTestAppInstalled(TestApp testApp, UserReference user) {
-        Package pkg = TestApis.packages().find(testApp.packageName());
-        if (pkg != null && TestApis.packages().find(testApp.packageName()).installedOnUser(user)) {
-            return testApp.instance(user);
-        }
+        return mLogger.method("ensureTestAppInstalled", testApp, user, () -> {
+            Package pkg = TestApis.packages().find(testApp.packageName());
+            if (pkg != null && TestApis.packages().find(testApp.packageName()).installedOnUser(
+                    user)) {
+                return testApp.instance(user);
+            }
 
-        TestAppInstance testAppInstance = testApp.install(user);
-        mInstalledTestApps.add(testAppInstance);
-        return testAppInstance;
+            TestAppInstance testAppInstance = testApp.install(user);
+            mInstalledTestApps.add(testAppInstance);
+            return testAppInstance;
+        });
     }
 
     private void ensureTestAppNotInstalled(TestApp testApp, UserReference user) {
-        Package pkg = TestApis.packages().find(testApp.packageName());
-        if (pkg == null || !TestApis.packages().find(testApp.packageName()).installedOnUser(user)) {
-            return;
-        }
+        mLogger.method("ensureTestAppNotInstalled", testApp, user, () -> {
+            Package pkg = TestApis.packages().find(testApp.packageName());
+            if (pkg == null || !TestApis.packages().find(testApp.packageName()).installedOnUser(
+                    user)) {
+                return;
+            }
 
-        TestAppInstance instance = testApp.instance(user);
+            TestAppInstance instance = testApp.instance(user);
 
-        if (mInstalledTestApps.contains(instance)) {
-            mInstalledTestApps.remove(instance);
-        } else {
-            mUninstalledTestApps.add(instance);
-        }
+            if (mInstalledTestApps.contains(instance)) {
+                mInstalledTestApps.remove(instance);
+            } else {
+                mUninstalledTestApps.add(instance);
+            }
 
-        testApp.uninstall(user);
+            testApp.uninstall(user);
+        });
     }
 
     private void ensureHasDeviceOwner(FailureMode failureMode, boolean isPrimary,
             Set<String> affiliationIds) {
-        // TODO(scottjonathan): Should support non-remotedpc device owner (default to remotedpc)
+        mLogger.method("ensureHasDeviceOwner", failureMode, isPrimary, affiliationIds, () -> {
+            // TODO(scottjonathan): Should support non-remotedpc device owner (default to remotedpc)
 
-        UserReference userReference = TestApis.users().system();
+            UserReference userReference = TestApis.users().system();
 
-        if (isPrimary && mPrimaryPolicyManager != null && !userReference.equals(
-                mPrimaryPolicyManager.user())) {
-            throw new IllegalStateException(
-                    "Only one DPC can be marked as primary per test (current primary is "
-                            + mPrimaryPolicyManager + ")");
-        }
-        if (!userReference.equals(TestApis.users().instrumented())) {
-            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
-            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
-        }
-
-        DeviceOwner currentDeviceOwner = TestApis.devicePolicy().getDeviceOwner();
-
-        if (currentDeviceOwner != null
-                && currentDeviceOwner.componentName().equals(RemoteDpc.DPC_COMPONENT_NAME)) {
-            mDeviceOwner = currentDeviceOwner;
-        } else {
-            UserReference instrumentedUser = TestApis.users().instrumented();
-
-            if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
-                // Prior to S we can't set device owner if there are other users on the device
-
-                if (instrumentedUser.id() != 0) {
-                    // If we're not on the system user we can't reach the required state
-                    throw new AssumptionViolatedException(
-                            "Can't set Device Owner when running on non-system-user"
-                                    + " on this version of Android");
-                }
-
-                for (UserReference u : TestApis.users().all()) {
-                    if (u.equals(instrumentedUser)) {
-                        // Can't remove the user we're running on
-                        continue;
-                    }
-                    try {
-                        removeAndRecordUser(u);
-                    } catch (NeneException e) {
-                        failOrSkip(
-                                "Error removing user to prepare for DeviceOwner: " + e.toString(),
-                                failureMode);
-                    }
-                }
+            if (isPrimary && mPrimaryPolicyManager != null && !userReference.equals(
+                    mPrimaryPolicyManager.user())) {
+                throw new IllegalStateException(
+                        "Only one DPC can be marked as primary per test (current primary is "
+                                + mPrimaryPolicyManager + ")");
+            }
+            if (!userReference.equals(TestApis.users().instrumented())) {
+                // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+                ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
             }
 
-            // TODO(scottjonathan): Remove accounts
-            ensureHasNoProfileOwner(userReference);
+            DeviceOwner currentDeviceOwner = TestApis.devicePolicy().getDeviceOwner();
 
-            if (!mHasChangedDeviceOwner) {
-                mOriginalDeviceOwner = currentDeviceOwner;
-                mHasChangedDeviceOwner = true;
+            if (currentDeviceOwner != null
+                    && currentDeviceOwner.componentName().equals(RemoteDpc.DPC_COMPONENT_NAME)) {
+                mDeviceOwner = currentDeviceOwner;
+            } else {
+                UserReference instrumentedUser = TestApis.users().instrumented();
+
+                if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) {
+                    // Prior to S we can't set device owner if there are other users on the device
+
+                    if (instrumentedUser.id() != 0) {
+                        // If we're not on the system user we can't reach the required state
+                        throw new AssumptionViolatedException(
+                                "Can't set Device Owner when running on non-system-user"
+                                        + " on this version of Android");
+                    }
+
+                    for (UserReference u : TestApis.users().all()) {
+                        if (u.equals(instrumentedUser)) {
+                            // Can't remove the user we're running on
+                            continue;
+                        }
+                        try {
+                            removeAndRecordUser(u);
+                        } catch (NeneException e) {
+                            failOrSkip(
+                                    "Error removing user to prepare for DeviceOwner: "
+                                            + e.toString(),
+                                    failureMode);
+                        }
+                    }
+                }
+
+                // TODO(scottjonathan): Remove accounts
+                ensureHasNoProfileOwner(userReference);
+
+                if (!mHasChangedDeviceOwner) {
+                    mOriginalDeviceOwner = currentDeviceOwner;
+                    mHasChangedDeviceOwner = true;
+                }
+
+                mDeviceOwner = RemoteDpc.setAsDeviceOwner().devicePolicyController();
             }
 
-            mDeviceOwner = RemoteDpc.setAsDeviceOwner().devicePolicyController();
-        }
+            if (isPrimary) {
+                mPrimaryPolicyManager = RemoteDpc.forDevicePolicyController(mDeviceOwner);
+            }
 
-        if (isPrimary) {
-            mPrimaryPolicyManager = RemoteDpc.forDevicePolicyController(mDeviceOwner);
-        }
-        
-        RemoteDpc.forDevicePolicyController(mDeviceOwner)
-                .devicePolicyManager()
-                .setAffiliationIds(REMOTE_DPC_COMPONENT_NAME, affiliationIds);
+            RemoteDpc.forDevicePolicyController(mDeviceOwner)
+                    .devicePolicyManager()
+                    .setAffiliationIds(REMOTE_DPC_COMPONENT_NAME, affiliationIds);
+        });
     }
 
     private void ensureHasProfileOwner(UserType onUser, boolean isPrimary,
             boolean useParentInstance, Set<String> affiliationIds) {
-        // TODO(scottjonathan): Should support non-remotedpc profile owner (default to remotedpc)
-        UserReference user = resolveUserTypeToUser(onUser);
-        ensureHasProfileOwner(user, isPrimary, useParentInstance, affiliationIds);
+        mLogger.method("ensureHasProfileOwner",
+                onUser, isPrimary, useParentInstance, affiliationIds, () -> {
+                    // TODO(scottjonathan): Should support non-remotedpc profile owner
+                    //  (default to remotedpc)
+                    UserReference user = resolveUserTypeToUser(onUser);
+                    ensureHasProfileOwner(user, isPrimary, useParentInstance, affiliationIds);
+                });
     }
 
     private void ensureHasProfileOwner(
             UserReference user, boolean isPrimary, boolean useParentInstance,
             Set<String> affiliationIds) {
-        if (isPrimary && mPrimaryPolicyManager != null
-                && !user.equals(mPrimaryPolicyManager.user())) {
-            throw new IllegalStateException("Only one DPC can be marked as primary per test");
-        }
+        mLogger.method("ensureHasProfileOwner", user, isPrimary, useParentInstance,
+                affiliationIds, () -> {
+                    if (isPrimary && mPrimaryPolicyManager != null
+                            && !user.equals(mPrimaryPolicyManager.user())) {
+                        throw new IllegalStateException(
+                                "Only one DPC can be marked as primary per test");
+                    }
 
-        if (!user.equals(TestApis.users().instrumented())) {
-            // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
-            ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
-        }
+                    if (!user.equals(TestApis.users().instrumented())) {
+                        // INTERACT_ACROSS_USERS_FULL is required for RemoteDPC
+                        ensureCanGetPermission(INTERACT_ACROSS_USERS_FULL);
+                    }
 
-        ProfileOwner currentProfileOwner = TestApis.devicePolicy().getProfileOwner(user);
-        DeviceOwner currentDeviceOwner = TestApis.devicePolicy().getDeviceOwner();
+                    ProfileOwner currentProfileOwner = TestApis.devicePolicy().getProfileOwner(
+                            user);
+                    DeviceOwner currentDeviceOwner = TestApis.devicePolicy().getDeviceOwner();
 
-        if (currentDeviceOwner != null && currentDeviceOwner.user().equals(user)) {
-            // Can't have DO and PO on the same user
-            ensureHasNoDeviceOwner();
-        }
+                    if (currentDeviceOwner != null && currentDeviceOwner.user().equals(user)) {
+                        // Can't have DO and PO on the same user
+                        ensureHasNoDeviceOwner();
+                    }
 
-        if (currentProfileOwner != null
-                && currentProfileOwner.componentName().equals(
-                RemoteDpc.DPC_COMPONENT_NAME)) {
-            mProfileOwners.put(user, currentProfileOwner);
-        } else {
+                    if (currentProfileOwner != null && currentProfileOwner.componentName()
+                            .equals(RemoteDpc.DPC_COMPONENT_NAME)) {
+                        mProfileOwners.put(user, currentProfileOwner);
+                    } else {
+                        if (!mChangedProfileOwners.containsKey(user)) {
+                            mChangedProfileOwners.put(user, currentProfileOwner);
+                        }
+
+                        mProfileOwners.put(user,
+                                RemoteDpc.setAsProfileOwner(user).devicePolicyController());
+                    }
+
+                    if (isPrimary) {
+                        if (useParentInstance) {
+                            mPrimaryPolicyManager = new RemoteDpcUsingParentInstance(
+                                    RemoteDpc.forDevicePolicyController(
+                                            mProfileOwners.get(user)).devicePolicyController());
+                        } else {
+                            mPrimaryPolicyManager =
+                                    RemoteDpc.forDevicePolicyController(mProfileOwners.get(user));
+                        }
+                    }
+
+                    if (affiliationIds != null) {
+                        RemoteDpc profileOwner = profileOwner(user);
+                        profileOwner.devicePolicyManager()
+                                .setAffiliationIds(REMOTE_DPC_COMPONENT_NAME, affiliationIds);
+                    }
+                });
+    }
+
+    private void ensureHasNoDeviceOwner() {
+        mLogger.method("ensureHasNoDeviceOwner", () -> {
+            DeviceOwner deviceOwner = TestApis.devicePolicy().getDeviceOwner();
+
+            if (deviceOwner == null) {
+                return;
+            }
+
+            if (!mHasChangedDeviceOwner) {
+                mOriginalDeviceOwner = deviceOwner;
+                mHasChangedDeviceOwner = true;
+            }
+
+            mDeviceOwner = null;
+            deviceOwner.remove();
+        });
+    }
+
+    private void ensureHasNoProfileOwner(UserType onUser) {
+        mLogger.method("ensureHasNoProfileOwner", onUser, () -> {
+            UserReference user = resolveUserTypeToUser(onUser);
+
+            ensureHasNoProfileOwner(user);
+        });
+    }
+
+    private void ensureHasNoProfileOwner(UserReference user) {
+        mLogger.method("ensureHasNoProfileOwner", user, () -> {
+            ProfileOwner currentProfileOwner = TestApis.devicePolicy().getProfileOwner(user);
+
+            if (currentProfileOwner == null) {
+                return;
+            }
+
             if (!mChangedProfileOwners.containsKey(user)) {
                 mChangedProfileOwners.put(user, currentProfileOwner);
             }
 
-            mProfileOwners.put(user, RemoteDpc.setAsProfileOwner(user).devicePolicyController());
-        }
-
-        if (isPrimary) {
-            if (useParentInstance) {
-                mPrimaryPolicyManager = new RemoteDpcUsingParentInstance(
-                        RemoteDpc.forDevicePolicyController(
-                                mProfileOwners.get(user)).devicePolicyController());
-            } else {
-                mPrimaryPolicyManager =
-                        RemoteDpc.forDevicePolicyController(mProfileOwners.get(user));
-            }
-        }
-
-        if (affiliationIds != null) {
-            RemoteDpc profileOwner = profileOwner(user);
-            profileOwner.devicePolicyManager()
-                    .setAffiliationIds(REMOTE_DPC_COMPONENT_NAME, affiliationIds);
-        }
-    }
-
-    private void ensureHasNoDeviceOwner() {
-        DeviceOwner deviceOwner = TestApis.devicePolicy().getDeviceOwner();
-
-        if (deviceOwner == null) {
-            return;
-        }
-
-        if (!mHasChangedDeviceOwner) {
-            mOriginalDeviceOwner = deviceOwner;
-            mHasChangedDeviceOwner = true;
-        }
-
-        mDeviceOwner = null;
-        deviceOwner.remove();
-    }
-
-    private void ensureHasNoProfileOwner(UserType onUser) {
-        UserReference user = resolveUserTypeToUser(onUser);
-
-        ensureHasNoProfileOwner(user);
-    }
-
-    private void ensureHasNoProfileOwner(UserReference user) {
-
-        ProfileOwner currentProfileOwner = TestApis.devicePolicy().getProfileOwner(user);
-
-        if (currentProfileOwner == null) {
-            return;
-        }
-
-        if (!mChangedProfileOwners.containsKey(user)) {
-            mChangedProfileOwners.put(user, currentProfileOwner);
-        }
-
-        TestApis.devicePolicy().getProfileOwner(user).remove();
-        mProfileOwners.remove(user);
+            TestApis.devicePolicy().getProfileOwner(user).remove();
+            mProfileOwners.remove(user);
+        });
     }
 
     /**
@@ -2062,16 +2248,19 @@
      * <p>If the device owner is not a RemoteDPC then an exception will be thrown
      */
     public RemoteDpc deviceOwner() {
-        if (mDeviceOwner == null) {
-            throw new IllegalStateException("No Harrier-managed device owner. This method should "
-                    + "only be used when Harrier was used to set the Device Owner.");
-        }
-        if (!mDeviceOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
-            throw new IllegalStateException("The device owner is not a RemoteDPC."
-                    + " You must use Nene to query for this device owner.");
-        }
+        return mLogger.method("deviceOwner", () -> {
+            if (mDeviceOwner == null) {
+                throw new IllegalStateException(
+                        "No Harrier-managed device owner. This method should "
+                                + "only be used when Harrier was used to set the Device Owner.");
+            }
+            if (!mDeviceOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
+                throw new IllegalStateException("The device owner is not a RemoteDPC."
+                        + " You must use Nene to query for this device owner.");
+            }
 
-        return RemoteDpc.forDevicePolicyController(mDeviceOwner);
+            return RemoteDpc.forDevicePolicyController(mDeviceOwner);
+        });
     }
 
     /**
@@ -2082,7 +2271,9 @@
      * <p>If the profile owner is not a RemoteDPC then an exception will be thrown.
      */
     public RemoteDpc profileOwner() {
-        return profileOwner(UserType.INSTRUMENTED_USER);
+        return mLogger.method("profileOwner", () -> {
+            return profileOwner(UserType.INSTRUMENTED_USER);
+        });
     }
 
     /**
@@ -2093,11 +2284,13 @@
      * <p>If the profile owner is not a RemoteDPC then an exception will be thrown.
      */
     public RemoteDpc profileOwner(UserType onUser) {
-        if (onUser == null) {
-            throw new NullPointerException();
-        }
+        return mLogger.method("profileOwner", onUser, () -> {
+            if (onUser == null) {
+                throw new NullPointerException();
+            }
 
-        return profileOwner(resolveUserTypeToUser(onUser));
+            return profileOwner(resolveUserTypeToUser(onUser));
+        });
     }
 
     /**
@@ -2108,70 +2301,79 @@
      * <p>If the profile owner is not a RemoteDPC then an exception will be thrown.
      */
     public RemoteDpc profileOwner(UserReference onUser) {
-        if (onUser == null) {
-            throw new NullPointerException();
-        }
+        return mLogger.method("profileOwner", onUser, () -> {
+            if (onUser == null) {
+                throw new NullPointerException();
+            }
 
-        if (!mProfileOwners.containsKey(onUser)) {
-            throw new IllegalStateException("No Harrier-managed profile owner. This method should "
-                    + "only be used when Harrier was used to set the Profile Owner.");
-        }
+            if (!mProfileOwners.containsKey(onUser)) {
+                throw new IllegalStateException(
+                        "No Harrier-managed profile owner. This method should "
+                                + "only be used when Harrier was used to set the Profile Owner.");
+            }
 
-        DevicePolicyController profileOwner = mProfileOwners.get(onUser);
+            DevicePolicyController profileOwner = mProfileOwners.get(onUser);
 
-        if (!profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
-            throw new IllegalStateException("The profile owner is not a RemoteDPC."
-                    + " You must use Nene to query for this profile owner.");
-        }
+            if (!profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
+                throw new IllegalStateException("The profile owner is not a RemoteDPC."
+                        + " You must use Nene to query for this profile owner.");
+            }
 
-        return RemoteDpc.forDevicePolicyController(profileOwner);
+            return RemoteDpc.forDevicePolicyController(profileOwner);
+        });
     }
 
     private void requirePackageInstalled(
             String packageName, UserType forUser, FailureMode failureMode) {
+        mLogger.method("requirePackageInstalled", packageName, forUser, failureMode, () -> {
+            Package pkg = TestApis.packages().find(packageName);
 
-        Package pkg = TestApis.packages().find(packageName);
-
-        if (forUser.equals(UserType.ANY)) {
-            checkFailOrSkip(
-                    packageName + " is required to be installed",
-                    !pkg.installedOnUsers().isEmpty(),
-                    failureMode);
-        } else {
-            checkFailOrSkip(
-                    packageName + " is required to be installed for " + forUser,
-                    pkg.installedOnUser(resolveUserTypeToUser(forUser)),
-                    failureMode);
-        }
+            if (forUser.equals(UserType.ANY)) {
+                checkFailOrSkip(
+                        packageName + " is required to be installed",
+                        !pkg.installedOnUsers().isEmpty(),
+                        failureMode);
+            } else {
+                checkFailOrSkip(
+                        packageName + " is required to be installed for " + forUser,
+                        pkg.installedOnUser(resolveUserTypeToUser(forUser)),
+                        failureMode);
+            }
+        });
     }
 
     private void requirePackageNotInstalled(
             String packageName, UserType forUser, FailureMode failureMode) {
-        Package pkg = TestApis.packages().find(packageName);
+        mLogger.method("requirePackageNotInstalled", packageName, forUser,
+                failureMode, () -> {
+                    Package pkg = TestApis.packages().find(packageName);
 
-        if (forUser.equals(UserType.ANY)) {
-            checkFailOrSkip(
-                    packageName + " is required to be not installed",
-                    pkg.installedOnUsers().isEmpty(),
-                    failureMode);
-        } else {
-            checkFailOrSkip(
-                    packageName + " is required to be not installed for " + forUser,
-                    !pkg.installedOnUser(resolveUserTypeToUser(forUser)),
-                    failureMode);
-        }
+                    if (forUser.equals(UserType.ANY)) {
+                        checkFailOrSkip(
+                                packageName + " is required to be not installed",
+                                pkg.installedOnUsers().isEmpty(),
+                                failureMode);
+                    } else {
+                        checkFailOrSkip(
+                                packageName + " is required to be not installed for " + forUser,
+                                !pkg.installedOnUser(resolveUserTypeToUser(forUser)),
+                                failureMode);
+                    }
+                });
     }
 
     private void ensurePackageNotInstalled(
             String packageName, UserType forUser) {
-        Package pkg = TestApis.packages().find(packageName);
+        mLogger.method("ensurePackageNotInstalled", packageName, forUser, () -> {
+            Package pkg = TestApis.packages().find(packageName);
 
-        if (forUser.equals(UserType.ANY)) {
-            pkg.uninstallFromAllUsers();
-        } else {
-            UserReference user = resolveUserTypeToUser(forUser);
-            pkg.uninstall(user);
-        }
+            if (forUser.equals(UserType.ANY)) {
+                pkg.uninstallFromAllUsers();
+            } else {
+                UserReference user = resolveUserTypeToUser(forUser);
+                pkg.uninstall(user);
+            }
+        });
     }
 
     /**
@@ -2189,28 +2391,30 @@
      * <p>If the profile owner or device owner is not a RemoteDPC then an exception will be thrown.
      */
     public RemotePolicyManager dpc() {
-        if (mPrimaryPolicyManager != null) {
-            return mPrimaryPolicyManager;
-        }
-
-        if (mProfileOwners.containsKey(TestApis.users().instrumented())) {
-            DevicePolicyController profileOwner =
-                    mProfileOwners.get(TestApis.users().instrumented());
-
-
-            if (profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
-                return RemoteDpc.forDevicePolicyController(profileOwner);
-            }
-        }
-
-        if (mDeviceOwner != null) {
-            if (mDeviceOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
-                return RemoteDpc.forDevicePolicyController(mDeviceOwner);
+        return mLogger.method("dpc", () -> {
+            if (mPrimaryPolicyManager != null) {
+                return mPrimaryPolicyManager;
             }
 
-        }
+            if (mProfileOwners.containsKey(TestApis.users().instrumented())) {
+                DevicePolicyController profileOwner =
+                        mProfileOwners.get(TestApis.users().instrumented());
 
-        throw new IllegalStateException("No Harrier-managed profile owner or device owner.");
+
+                if (profileOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
+                    return RemoteDpc.forDevicePolicyController(profileOwner);
+                }
+            }
+
+            if (mDeviceOwner != null) {
+                if (mDeviceOwner.componentName().equals(REMOTE_DPC_COMPONENT_NAME)) {
+                    return RemoteDpc.forDevicePolicyController(mDeviceOwner);
+                }
+
+            }
+
+            throw new IllegalStateException("No Harrier-managed profile owner or device owner.");
+        });
     }
 
     /**
@@ -2220,178 +2424,210 @@
      * automatically remove test apps use the {@link EnsureTestAppInstalled} annotation.
      */
     public TestAppProvider testApps() {
-        return mTestAppProvider;
+        return mLogger.method("testApps", () -> {
+            return mTestAppProvider;
+        });
     }
 
     /**
      * Get a test app installed with @EnsureTestAppInstalled with no key.
      */
     public TestAppInstance testApp() {
-        return testApp(DEFAULT_TEST_APP_KEY);
+        return mLogger.method("testApp", () -> {
+            return testApp(DEFAULT_TEST_APP_KEY);
+        });
     }
 
     /**
      * Get a test app installed with `@EnsureTestAppInstalled` with the given key.
      */
     public TestAppInstance testApp(String key) {
-        if (!mTestApps.containsKey(key)) {
-            throw new NeneException("No testapp with given key. Use @EnsureTestAppInstalled");
-        }
+        return mLogger.method("testApp", key, () -> {
+            if (!mTestApps.containsKey(key)) {
+                throw new NeneException("No testapp with given key. Use @EnsureTestAppInstalled");
+            }
 
-        return mTestApps.get(key);
+            return mTestApps.get(key);
+        });
     }
 
     private void ensureCanGetPermission(String permission) {
-        if (mPermissionsInstrumentationPackage == null) {
-            // We just need to check if we can get it generally
+        mLogger.method("ensureCanGetPermission", permission, () -> {
+            if (mPermissionsInstrumentationPackage == null) {
+                // We just need to check if we can get it generally
 
-            if (TestApis.permissions().usablePermissions().contains(permission)) {
-                return;
+                if (TestApis.permissions().usablePermissions().contains(permission)) {
+                    return;
+                }
+
+                if (TestApis.packages().instrumented().isInstantApp()) {
+                    // Instant Apps aren't able to know the permissions of shell so we can't know
+                    // if we
+                    // can adopt it - we'll assume we can adopt and log
+                    Log.i(LOG_TAG,
+                            "Assuming we can get permission " + permission
+                                    + " as running on instant app");
+                    return;
+                }
+
+                TestApis.permissions().throwPermissionException(
+                        "Can not get required permission", permission);
             }
 
-            if (TestApis.packages().instrumented().isInstantApp()) {
-                // Instant Apps aren't able to know the permissions of shell so we can't know if we
-                // can adopt it - we'll assume we can adopt and log
-                Log.i(LOG_TAG,
-                        "Assuming we can get permission " + permission
-                                + " as running on instant app");
-                return;
+            if (TestApis.permissions().adoptablePermissions().contains(permission)) {
+                requireNoPermissionsInstrumentation("Requires permission " + permission);
+            } else if (mPermissionsInstrumentationPackagePermissions.contains(permission)) {
+                requirePermissionsInstrumentation("Requires permission " + permission);
+            } else {
+                // Can't get permission at all - error (including the permissions for both)
+                TestApis.permissions().throwPermissionException(
+                        "Can not get permission " + permission + " including by instrumenting "
+                                + mPermissionsInstrumentationPackage
+                                + "\n " + mPermissionsInstrumentationPackage + " permissions: "
+                                + mPermissionsInstrumentationPackagePermissions,
+                        permission
+                );
             }
-
-            TestApis.permissions().throwPermissionException(
-                    "Can not get required permission", permission);
-        }
-
-        if (TestApis.permissions().adoptablePermissions().contains(permission)) {
-            requireNoPermissionsInstrumentation("Requires permission " + permission);
-        } else if (mPermissionsInstrumentationPackagePermissions.contains(permission)) {
-            requirePermissionsInstrumentation("Requires permission " + permission);
-        } else {
-            // Can't get permission at all - error (including the permissions for both)
-            TestApis.permissions().throwPermissionException(
-                    "Can not get permission " + permission + " including by instrumenting "
-                            + mPermissionsInstrumentationPackage
-                            + "\n " + mPermissionsInstrumentationPackage + " permissions: "
-                            + mPermissionsInstrumentationPackagePermissions,
-                    permission
-            );
-        }
+        });
     }
 
     private void switchToUser(UserReference user) {
-        UserReference currentUser = TestApis.users().current();
-        if (!currentUser.equals(user)) {
-            if (mOriginalSwitchedUser == null) {
-                mOriginalSwitchedUser = currentUser;
+        mLogger.method("switchToUser", user, () -> {
+            UserReference currentUser = TestApis.users().current();
+            if (!currentUser.equals(user)) {
+                if (mOriginalSwitchedUser == null) {
+                    mOriginalSwitchedUser = currentUser;
+                }
+                user.switchTo();
             }
-            user.switchTo();
-        }
+        });
     }
 
     private void switchFromUser(UserReference user) {
-        UserReference currentUser = TestApis.users().current();
-        if (!currentUser.equals(user)) {
-            return;
-        }
-
-        // We need to find a different user to switch to
-        // full users only, starting with lowest ID
-        List<UserReference> users = new ArrayList<>(TestApis.users().all());
-        users.sort(Comparator.comparingInt(UserReference::id));
-
-        for (UserReference otherUser : users) {
-            if (otherUser.equals(user)) {
-                continue;
+        mLogger.method("switchFromUser", user, () -> {
+            UserReference currentUser = TestApis.users().current();
+            if (!currentUser.equals(user)) {
+                return;
             }
 
-            if (otherUser.parent() != null) {
-                continue;
+            // We need to find a different user to switch to
+            // full users only, starting with lowest ID
+            List<UserReference> users = new ArrayList<>(TestApis.users().all());
+            users.sort(Comparator.comparingInt(UserReference::id));
+
+            for (UserReference otherUser : users) {
+                if (otherUser.equals(user)) {
+                    continue;
+                }
+
+                if (otherUser.parent() != null) {
+                    continue;
+                }
+
+                switchToUser(otherUser);
+                return;
             }
 
-            switchToUser(otherUser);
-            return;
-        }
-
-        // There are no users to switch to so we'll create one
-        ensureHasUser(SECONDARY_USER_TYPE_NAME,
-                /* installInstrumentedApp= */ OptionalBoolean.ANY,
-                /* switchedToUser= */ OptionalBoolean.TRUE);
+            // There are no users to switch to so we'll create one
+            ensureHasUser(SECONDARY_USER_TYPE_NAME,
+                    /* installInstrumentedApp= */ OptionalBoolean.ANY,
+                    /* switchedToUser= */ OptionalBoolean.TRUE);
+        });
     }
 
     private void requireNotHeadlessSystemUserMode() {
-        assumeFalse("This test is not supported on headless system user devices",
-                TestApis.users().isHeadlessSystemUserMode());
+        mLogger.method("requireNotHeadlessSystemUserMode", () -> {
+            assumeFalse("This test is not supported on headless system user devices",
+                    TestApis.users().isHeadlessSystemUserMode());
+        });
     }
 
     private void requireHeadlessSystemUserMode() {
-        assumeTrue("This test is only supported on headless system user devices",
-                TestApis.users().isHeadlessSystemUserMode());
+        mLogger.method("requireHeadlessSystemUserMode", () -> {
+            assumeTrue("This test is only supported on headless system user devices",
+                    TestApis.users().isHeadlessSystemUserMode());
+        });
     }
 
     private void requireLowRamDevice(String reason, FailureMode failureMode) {
-        checkFailOrSkip(reason,
-                TestApis.context().instrumentedContext()
-                        .getSystemService(ActivityManager.class)
-                        .isLowRamDevice(),
-                failureMode);
+        mLogger.method("requireLowRamDevice", reason, failureMode, () -> {
+            checkFailOrSkip(reason,
+                    TestApis.context().instrumentedContext()
+                            .getSystemService(ActivityManager.class)
+                            .isLowRamDevice(),
+                    failureMode);
+        });
     }
 
     private void requireNotLowRamDevice(String reason, FailureMode failureMode) {
-        checkFailOrSkip(reason,
-                !TestApis.context().instrumentedContext()
-                        .getSystemService(ActivityManager.class)
-                        .isLowRamDevice(),
-                failureMode);
+        mLogger.method("requireNotLowRamDevice", reason, failureMode, () -> {
+            checkFailOrSkip(reason,
+                    !TestApis.context().instrumentedContext()
+                            .getSystemService(ActivityManager.class)
+                            .isLowRamDevice(),
+                    failureMode);
+        });
     }
 
     private void ensureScreenIsOn() {
-        TestApis.device().wakeUp();
+        mLogger.method("ensureScreenIsOn", () -> {
+            TestApis.device().wakeUp();
+        });
     }
 
     private void ensurePasswordSet(UserType forUser, String password) {
-        UserReference user = resolveUserTypeToUser(forUser);
+        mLogger.method("ensurePasswordSet", forUser, password, () -> {
+            UserReference user = resolveUserTypeToUser(forUser);
 
-        if (user.hasPassword()) {
-            return;
-        }
+            if (user.hasPassword()) {
+                return;
+            }
 
-        try {
-            user.setPassword(password);
-        } catch (NeneException e) {
-            throw new AssertionError("Require password set but error when setting password", e);
-        }
-        mUsersSetPasswords.add(user);
+            try {
+                user.setPassword(password);
+            } catch (NeneException e) {
+                throw new AssertionError("Require password set but error when setting "
+                        + "password on user " + user, e);
+            }
+            mUsersSetPasswords.add(user);
+        });
     }
 
     private void ensurePasswordNotSet(UserType forUser) {
-        UserReference user = resolveUserTypeToUser(forUser);
+        mLogger.method("ensurePasswordNotSet", forUser, () -> {
+            UserReference user = resolveUserTypeToUser(forUser);
 
-        if (!user.hasPassword()) {
-            return;
-        }
+            if (!user.hasPassword()) {
+                return;
+            }
 
-        try {
-            user.clearPassword(DEFAULT_PASSWORD);
-        } catch (NeneException e
-        ) {
-            throw new AssertionError(
-                    "Test requires user " + user + " does not have a password. "
-                            + "Password is set and is not DEFAULT_PASSWORD.");
-        }
-        mUsersSetPasswords.remove(user);
+            try {
+                user.clearPassword(DEFAULT_PASSWORD);
+            } catch (NeneException e
+            ) {
+                throw new AssertionError(
+                        "Test requires user " + user + " does not have a password. "
+                                + "Password is set and is not DEFAULT_PASSWORD.");
+            }
+            mUsersSetPasswords.remove(user);
+        });
     }
 
     private void ensureBluetoothEnabled() {
-        if (mOriginalBluetoothEnabled == null) {
-            mOriginalBluetoothEnabled = TestApis.bluetooth().isEnabled();
-        }
-        TestApis.bluetooth().setEnabled(true);
+        mLogger.method("ensureBluetoothEnabled", () -> {
+            if (mOriginalBluetoothEnabled == null) {
+                mOriginalBluetoothEnabled = TestApis.bluetooth().isEnabled();
+            }
+            TestApis.bluetooth().setEnabled(true);
+        });
     }
 
     private void ensureBluetoothDisabled() {
-        if (mOriginalBluetoothEnabled == null) {
-            mOriginalBluetoothEnabled = TestApis.bluetooth().isEnabled();
-        }
-        TestApis.bluetooth().setEnabled(false);
+        mLogger.method("ensureBluetoothDisabled", () -> {
+            if (mOriginalBluetoothEnabled == null) {
+                mOriginalBluetoothEnabled = TestApis.bluetooth().isEnabled();
+            }
+            TestApis.bluetooth().setEnabled(false);
+        });
     }
 }
diff --git a/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/logging/CommonLogger.java b/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/logging/CommonLogger.java
new file mode 100644
index 0000000..7bf2a5e
--- /dev/null
+++ b/common/device-side/bedstead/nene/common/src/main/java/com/android/bedstead/nene/logging/CommonLogger.java
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.bedstead.nene.logging;
+
+import java.util.function.Supplier;
+
+/**
+ * Methods used for logging.
+ */
+public interface CommonLogger {
+
+    interface RunnableThrows<T extends Throwable> {
+        void run() throws T;
+    }
+
+    interface SupplierThrows<V, T extends Throwable> {
+        V get() throws T;
+    }
+
+    void constructor(Runnable method);
+    void constructor(Object... args);
+    void constructor(Object arg1, Runnable method);
+    void constructor(Object arg1, Object arg2, Runnable method);
+    void constructor(Object arg1, Object arg2, Object arg3, Runnable method);
+    void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Runnable method);
+    void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Runnable method);
+    void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Runnable method);
+    void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Runnable method);
+
+    void method(String name, Runnable method);
+    void method(String name, Object arg1, Runnable method);
+    void method(String name, Object arg1, Object arg2, Runnable method);
+    void method(String name, Object arg1, Object arg2, Object arg3, Runnable method);
+    void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Runnable method);
+    void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Runnable method);
+    void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Runnable method);
+    void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Runnable method);
+
+    <T extends Throwable> void method(Class<T> throwableClass, String name, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, RunnableThrows<T> method) throws T;
+    <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, RunnableThrows<T> method) throws T;
+
+    <R> R method(String name, Supplier<R> method);
+    <R> R method(String name, Object arg1, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Object arg3, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Supplier<R> method);
+    <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Supplier<R> method);
+
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, SupplierThrows<R, T> method) throws T;
+    <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, SupplierThrows<R, T> method) throws T;
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/TestApis.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/TestApis.java
index 5a4cf4e..7fa094f 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/TestApis.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/TestApis.java
@@ -24,6 +24,7 @@
 import com.android.bedstead.nene.device.Device;
 import com.android.bedstead.nene.devicepolicy.DevicePolicy;
 import com.android.bedstead.nene.inputmethods.InputMethods;
+import com.android.bedstead.nene.instrumentation.Instrumentation;
 import com.android.bedstead.nene.location.Locations;
 import com.android.bedstead.nene.notifications.Notifications;
 import com.android.bedstead.nene.packages.Packages;
@@ -111,6 +112,12 @@
         return InputMethods.sInstance;
     }
 
+    /** Access Test APIs related to instrumentation. */
+    @Experimental
+    public static Instrumentation instrumentation() {
+        return Instrumentation.sInstance;
+    }
+
     /** @deprecated Use statically */
     @Deprecated()
     public TestApis() {
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/Accessibility.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/Accessibility.java
index bf3e235..1df7804 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/Accessibility.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/Accessibility.java
@@ -22,6 +22,7 @@
 
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.annotations.Experimental;
+import com.android.bedstead.nene.logging.Logger;
 
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -35,8 +36,10 @@
     private static final AccessibilityManager sAccessibilityManager =
             TestApis.context().instrumentedContext().getSystemService(AccessibilityManager.class);
 
-    private Accessibility() {
+    private final Logger mLogger = Logger.forInstance(this);
 
+    private Accessibility() {
+        mLogger.constructor();
     }
 
     /**
@@ -45,10 +48,11 @@
      * <p>See {@link AccessibilityManager#getInstalledAccessibilityServiceList()}.
      */
     public Set<AccessibilityService> installedAccessibilityServices() {
-        return sAccessibilityManager
-                .getInstalledAccessibilityServiceList().stream()
-                .map(AccessibilityService::new)
-                .collect(Collectors.toSet());
+        return mLogger.method("installedAccessibilityServices", () ->
+                sAccessibilityManager
+                        .getInstalledAccessibilityServiceList().stream()
+                        .map(AccessibilityService::new)
+                        .collect(Collectors.toSet()));
     }
 
     /**
@@ -57,9 +61,10 @@
      * <p>See {@link AccessibilityManager#getEnabledAccessibilityServiceList(int)}.
      */
     public Set<AccessibilityService> enabledAccessibilityServices() {
-        return sAccessibilityManager
-                .getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK)
-                .stream().map(AccessibilityService::new)
-                .collect(Collectors.toSet());
+        return mLogger.method("enabledAccessibilityServices", () ->
+                sAccessibilityManager
+                        .getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK)
+                        .stream().map(AccessibilityService::new)
+                        .collect(Collectors.toSet()));
     }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/AccessibilityService.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/AccessibilityService.java
index 834f3aa..e85b7a5 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/AccessibilityService.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/accessibility/AccessibilityService.java
@@ -19,6 +19,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.logging.Logger;
 import com.android.bedstead.nene.packages.Package;
 
 /**
@@ -26,14 +27,18 @@
  */
 public final class AccessibilityService {
 
-    private final AccessibilityServiceInfo mServiceInfo;
+    private AccessibilityServiceInfo mServiceInfo;
+    private final Logger mLogger = Logger.forInstance(this);
 
     AccessibilityService(AccessibilityServiceInfo serviceInfo) {
-        mServiceInfo = serviceInfo;
+        mLogger.constructor(serviceInfo, () -> {
+            mServiceInfo = serviceInfo;
+        });
     }
 
     /** The package of the accessibility service. */
     public Package pkg() {
-        return TestApis.packages().find(mServiceInfo.getResolveInfo().serviceInfo.packageName);
+        return mLogger.method("pkg", () ->
+                TestApis.packages().find(mServiceInfo.getResolveInfo().serviceInfo.packageName));
     }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
index 1a8e578..aeabf3d 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/bluetooth/Bluetooth.java
@@ -32,6 +32,7 @@
 import android.content.Intent;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.logging.Logger;
 import com.android.bedstead.nene.permissions.PermissionContext;
 import com.android.bedstead.nene.utils.Poll;
 import com.android.compatibility.common.util.BlockingBroadcastReceiver;
@@ -46,86 +47,98 @@
             sContext.getSystemService(BluetoothManager.class);
     private static final BluetoothAdapter sBluetoothAdapter = sBluetoothManager.getAdapter();
 
-    private Bluetooth() {
+    private final Logger mLogger = Logger.forInstance(this);
 
+    private Bluetooth() {
+        mLogger.constructor();
     }
 
     /** Enable or disable bluetooth on the device. */
     public void setEnabled(boolean enabled) {
-        if (isEnabled() == enabled) {
-            return;
-        }
+        mLogger.method("setEnabled", enabled, () -> {
+            if (isEnabled() == enabled) {
+                return;
+            }
 
-        if (enabled) {
-            enable();
-        } else {
-            disable();
-        }
+            if (enabled) {
+                enable();
+            } else {
+                disable();
+            }
+        });
     }
 
     private void enable() {
-        try (PermissionContext p =
-                     TestApis.permissions()
-                             .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL)
-                             .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
-            BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
-                    sContext,
-                    BluetoothAdapter.ACTION_STATE_CHANGED,
-                    this::isStateEnabled).register();
+        mLogger.method("enable", () -> {
+            try (PermissionContext p =
+                         TestApis.permissions()
+                                 .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL)
+                                 .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
+                BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
+                        sContext,
+                        BluetoothAdapter.ACTION_STATE_CHANGED,
+                        this::isStateEnabled).register();
 
-            try {
-                assertThat(sBluetoothAdapter.enable()).isTrue();
+                try {
+                    assertThat(sBluetoothAdapter.enable()).isTrue();
 
-                r.awaitForBroadcast();
-                Poll.forValue("Bluetooth Enabled", this::isEnabled)
-                        .toBeEqualTo(true)
-                        .errorOnFail()
-                        .await();
-            } finally {
-                r.unregisterQuietly();
+                    r.awaitForBroadcast();
+                    Poll.forValue("Bluetooth Enabled", this::isEnabled)
+                            .toBeEqualTo(true)
+                            .errorOnFail()
+                            .await();
+                } finally {
+                    r.unregisterQuietly();
+                }
             }
-        }
+        });
     }
 
     private void disable() {
-        try (PermissionContext p =
-                     TestApis.permissions()
-                             .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL)
-                             .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
-            BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
-                    sContext,
-                    BluetoothAdapter.ACTION_STATE_CHANGED,
-                    this::isStateDisabled).register();
+        mLogger.method("disable", () -> {
+            try (PermissionContext p =
+                         TestApis.permissions()
+                                 .withPermission(BLUETOOTH_CONNECT, INTERACT_ACROSS_USERS_FULL)
+                                 .withPermissionOnVersionAtLeast(T, NETWORK_SETTINGS)) {
+                BlockingBroadcastReceiver r = BlockingBroadcastReceiver.create(
+                        sContext,
+                        BluetoothAdapter.ACTION_STATE_CHANGED,
+                        this::isStateDisabled).register();
 
-            try {
-                assertThat(sBluetoothAdapter.disable()).isTrue();
+                try {
+                    assertThat(sBluetoothAdapter.disable()).isTrue();
 
-                r.awaitForBroadcast();
-                Poll.forValue("Bluetooth Enabled", this::isEnabled)
-                        .toBeEqualTo(false)
-                        .errorOnFail()
-                        .await();
-            } finally {
-                r.unregisterQuietly();
+                    r.awaitForBroadcast();
+                    Poll.forValue("Bluetooth Enabled", this::isEnabled)
+                            .toBeEqualTo(false)
+                            .errorOnFail()
+                            .await();
+                } finally {
+                    r.unregisterQuietly();
+                }
             }
-        }
+        });
     }
 
     /** {@code true} if bluetooth is enabled. */
     public boolean isEnabled() {
-        try (PermissionContext p =
-                     TestApis.permissions().withPermissionOnVersionAtMost(R, BLUETOOTH)) {
-            return sBluetoothAdapter.isEnabled();
-        }
+        return mLogger.method("isEnabled", () -> {
+            try (PermissionContext p =
+                         TestApis.permissions().withPermissionOnVersionAtMost(R, BLUETOOTH)) {
+                return sBluetoothAdapter.isEnabled();
+            }
+        });
     }
 
     private boolean isStateEnabled(Intent intent) {
-        return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
-                == BluetoothAdapter.STATE_ON;
+        return mLogger.method("isStateEnabled", intent, () ->
+                intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
+                        == BluetoothAdapter.STATE_ON);
     }
 
     private boolean isStateDisabled(Intent intent) {
-        return intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
-                == BluetoothAdapter.STATE_OFF;
+        return mLogger.method("isStateDisabled", intent, () ->
+                intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
+                        == BluetoothAdapter.STATE_OFF);
     }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
index 24bbaee..b88c054 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
@@ -146,6 +146,7 @@
 
             Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
                     .toNotBeEqualTo(true)
+                    .timeout(Duration.ofMinutes(5))
                     .errorOnFail()
                     .await();
         }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
index dd6a3e9..528d532 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.os.Build.VERSION.SDK_INT;
 
+import static com.android.bedstead.nene.permissions.CommonPermissions.FORCE_DEVICE_POLICY_MANAGER_LOGS;
 import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_DEVICE_ADMINS;
 import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS;
 
@@ -47,12 +48,9 @@
 import com.android.bedstead.nene.utils.ShellCommand;
 import com.android.bedstead.nene.utils.ShellCommandUtils;
 import com.android.bedstead.nene.utils.Versions;
-import com.android.compatibility.common.util.PollingCheck;
 
 import java.time.Duration;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -99,7 +97,8 @@
                             return false; // Just retry on old versions as we don't have stderr
                         }
                         if (ex instanceof AdbException) {
-                            if (((AdbException) ex).error().contains("is being removed")) {
+                            String error = ((AdbException) ex).error();
+                            if (error.contains("is being removed")) {
                                 return false;
                             }
                         }
@@ -173,17 +172,16 @@
                 // TODO(b/187925230): If it fails, we check for terminal failure states - and if not
                 //  we retry because if the DO/PO was recently removed, it can take some time
                 //  to be allowed to set it again
-                retryIfNotTerminal(
-                        () -> {
+                Retry.logic(() -> {
                             devicePolicyManager.setActiveAdmin(deviceOwnerComponent,
                                     /* refreshing= */ true, user.id());
                             setDeviceOwnerOnly(devicePolicyManager,
                                     deviceOwnerComponent, "Nene", user.id());
-                        },
-                        () -> checkForTerminalDeviceOwnerFailures(
-                                user, deviceOwnerComponent, /* allowAdditionalUsers= */ true),
-                        NeneException.class, IllegalArgumentException.class);
-            } catch (IllegalStateException | SecurityException e) {
+                }).terminalException((e) -> checkForTerminalDeviceOwnerFailures(
+                        user, deviceOwnerComponent, /* allowAdditionalUsers= */ true))
+                        .timeout(Duration.ofMinutes(5))
+                        .run();
+            } catch (Throwable e) {
                 throw new NeneException("Error setting device owner", e);
             }
         } finally {
@@ -234,44 +232,6 @@
         }
     }
 
-    /**
-     * Runs {@code operation}. If it fails, runs {@code terminalCheck} and then retries
-     * {@code operation} until it does not fail or for a maximum of 30 seconds.
-     *
-     * <p>The {@code operation} is considered to be successful if it does not throw an exception
-     */
-    private void retryIfNotTerminal(
-            Runnable operation, Runnable terminalCheck,
-            Class<? extends RuntimeException>... exceptions) {
-        Set<Class<? extends RuntimeException>> exceptionSet =
-                new HashSet<>(Arrays.asList(exceptions));
-        try {
-            operation.run();
-        } catch (RuntimeException e) {
-            if (!exceptionSet.contains(e.getClass())) {
-                throw e;
-            }
-
-            terminalCheck.run();
-
-            try {
-                PollingCheck.waitFor(() -> {
-                    try {
-                        operation.run();
-                        return true;
-                    } catch (RuntimeException e2) {
-                        if (!exceptionSet.contains(e2.getClass())) {
-                            throw e2;
-                        }
-                        return false;
-                    }
-                });
-            } catch (AssertionError e3) {
-                operation.run();
-            }
-        }
-    }
-
     private DeviceOwner setDeviceOwnerPreS(ComponentName deviceOwnerComponent) {
         UserReference user = TestApis.users().system();
 
@@ -282,18 +242,23 @@
         // TODO(b/187925230): If it fails, we check for terminal failure states - and if not
         //  we retry because if the device owner was recently removed, it can take some time
         //  to be allowed to set it again
-        retryIfNotTerminal(
-                () -> command.executeOrThrowNeneException("Could not set device owner for user "
-                        + user + " component " + deviceOwnerComponent),
-                () -> checkForTerminalDeviceOwnerFailures(
-                    user, deviceOwnerComponent, /* allowAdditionalUsers= */ false));
+
+        try {
+            Retry.logic(command::execute)
+                .terminalException((e) -> checkForTerminalDeviceOwnerFailures(
+                            user, deviceOwnerComponent, /* allowAdditionalUsers= */ false))
+                    .timeout(Duration.ofMinutes(5))
+                    .run();
+        } catch (Throwable e) {
+            throw new NeneException("Error setting device owner", e);
+        }
 
         return new DeviceOwner(user,
                 TestApis.packages().find(
                         deviceOwnerComponent.getPackageName()), deviceOwnerComponent);
     }
 
-    private void checkForTerminalDeviceOwnerFailures(
+    private boolean checkForTerminalDeviceOwnerFailures(
             UserReference user, ComponentName deviceOwnerComponent, boolean allowAdditionalUsers) {
         DeviceOwner deviceOwner = getDeviceOwner();
         if (deviceOwner != null) {
@@ -328,6 +293,8 @@
 
         }
         // TODO(scottjonathan): Check accounts
+
+        return false;
     }
 
     private boolean componentCanBeSetAsDeviceAdmin(ComponentName component, UserReference user) {
@@ -390,4 +357,28 @@
                     .getPolicyExemptApps();
         }
     }
+
+    @Experimental
+    public void forceNetworkLogs() {
+        try (PermissionContext p = TestApis.permissions().withPermission(FORCE_DEVICE_POLICY_MANAGER_LOGS)) {
+            long throttle = TestApis.context()
+                    .instrumentedContext()
+                    .getSystemService(DevicePolicyManager.class)
+                    .forceNetworkLogs();
+
+            if (throttle == -1) {
+                throw new NeneException("Error forcing network logs: returned -1");
+            }
+            if (throttle == 0) {
+                return;
+            }
+            try {
+                Thread.sleep(throttle);
+            } catch (InterruptedException e) {
+                throw new NeneException("Error waiting for network log throttle", e);
+            }
+
+            forceNetworkLogs();
+        }
+    }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
index a259203..ce73f43 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
@@ -138,6 +138,7 @@
 
             Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
                     .toNotBeEqualTo(true)
+                    .timeout(Duration.ofMinutes(5))
                     .errorOnFail()
                     .await();
         }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Arguments.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Arguments.java
new file mode 100644
index 0000000..8a4578a
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Arguments.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.bedstead.nene.instrumentation;
+
+import android.os.Bundle;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+/** Access to Instrumentation Arguments. */
+public final class Arguments {
+
+    public static final Arguments sInstance = new Arguments();
+
+    private final Bundle mArguments = InstrumentationRegistry.getArguments();
+
+    private Arguments() {
+    }
+
+    /** Gets int instrumentation arg. */
+    public int getInt(String key) {
+        return mArguments.getInt(key);
+    }
+
+    /** Gets int instrumentation arg. */
+    public int getInt(String key, int defaultValue) {
+        return mArguments.getInt(key, defaultValue);
+    }
+
+    /** Gets boolean instrumentation arg. */
+    public boolean getBoolean(String key) {
+        return mArguments.getBoolean(key);
+    }
+
+    /** Gets boolean instrumentation arg. */
+    public boolean getBoolean(String key, boolean defaultValue) {
+        return mArguments.getBoolean(key, defaultValue);
+    }
+
+    /** Gets string instrumentation arg. */
+    public String getString(String key) {
+        return mArguments.getString(key);
+    }
+
+    /** Gets string instrumentation arg. */
+    public String getString(String key, String defaultValue) {
+        return mArguments.getString(key, defaultValue);
+    }
+
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Instrumentation.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Instrumentation.java
new file mode 100644
index 0000000..1a0d4d1
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/instrumentation/Instrumentation.java
@@ -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 com.android.bedstead.nene.instrumentation;
+
+/** Test APIs related to Instrumentation. */
+public final class Instrumentation {
+    public static final Instrumentation sInstance = new Instrumentation();
+
+    private Instrumentation() {
+
+    }
+
+    /** Interact with instrumentation arguments. */
+    public Arguments arguments() {
+        return Arguments.sInstance;
+    }
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/location/LocationProvider.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/location/LocationProvider.java
index 3551aae..7bddceb 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/location/LocationProvider.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/location/LocationProvider.java
@@ -16,8 +16,8 @@
 
 package com.android.bedstead.nene.location;
 
-import static com.android.bedstead.nene.appops.AppOpsMode.ALLOWED;
 import static com.android.bedstead.nene.appops.AppOpsMode.DEFAULT;
+import static com.android.bedstead.nene.appops.CommonAppOps.OPSTR_MOCK_LOCATION;
 
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -27,6 +27,7 @@
 import android.os.SystemClock;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.permissions.PermissionContext;
 
 /** A test location provider on the device. */
 public final class LocationProvider implements AutoCloseable {
@@ -49,18 +50,18 @@
     }
 
     private void addTestProvider() {
-        // TODO(b/215671032): Allow app op to be adopted with permissions
-        TestApis.packages().instrumented().appOps().set(AppOpsManager.OPSTR_MOCK_LOCATION, ALLOWED);
-        sLocationManager.addTestProvider(sProviderName,
-                /* requiresNetwork= */ true,
-                /* requiresSatellite= */ false,
-                /* requiresCell= */ true,
-                /* hasMonetaryCost= */ false,
-                /* supportsAltitude= */ false,
-                /* supportsSpeed= */ false,
-                /* supportsBearing= */ false,
-                Criteria.POWER_MEDIUM,
-                Criteria.ACCURACY_COARSE);
+        try (PermissionContext p = TestApis.permissions().withAppOp(OPSTR_MOCK_LOCATION)) {
+            sLocationManager.addTestProvider(sProviderName,
+                    /* requiresNetwork= */ true,
+                    /* requiresSatellite= */ false,
+                    /* requiresCell= */ true,
+                    /* hasMonetaryCost= */ false,
+                    /* supportsAltitude= */ false,
+                    /* supportsSpeed= */ false,
+                    /* supportsBearing= */ false,
+                    Criteria.POWER_MEDIUM,
+                    Criteria.ACCURACY_COARSE);
+        }
     }
 
     private void enableTestProvider() {
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/AdbLogger.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/AdbLogger.java
new file mode 100644
index 0000000..fa15935
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/AdbLogger.java
@@ -0,0 +1,359 @@
+/*
+ * 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 com.android.bedstead.nene.logging;
+
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/**
+ * {@link Logger} which passes all logs to ADB.
+ */
+public final class AdbLogger implements Logger {
+
+    public static final String KEY = "ADB";
+
+    private final String mTag;
+
+    AdbLogger(Object instance) {
+        mTag = "NNL_" + instance.getClass().getCanonicalName() + "@"
+                + Integer.toHexString(instance.hashCode());
+    }
+
+    @Override
+    public void constructor(Runnable method) {
+        constructor(method, new Object[]{});
+    }
+
+    @Override
+    public void constructor(Object... args) {
+        constructor(() -> {}, args);
+    }
+
+    @Override
+    public void constructor(Object arg1, Runnable method) {
+        constructor(method, arg1);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Runnable method) {
+        constructor(method, arg1, arg2);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Runnable method) {
+        constructor(method, arg1, arg2, arg3);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Runnable method) {
+        constructor(method, arg1, arg2, arg3, arg4);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Runnable method) {
+        constructor(method, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Runnable method) {
+        constructor(method, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Object arg7, Runnable method) {
+        constructor(method, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    private void constructor(Runnable method, Object... args) {
+        begin("constructor", args);
+        try {
+            method.run();
+            end();
+        } catch (Throwable t) {
+            exception(t);
+            throw t;
+        }
+    }
+
+    @Override
+    public void method(String name, Runnable method) {
+        method(method, name);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Runnable method) {
+        method(method, name, arg1);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Runnable method) {
+        method(method, name, arg1, arg2);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Runnable method) {
+        method(method, name, arg1, arg2, arg3);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Runnable method) {
+        method(method, name, arg1, arg2, arg3, arg4);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Runnable method) {
+        method(method, name, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Runnable method) {
+        method(method, name, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Object arg7, Runnable method) {
+        method(method, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name,
+            RunnableThrows<T> method) throws T {
+        method(method, name);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            RunnableThrows<T> method) throws T {
+        method(method, name, arg1);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2, arg3);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2, arg3, arg4);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6,
+            RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
+            RunnableThrows<T> method) throws T {
+        method(method, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    private void method(Runnable method, String name, Object... args) {
+        begin(name, args);
+        try {
+            method.run();
+            end();
+        } catch (Throwable t) {
+            exception(t);
+            throw t;
+        }
+    }
+
+    private <T extends Throwable> void method(
+            RunnableThrows<T> method, String name, Object... args) throws T {
+        begin(name, args);
+        try {
+            method.run();
+            end();
+        } catch (Throwable t) {
+            exception(t);
+            throw t;
+        }
+    }
+
+    @Override
+    public <R> R method(String name, Supplier<R> method) {
+        return method(method, name);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Supplier<R> method) {
+        return method(method, name, arg1);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Supplier<R> method) {
+        return method(method, name, arg1, arg2);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Supplier<R> method) {
+        return method(method, name, arg1, arg2, arg3);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Supplier<R> method) {
+        return method(method, name, arg1, arg2, arg3, arg4);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Supplier<R> method) {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Object arg6, Supplier<R> method) {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Object arg6, Object arg7, Supplier<R> method) {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name,
+            SupplierThrows<R, T> method) throws T {
+        return method(method, name);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1, arg2);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1, arg2, arg3);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1, arg2, arg3, arg4);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, SupplierThrows<R, T> method)
+            throws T {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6,
+            SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
+            SupplierThrows<R, T> method) throws T {
+        return method(method, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    private <R> R method(Supplier<R> method, String name, Object... args) {
+        begin(name, args);
+        try {
+            R value = method.get();
+            end(value);
+            return value;
+        } catch (Throwable t) {
+            exception(t);
+            throw t;
+        }
+    }
+
+    private <R, T extends Throwable> R method(
+            SupplierThrows<R, T> method, String name, Object... args) throws T {
+        begin(name, args);
+        try {
+            R value = method.get();
+            end(value);
+            return value;
+        } catch (Throwable t) {
+            exception(t);
+            throw t;
+        }
+    }
+
+    private void begin(String title, Object... args) {
+        Log.i(mTag, "BEGIN " + title + formatArgs(args));
+    }
+
+    private void exception(Throwable t) {
+        Log.i(mTag, "END EXCEPTION ("  + t + ")");
+    }
+
+    private void end(Object ret) {
+        Log.i(mTag, "END ("  + ret + ")");
+    }
+
+    private void end() {
+        Log.i(mTag, "END");
+    }
+
+    private String formatArgs(Object[] args) {
+        if (args.length == 0) {
+            return "";
+        }
+
+        return " (" + Arrays.stream(args).map(Object::toString)
+                .collect(Collectors.joining(", ")) + ")";
+    }
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/Logger.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/Logger.java
new file mode 100644
index 0000000..44a5df3e
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/Logger.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.android.bedstead.nene.logging;
+
+import com.android.bedstead.nene.TestApis;
+
+import java.util.function.Function;
+
+/**
+ * Logger used for tests and test infrastructure.
+ *
+ * <p>By default, logs will be dropped silently.
+ *
+ * <p>To change this, pass the LOGGING instrumentation argument.
+ *
+ * <p>E.g. {@code -- --instrumentation-arg LOGGING ADB} to log to ADB.
+ */
+public interface Logger extends CommonLogger {
+
+    /**
+     * The key to use to pass in the type of logger to use.
+     *
+     * <p>Defaults to silently dropping logs.
+     */
+    String LOGGER_KEY = "LOGGER";
+
+    Function<Object, Logger> LOG_CONSTRUCTOR =
+            TestApis.instrumentation().arguments().getString(LOGGER_KEY, "")
+                    .equals(AdbLogger.KEY) ? AdbLogger::new : (object) -> VoidLogger.sInstance;
+
+    /** Create a {@link Logger} for the given object. */
+    static Logger forInstance(Object object) {
+        return LOG_CONSTRUCTOR.apply(object);
+    }
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/VoidLogger.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/VoidLogger.java
new file mode 100644
index 0000000..53ff8a0
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/logging/VoidLogger.java
@@ -0,0 +1,268 @@
+/*
+ * 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 com.android.bedstead.nene.logging;
+
+import java.util.function.Supplier;
+
+/**
+ * {@link Logger} which drops all logs.
+ */
+public final class VoidLogger implements Logger {
+
+    public static final VoidLogger sInstance = new VoidLogger();
+
+    private VoidLogger() {
+
+    }
+
+    @Override
+    public void constructor(Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object... args) {
+
+    }
+
+    @Override
+    public void constructor(Object arg1, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void constructor(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Object arg7, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public void method(String name, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5,
+            Object arg6, Object arg7, Runnable method) {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name,
+            RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6,
+            RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <T extends Throwable> void method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
+            RunnableThrows<T> method) throws T {
+        method.run();
+    }
+
+    @Override
+    public <R> R method(String name, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Object arg6, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <R> R method(String name, Object arg1, Object arg2, Object arg3, Object arg4,
+            Object arg5, Object arg6, Object arg7, Supplier<R> method) {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name,
+            SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, SupplierThrows<R, T> method)
+            throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6,
+            SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+
+    @Override
+    public <T extends Throwable, R> R method(Class<T> throwableClass, String name, Object arg1,
+            Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
+            SupplierThrows<R, T> method) throws T {
+        return method.get();
+    }
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
index d687ab9..6592463 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Poll.java
@@ -60,7 +60,7 @@
     private static final String LOG_TAG = Poll.class.getName();
 
     private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(30);
-    private static final long SLEEP_MILLIS = 200;
+    private static final long SLEEP_MILLIS = 200; // TODO(b/223768343): Allow configuring
     private final String mValueName;
     private final ValueSupplier<E> mSupplier;
     private ValueChecker<E> mChecker = (v) -> true;
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Retry.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Retry.java
index cb44d26..8038795 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Retry.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/Retry.java
@@ -16,6 +16,8 @@
 
 package com.android.bedstead.nene.utils;
 
+import android.util.Log;
+
 import com.android.bedstead.nene.exceptions.NeneException;
 import com.android.bedstead.nene.exceptions.PollValueFailedException;
 
@@ -35,6 +37,8 @@
  */
 public final class Retry<E> {
 
+    private static final String LOG_TAG = "Retry";
+
     private final Poll<E> mPoll;
 
     /**
@@ -86,6 +90,7 @@
             return mPoll.await();
         } catch (PollValueFailedException e) {
             // We know there will be an exception cause because we aren't validating the value
+            Log.e(LOG_TAG, "Failure in retries", e);
             throw e.getCause();
         }
     }
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DelegatedAdminReceiverInfo.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DelegatedAdminReceiverInfo.java
new file mode 100644
index 0000000..f4f78e7
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/info/DelegatedAdminReceiverInfo.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.android.queryable.info;
+
+import android.app.admin.DelegatedAdminReceiver;
+
+/**
+ * Wrapper for information about a {@link DelegatedAdminReceiver}.
+ *
+ * <p>This is used instead of {@link DelegatedAdminReceiver} so that it can be easily serialized.
+ */
+@SuppressWarnings("NewApi")
+public class DelegatedAdminReceiverInfo extends BroadcastReceiverInfo {
+    public DelegatedAdminReceiverInfo(DelegatedAdminReceiver delegatedAdminReceiver) {
+        super(delegatedAdminReceiver);
+    }
+
+    public DelegatedAdminReceiverInfo(
+            Class<? extends DelegatedAdminReceiver> delegatedAdminReceiverClass) {
+        super(delegatedAdminReceiverClass);
+    }
+
+    public DelegatedAdminReceiverInfo(String delegatedAdminReceiverClassName) {
+        super(delegatedAdminReceiverClassName);
+    }
+
+    @Override
+    public String toString() {
+        return "DelegatedAdminReceiver{"
+                + "broadcastReceiver=" + super.toString()
+                + "}";
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQuery.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQuery.java
new file mode 100644
index 0000000..0e5098b
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQuery.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.queryable.queries;
+
+import android.app.admin.DelegatedAdminReceiver;
+
+import com.android.queryable.Queryable;
+import com.android.queryable.info.DelegatedAdminReceiverInfo;
+
+/** Query for a {@link DelegatedAdminReceiver}. */
+public interface DelegatedAdminReceiverQuery<E extends Queryable>
+        extends Query<DelegatedAdminReceiverInfo>  {
+
+    static DelegatedAdminReceiverQuery<DelegatedAdminReceiverQuery<?>> delegatedAdminReceiver() {
+        return new DelegatedAdminReceiverQueryHelper<>();
+    }
+
+    BroadcastReceiverQuery<E> broadcastReceiver();
+}
diff --git a/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQueryHelper.java b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQueryHelper.java
new file mode 100644
index 0000000..befdc77
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/main/java/com/android/queryable/queries/DelegatedAdminReceiverQueryHelper.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.queryable.queries;
+
+import com.android.queryable.Queryable;
+import com.android.queryable.info.DelegatedAdminReceiverInfo;
+
+/** Implementation of {@link DelegatedAdminReceiverQuery}. */
+public final class DelegatedAdminReceiverQueryHelper<E extends Queryable>
+        implements DelegatedAdminReceiverQuery<E> {
+
+    private final E mQuery;
+    private final BroadcastReceiverQueryHelper<E> mBroadcastReceiverQueryHelper;
+
+    DelegatedAdminReceiverQueryHelper() {
+        mQuery = (E) this;
+        mBroadcastReceiverQueryHelper = new BroadcastReceiverQueryHelper<>(mQuery);
+    }
+
+    public DelegatedAdminReceiverQueryHelper(E query) {
+        mQuery = query;
+        mBroadcastReceiverQueryHelper = new BroadcastReceiverQueryHelper<>(query);
+    }
+
+    @Override
+    public BroadcastReceiverQuery<E> broadcastReceiver() {
+        return mBroadcastReceiverQueryHelper;
+    }
+
+    /** {@code true} if all filters are met by {@code value}. */
+    @Override
+    public boolean matches(DelegatedAdminReceiverInfo value) {
+        return mBroadcastReceiverQueryHelper.matches(value);
+    }
+
+    @Override
+    public String describeQuery(String fieldName) {
+        return Queryable.joinQueryStrings(
+                mBroadcastReceiverQueryHelper.describeQuery(fieldName + ".broadcastReceiver")
+        );
+    }
+}
diff --git a/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DelegatedAdminReceiverInfoTest.java b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DelegatedAdminReceiverInfoTest.java
new file mode 100644
index 0000000..3e34752
--- /dev/null
+++ b/common/device-side/bedstead/queryable/src/test/java/com/android/queryable/info/DelegatedAdminReceiverInfoTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 com.android.queryable.info;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DelegatedAdminReceiver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DelegatedAdminReceiverInfoTest {
+
+    private static final Class<? extends DelegatedAdminReceiver> TEST_DEVICE_ADMIN_RECEIVER_CLASS =
+            DelegatedAdminReceiver.class;
+    private static final String TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME =
+            DelegatedAdminReceiver.class.getName();
+    private static final String TEST_DEVICE_ADMIN_RECEIVER_SIMPLE_NAME =
+            DelegatedAdminReceiver.class.getSimpleName();
+    private static final DelegatedAdminReceiver TEST_DEVICE_ADMIN_RECEIVER_INSTANCE =
+            new DelegatedAdminReceiver();
+
+    @Test
+    public void classConstructor_setsClassName() {
+        DelegatedAdminReceiverInfo delegatedAdminReceiverInfo = new DelegatedAdminReceiverInfo(
+                TEST_DEVICE_ADMIN_RECEIVER_CLASS);
+
+        assertThat(delegatedAdminReceiverInfo.className())
+                .isEqualTo(TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void instanceConstructor_setsClassName() {
+        DelegatedAdminReceiverInfo delegatedAdminReceiverInfo = new DelegatedAdminReceiverInfo(
+                TEST_DEVICE_ADMIN_RECEIVER_INSTANCE);
+
+        assertThat(delegatedAdminReceiverInfo.className())
+                .isEqualTo(TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void stringConstructor_setsClassName() {
+        DelegatedAdminReceiverInfo delegatedAdminReceiverInfo = new DelegatedAdminReceiverInfo(
+                TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(delegatedAdminReceiverInfo.className())
+                .isEqualTo(TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+    }
+
+    @Test
+    public void simpleName_getsSimpleName() {
+        DelegatedAdminReceiverInfo delegatedAdminReceiverInfo = new DelegatedAdminReceiverInfo(
+                TEST_DEVICE_ADMIN_RECEIVER_CLASS_NAME);
+
+        assertThat(delegatedAdminReceiverInfo.simpleName())
+                .isEqualTo(TEST_DEVICE_ADMIN_RECEIVER_SIMPLE_NAME);
+    }
+}
diff --git a/common/device-side/bedstead/testapp/CommonManifest.xml b/common/device-side/bedstead/testapp/CommonManifest.xml
index 836db22..c3232fa 100644
--- a/common/device-side/bedstead/testapp/CommonManifest.xml
+++ b/common/device-side/bedstead/testapp/CommonManifest.xml
@@ -140,7 +140,9 @@
     <uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
     <uses-permission android:name="android.permission.SET_ALWAYS_FINISH" />
     <uses-permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" />
-    <uses-permission android:name="android.permission.ACCESS_SUPPLEMENTAL_APIS" />
+    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
+    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
+    <uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCES" />
     <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
     <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
@@ -193,4 +195,4 @@
                   android:exported="true" />
     </application>
     <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28"/>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/common/device-side/bedstead/testapp/manifests/DelegateManifest.xml b/common/device-side/bedstead/testapp/manifests/DelegateManifest.xml
index 6740e5e..2dbab47 100644
--- a/common/device-side/bedstead/testapp/manifests/DelegateManifest.xml
+++ b/common/device-side/bedstead/testapp/manifests/DelegateManifest.xml
@@ -21,6 +21,16 @@
     <application>
         <!-- Don't allow this test app to be returned by queries unless filtered by package name -->
         <meta-data android:name="testapp-package-query-only" android:value="true" />
+
+        <receiver android:name="com.android.bedstead.testapp.BaseTestAppDelegatedAdminReceiver"
+                  android:permission="android.permission.BIND_DEVICE_ADMIN"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS"/>
+                <action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
+                <action android:name="android.app.action.SECURITY_LOGS_AVAILABLE"/>
+            </intent-filter>
+        </receiver>
     </application>
     <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28"/>
 </manifest>
\ No newline at end of file
diff --git a/common/device-side/bedstead/testapp/src/library/main/java/com/android/bedstead/testapp/TestAppEvents.java b/common/device-side/bedstead/testapp/src/library/main/java/com/android/bedstead/testapp/TestAppEvents.java
index 966fb95..3c45313 100644
--- a/common/device-side/bedstead/testapp/src/library/main/java/com/android/bedstead/testapp/TestAppEvents.java
+++ b/common/device-side/bedstead/testapp/src/library/main/java/com/android/bedstead/testapp/TestAppEvents.java
@@ -26,28 +26,50 @@
 import com.android.eventlib.events.activities.ActivityStoppedEvent;
 import com.android.eventlib.events.broadcastreceivers.BroadcastReceivedEvent;
 import com.android.eventlib.events.broadcastreceivers.BroadcastReceiverEvents;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminChoosePrivateKeyAliasEvent.DelegatedAdminChoosePrivateKeyAliasEventQuery;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminReceiverEvents;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent;
+import com.android.eventlib.events.delegatedadminreceivers.DelegatedAdminSecurityLogsAvailableEvent.DelegatedAdminSecurityLogsAvailableEventQuery;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent;
+import com.android.eventlib.events.deviceadminreceivers.DelegatedAdminNetworkLogsAvailableEvent.DelegatedAdminNetworkLogsAvailableEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminBugreportFailedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminBugreportSharedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminBugreportSharingDeclinedEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminBugreportSharingDeclinedEvent.DeviceAdminBugreportSharingDeclinedEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminChoosePrivateKeyAliasEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminChoosePrivateKeyAliasEvent.DeviceAdminChoosePrivateKeyAliasEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminDisableRequestedEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminDisableRequestedEvent.DeviceAdminDisableRequestedEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminDisabledEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminEnabledEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminLockTaskModeEnteringEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminLockTaskModeEnteringEvent.DeviceAdminLockTaskModeEnteringEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminLockTaskModeExitingEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminLockTaskModeExitingEvent.DeviceAdminLockTaskModeExitingEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminNetworkLogsAvailableEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminNetworkLogsAvailableEvent.DeviceAdminNetworkLogsAvailableEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminOperationSafetyStateChangedEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminOperationSafetyStateChangedEvent.DeviceAdminOperationSafetyStateChangedEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordChangedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordExpiringEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordExpiringEvent.DeviceAdminPasswordExpiringEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordFailedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordSucceededEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminPasswordSucceededEvent.DeviceAdminPasswordSucceededEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminProfileProvisioningCompleteEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminProfileProvisioningCompleteEvent.DeviceAdminProfileProvisioningCompleteEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminReadyForUserInitializationEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminReadyForUserInitializationEvent.DeviceAdminReadyForUserInitializationEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminReceiverEvents;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSecurityLogsAvailableEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSecurityLogsAvailableEvent.DeviceAdminSecurityLogsAvailableEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSystemUpdatePendingEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminSystemUpdatePendingEvent.DeviceAdminSystemUpdatePendingEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminTransferAffiliatedProfileOwnershipCompleteEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminTransferAffiliatedProfileOwnershipCompleteEvent.DeviceAdminTransferAffiliatedProfileOwnershipCompleteEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminTransferOwnershipCompleteEvent;
+import com.android.eventlib.events.deviceadminreceivers.DeviceAdminTransferOwnershipCompleteEvent.DeviceAdminTransferOwnershipCompleteEventQuery;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminUserAddedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminUserRemovedEvent;
 import com.android.eventlib.events.deviceadminreceivers.DeviceAdminUserStartedEvent;
@@ -73,7 +95,7 @@
  * <p>{@code #poll} can be used to fetch results, and the result can be asserted on.
  */
 public class TestAppEvents implements ActivityEvents, BroadcastReceiverEvents,
-        DeviceAdminReceiverEvents, ServiceEvents {
+        DeviceAdminReceiverEvents, DelegatedAdminReceiverEvents, ServiceEvents {
 
     private final TestAppInstance mTestApp;
 
@@ -152,14 +174,14 @@
     }
 
     @Override
-    public DeviceAdminBugreportSharingDeclinedEvent.DeviceAdminBugreportSharingDeclinedEventQuery bugReportSharingDeclined() {
+    public DeviceAdminBugreportSharingDeclinedEventQuery bugReportSharingDeclined() {
         return DeviceAdminBugreportSharingDeclinedEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminChoosePrivateKeyAliasEvent.DeviceAdminChoosePrivateKeyAliasEventQuery choosePrivateKeyAlias() {
+    public DeviceAdminChoosePrivateKeyAliasEventQuery choosePrivateKeyAlias() {
         return DeviceAdminChoosePrivateKeyAliasEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
@@ -173,7 +195,7 @@
     }
 
     @Override
-    public DeviceAdminDisableRequestedEvent.DeviceAdminDisableRequestedEventQuery deviceAdminDisableRequested() {
+    public DeviceAdminDisableRequestedEventQuery deviceAdminDisableRequested() {
         return DeviceAdminDisableRequestedEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
@@ -187,28 +209,28 @@
     }
 
     @Override
-    public DeviceAdminLockTaskModeEnteringEvent.DeviceAdminLockTaskModeEnteringEventQuery lockTaskModeEntering() {
+    public DeviceAdminLockTaskModeEnteringEventQuery lockTaskModeEntering() {
         return DeviceAdminLockTaskModeEnteringEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminLockTaskModeExitingEvent.DeviceAdminLockTaskModeExitingEventQuery lockTaskModeExiting() {
+    public DeviceAdminLockTaskModeExitingEventQuery lockTaskModeExiting() {
         return DeviceAdminLockTaskModeExitingEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminNetworkLogsAvailableEvent.DeviceAdminNetworkLogsAvailableEventQuery networkLogsAvailable() {
+    public DeviceAdminNetworkLogsAvailableEventQuery networkLogsAvailable() {
         return DeviceAdminNetworkLogsAvailableEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminOperationSafetyStateChangedEvent.DeviceAdminOperationSafetyStateChangedEventQuery operationSafetyStateChanged() {
+    public DeviceAdminOperationSafetyStateChangedEventQuery operationSafetyStateChanged() {
         return DeviceAdminOperationSafetyStateChangedEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
@@ -222,7 +244,7 @@
     }
 
     @Override
-    public DeviceAdminPasswordExpiringEvent.DeviceAdminPasswordExpiringEventQuery passwordExpiring() {
+    public DeviceAdminPasswordExpiringEventQuery passwordExpiring() {
         return DeviceAdminPasswordExpiringEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
@@ -236,49 +258,49 @@
     }
 
     @Override
-    public DeviceAdminPasswordSucceededEvent.DeviceAdminPasswordSucceededEventQuery passwordSucceeded() {
+    public DeviceAdminPasswordSucceededEventQuery passwordSucceeded() {
         return DeviceAdminPasswordSucceededEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminProfileProvisioningCompleteEvent.DeviceAdminProfileProvisioningCompleteEventQuery profileProvisioningComplete() {
+    public DeviceAdminProfileProvisioningCompleteEventQuery profileProvisioningComplete() {
         return DeviceAdminProfileProvisioningCompleteEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminReadyForUserInitializationEvent.DeviceAdminReadyForUserInitializationEventQuery readyForUserInitialization() {
+    public DeviceAdminReadyForUserInitializationEventQuery readyForUserInitialization() {
         return DeviceAdminReadyForUserInitializationEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminSecurityLogsAvailableEvent.DeviceAdminSecurityLogsAvailableEventQuery securityLogsAvailable() {
+    public DeviceAdminSecurityLogsAvailableEventQuery securityLogsAvailable() {
         return DeviceAdminSecurityLogsAvailableEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminSystemUpdatePendingEvent.DeviceAdminSystemUpdatePendingEventQuery systemUpdatePending() {
+    public DeviceAdminSystemUpdatePendingEventQuery systemUpdatePending() {
         return DeviceAdminSystemUpdatePendingEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminTransferAffiliatedProfileOwnershipCompleteEvent.DeviceAdminTransferAffiliatedProfileOwnershipCompleteEventQuery transferAffiliatedProfileOwnershipComplete() {
+    public DeviceAdminTransferAffiliatedProfileOwnershipCompleteEventQuery transferAffiliatedProfileOwnershipComplete() {
         return DeviceAdminTransferAffiliatedProfileOwnershipCompleteEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
     }
 
     @Override
-    public DeviceAdminTransferOwnershipCompleteEvent.DeviceAdminTransferOwnershipCompleteEventQuery transferOwnershipComplete() {
+    public DeviceAdminTransferOwnershipCompleteEventQuery transferOwnershipComplete() {
         return DeviceAdminTransferOwnershipCompleteEvent.queryPackage(
                 mTestApp.packageName())
                 .onUser(mTestApp.user());
@@ -390,4 +412,24 @@
                 .onUser(mTestApp.user());
     }
 
+    @Override
+    public DelegatedAdminChoosePrivateKeyAliasEventQuery delegateChoosePrivateKeyAlias() {
+        return DelegatedAdminChoosePrivateKeyAliasEvent.queryPackage(
+                mTestApp.testApp().packageName())
+                .onUser(mTestApp.user());
+    }
+
+    @Override
+    public DelegatedAdminNetworkLogsAvailableEventQuery delegateNetworkLogsAvailable() {
+        return DelegatedAdminNetworkLogsAvailableEvent.queryPackage(
+                        mTestApp.testApp().packageName())
+                .onUser(mTestApp.user());
+    }
+
+    @Override
+    public DelegatedAdminSecurityLogsAvailableEventQuery delegateSecurityLogsAvailable() {
+        return DelegatedAdminSecurityLogsAvailableEvent.queryPackage(
+                        mTestApp.testApp().packageName())
+                .onUser(mTestApp.user());
+    }
 }
diff --git a/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/BaseTestAppDelegatedAdminReceiver.java b/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/BaseTestAppDelegatedAdminReceiver.java
new file mode 100644
index 0000000..2e3de42
--- /dev/null
+++ b/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/BaseTestAppDelegatedAdminReceiver.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.android.bedstead.testapp;
+
+import android.app.admin.DelegatedAdminReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.eventlib.premade.EventLibDelegatedAdminReceiver;
+
+/**
+ * Implementation of {@link DelegatedAdminReceiver} which logs events in response to callbacks and
+ * supports TestApp Features.
+ */
+public class BaseTestAppDelegatedAdminReceiver extends EventLibDelegatedAdminReceiver {
+    @Override
+    public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, Uri uri,
+            String alias) {
+        return super.onChoosePrivateKeyAlias(context, intent, uid, uri, alias);
+    }
+
+    @Override
+    public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
+            int networkLogsCount) {
+        super.onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount);
+    }
+
+    @Override
+    public void onSecurityLogsAvailable(Context context, Intent intent) {
+        super.onSecurityLogsAvailable(context, intent);
+    }
+}
diff --git a/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/TestAppAppComponentFactory.java b/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/TestAppAppComponentFactory.java
index b5ee589..3d8e256 100644
--- a/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/TestAppAppComponentFactory.java
+++ b/common/device-side/bedstead/testapp/src/testapps/main/java/com/android/bedstead/testapp/TestAppAppComponentFactory.java
@@ -88,7 +88,6 @@
         try {
             return super.instantiateReceiver(classLoader, className, intent);
         } catch (ClassNotFoundException e) {
-
             if (className.endsWith("DeviceAdminReceiver")) {
                 Log.d(LOG_TAG, "Broadcast Receiver class (" + className
                         + ") not found, routing to TestAppDeviceAdminReceiver");
@@ -98,6 +97,15 @@
                                 intent);
                 receiver.setOverrideDeviceAdminReceiverClassName(className);
                 return receiver;
+            } else if (className.endsWith("DelegatedAdminReceiver")) {
+                Log.d(LOG_TAG, "Broadcast Receiver class (" + className
+                        + ") not found, routing to TestAppDelegatedAdminReceiver");
+                BaseTestAppDelegatedAdminReceiver receiver = (BaseTestAppDelegatedAdminReceiver)
+                        super.instantiateReceiver(
+                                classLoader, BaseTestAppDelegatedAdminReceiver.class.getName(),
+                                intent);
+                receiver.setOverrideDelegatedAdminReceiverClassName(className);
+                return receiver;
             }
 
             Log.d(LOG_TAG, "Broadcast Receiver class (" + className
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
index 0235d69..532dbe5 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/PackageDeviceInfo.java
@@ -43,7 +43,8 @@
 public class PackageDeviceInfo extends DeviceInfo {
 
     private static final String PLATFORM = "android";
-    private static final String PLATFORM_PERMISSION_PREFIX = "android.";
+    private static final String PLATFORM_ANDROID_PERMISSION_PREFIX = "android.permission.";
+    private static final String PLATFORM_MANIFEST_PERMISSION_PREFIX = "android.Manifest.permission.";
 
     private static final String PACKAGE = "package";
     private static final String NAME = "name";
@@ -54,6 +55,7 @@
     private static final String TARGET_SDK = "target_sdk";
 
     private static final String REQUESTED_PERMISSIONS = "requested_permissions";
+    private static final String DEFINED_PERMISSIONS = "defined_permissions";
     private static final String PERMISSION_NAME = "name";
     private static final String PERMISSION_FLAGS = "flags";
     private static final String PERMISSION_GROUP = "permission_group";
@@ -61,6 +63,7 @@
     private static final String PERMISSION_PROTECTION_FLAGS = "protection_level_flags";
     private static final String PERMISSION_IS_GRANTED = "is_granted";
 
+
     private static final String PERMISSION_TYPE = "type";
     private static final int PERMISSION_TYPE_SYSTEM = 1;
     private static final int PERMISSION_TYPE_OEM = 2;
@@ -84,6 +87,21 @@
     private static final String CONFIG_ACCESSIBILITY_SERVICE = "config_defaultAccessibilityService";
     private static final String DEFAULT_ACCESSIBILITY_SERVICE = "is_default_accessibility_service";
 
+    private static final HashSet<String> ADDITIONAL_ANDROID_PERMISSIONS = new HashSet<>(Arrays.asList(new String[] {
+        "com.android.voicemail.permission.ADD_VOICEMAIL",
+        "com.android.voicemail.permission.WRITE_VOICEMAIL",
+        "com.android.voicemail.permission.READ_VOICEMAIL",
+        "com.android.browser.permission.READ_HISTORY_BOOKMARKS",
+        "com.android.browser.permission.WRITE_HISTORY_BOOKMARKS",
+        "com.android.alarm.permission.SET_ALARM",
+        "com.android.launcher.permission.INSTALL_SHORTCUT",
+        "com.android.launcher.permission.UNINSTALL_SHORTCUT",
+        "com.android.permission.INSTALL_EXISTING_PACKAGES",
+        "com.android.permission.USE_INSTALLER_V2",
+        "com.android.permission.USE_SYSTEM_DATA_LOADERS",
+        "android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
+    }));
+
 
     @Override
     protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
@@ -111,7 +129,9 @@
             store.addResult(NAME, pkg.packageName);
             store.addResult(VERSION_NAME, pkg.versionName);
 
-            collectPermissions(store, pm, platformPermissions, pkg);
+            collectRequestedPermissions(store, pm, platformPermissions, pkg);
+            collectDefinedPermissions(store, platformPermissions, pkg);
+
             collectionApplicationInfo(store, pm, pkg);
 
             store.addResult(HAS_DEFAULT_NOTIFICATION_ACCESS,
@@ -138,7 +158,7 @@
         store.endArray(); // "package"
     }
 
-    private static void collectPermissions(DeviceInfoStore store,
+    private static void collectRequestedPermissions(DeviceInfoStore store,
                                            PackageManager pm,
                                            Set<String> systemPermissions,
                                            PackageInfo pkg) throws IOException
@@ -152,20 +172,7 @@
                     final PermissionInfo pi = pm.getPermissionInfo(permission, 0);
 
                     store.startGroup();
-                    store.addResult(PERMISSION_NAME, permission);
-                    writePermissionsDetails(pi, store);
-
-                    final boolean isPlatformPermission = systemPermissions.contains(permission);
-                    if (isPlatformPermission) {
-                      final boolean isAndroidPermission = permission.startsWith(PLATFORM_PERMISSION_PREFIX);
-                      if (isAndroidPermission) {
-                        store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_SYSTEM);
-                      } else {
-                        store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_OEM);
-                      }
-                    } else {
-                      store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_CUSTOM);
-                    }
+                    writePermissionsDetails(pi, store, systemPermissions);
 
                     boolean isGranted = pm.checkPermission(
                             permission, pkg.packageName) == pm.PERMISSION_GRANTED;
@@ -180,6 +187,27 @@
         store.endArray();
     }
 
+    private static void collectDefinedPermissions(DeviceInfoStore store,
+                                                  Set<String> systemPermissions,
+                                                  PackageInfo pkg) throws IOException {
+        if (pkg.permissions != null && pkg.permissions.length > 0) {
+            store.startArray(DEFINED_PERMISSIONS);
+            for (PermissionInfo permission : pkg.permissions) {
+                if (permission == null) continue;
+                // Ignore "android" package defined AOSP permissions.
+                if (pkg.packageName.equals(PLATFORM)
+                        && isAndroidPermission(permission.name))
+                    continue;
+
+                store.startGroup();
+                writePermissionsDetails(permission, store, systemPermissions);
+                store.endGroup();
+
+            }
+            store.endArray();
+        }
+    }
+
     private static void collectionApplicationInfo(DeviceInfoStore store,
                                                   PackageManager pm,
                                                   PackageInfo pkg) throws IOException {
@@ -231,8 +259,12 @@
         return sharedPermissions.contains(PackageDeviceInfo.INSTALL_PACKAGES_PERMISSION);
     }
 
-    private static void writePermissionsDetails(PermissionInfo pi, DeviceInfoStore store)
-            throws IOException {
+    private static void writePermissionsDetails(PermissionInfo pi,
+                                                DeviceInfoStore store,
+                                                Set<String> systemPermissions) throws IOException {
+        final String permissionName = pi.name;
+        store.addResult(PERMISSION_NAME, permissionName);
+
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
             store.addResult(PERMISSION_FLAGS, pi.flags);
         } else {
@@ -250,6 +282,18 @@
             store.addResult(PERMISSION_PROTECTION_FLAGS,
                     pi.protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE);
         }
+
+        final boolean isPlatformPermission = systemPermissions.contains(permissionName);
+        if (isPlatformPermission) {
+            final boolean isAndroidPermission = isAndroidPermission(permissionName);
+            if (isAndroidPermission) {
+            store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_SYSTEM);
+            } else {
+            store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_OEM);
+            }
+        } else {
+            store.addResult(PERMISSION_TYPE, PERMISSION_TYPE_CUSTOM);
+        }
     }
 
     private Set<String> getActiveDeviceAdminPackages() {
@@ -297,5 +341,14 @@
                 .getResources()
                 .getIdentifier(name, type, "android");
     }
+
+    /** Return a boolean value to whether the permission is an android permission defined by android package */
+    private static boolean isAndroidPermission(String permissionName) {
+        if(permissionName.startsWith(PLATFORM_ANDROID_PERMISSION_PREFIX)
+            || permissionName.startsWith(PLATFORM_MANIFEST_PERMISSION_PREFIX)
+            || ADDITIONAL_ANDROID_PERMISSIONS.contains(permissionName))
+            return true;
+        return false;
+    }
 }
 
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java
index 767f1d9..8f1d450 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/StorageDeviceInfo.java
@@ -16,6 +16,7 @@
 package com.android.compatibility.common.deviceinfo;
 
 import android.os.Environment;
+import android.os.SystemProperties;
 import android.util.Log;
 
 import com.android.compatibility.common.util.DeviceInfoStore;
@@ -57,12 +58,15 @@
         store.addResult("num_emulated", emulated);
 
         store.addListResult("raw_partition", scanPartitions());
+
+        boolean hasCompress = SystemProperties.getInt("vold.has_compress", 0) != 0 ? true : false;
+        store.addResult("compression", hasCompress);
     }
 
     private List<String> scanPartitions() {
         List<String> partitionList = new ArrayList<>();
         try {
-            Process df = new ProcessBuilder("df -k").start();
+            Process df = Runtime.getRuntime().exec("df -k");
             Scanner scanner = new Scanner(df.getInputStream());
             try {
                 while (scanner.hasNextLine()) {
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
index 2b174a7..edf0077 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
@@ -16,7 +16,7 @@
 
 package com.android.compatibility.common.util;
 
-import static android.telephony.TelephonyManager.CarrierPrivilegesListener;
+import static android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
@@ -58,10 +58,10 @@
         private final boolean mGain;
         private final boolean mIsShell;
         private final TelephonyManager mTelephonyManager;
-        private final CarrierPrivilegesListener mCarrierPrivilegesListener;
+        private final CarrierPrivilegesCallback mCarrierPrivilegesCallback;
 
         /**
-         * Construct a {@link CarrierPrivilegesListener} to monitor carrier privileges change.
+         * Construct a {@link CarrierPrivilegesCallback} to monitor carrier privileges change.
          * @param c context
          * @param subId subscriptionId to listen to
          * @param gain true if wait to grant carrier privileges, false if wait to revoke
@@ -76,26 +76,25 @@
                     TelephonyManager.class).createForSubscriptionId(subId);
             Objects.requireNonNull(mTelephonyManager);
 
-            mCarrierPrivilegesListener =
-                    (privilegedPackageNames, privilegedUids) -> {
-                        if (mTelephonyManager.hasCarrierPrivileges() == mGain) {
-                            mLatch.countDown();
-                        }
-                    };
+            mCarrierPrivilegesCallback = (privilegedPackageNames, privilegedUids) -> {
+                if (mTelephonyManager.hasCarrierPrivileges() == mGain) {
+                    mLatch.countDown();
+                }
+            };
 
             // Run with shell identify only when caller is not Shell to avoid overriding current
             // SHELL permissions
             if (mIsShell) {
-                mTelephonyManager.addCarrierPrivilegesListener(
+                mTelephonyManager.registerCarrierPrivilegesCallback(
                         SubscriptionManager.getSlotIndex(subId),
                         mContext.getMainExecutor(),
-                        mCarrierPrivilegesListener);
+                        mCarrierPrivilegesCallback);
             } else {
                 runWithShellPermissionIdentity(() -> {
-                    mTelephonyManager.addCarrierPrivilegesListener(
+                    mTelephonyManager.registerCarrierPrivilegesCallback(
                             SubscriptionManager.getSlotIndex(subId),
                             mContext.getMainExecutor(),
-                            mCarrierPrivilegesListener);
+                            mCarrierPrivilegesCallback);
                 }, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
             }
         }
@@ -105,11 +104,12 @@
             if (mTelephonyManager == null) return;
 
             if (mIsShell) {
-                mTelephonyManager.removeCarrierPrivilegesListener(mCarrierPrivilegesListener);
+                mTelephonyManager.unregisterCarrierPrivilegesCallback(mCarrierPrivilegesCallback);
             } else {
-                runWithShellPermissionIdentity(() -> {
-                    mTelephonyManager.removeCarrierPrivilegesListener(mCarrierPrivilegesListener);
-                }, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+                runWithShellPermissionIdentity(
+                        () -> mTelephonyManager.unregisterCarrierPrivilegesCallback(
+                                mCarrierPrivilegesCallback),
+                        Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
             }
         }
 
diff --git a/hostsidetests/appcompat/strictjavapackages/Android.bp b/hostsidetests/appcompat/strictjavapackages/Android.bp
index a2b4581..272be12 100644
--- a/hostsidetests/appcompat/strictjavapackages/Android.bp
+++ b/hostsidetests/appcompat/strictjavapackages/Android.bp
@@ -23,6 +23,7 @@
     libs: [
         "tradefed",
         "compatibility-host-util",
+        "cts-tradefed",
     ],
     static_libs: [
         "compat-classpaths-testing",
@@ -34,6 +35,9 @@
         "general-tests",
         "mts-mainline-infra",
     ],
-    data: [":SharedLibraryInfoTestApp"],
+    data: [
+        ":SharedLibraryInfoTestApp",
+        ":StrictJavaPackagesTestApp",
+    ],
     per_testcase_directory: true,
 }
diff --git a/hostsidetests/appcompat/strictjavapackages/app/Android.bp b/hostsidetests/appcompat/strictjavapackages/app/Android.bp
new file mode 100644
index 0000000..47e7f00
--- /dev/null
+++ b/hostsidetests/appcompat/strictjavapackages/app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+    name: "StrictJavaPackagesTestApp",
+    defaults: ["cts_defaults"],
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.core",
+    ],
+    sdk_version: "test_current",
+    test_suites: [
+        "ats",
+        "cts",
+        "gts",
+        "general-tests",
+        "mts",
+        "tvts",
+    ],
+}
diff --git a/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml b/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml
new file mode 100644
index 0000000..6ac77db
--- /dev/null
+++ b/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.compat.sjp.app"
+          android:targetSandboxVersion="2">
+    <application android:requestLegacyExternalStorage="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.compat.sjp.app" />
+</manifest>
diff --git a/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java b/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java
new file mode 100644
index 0000000..fa98fe6
--- /dev/null
+++ b/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.compat.sjp.app;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.pm.PackageManager;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Device-side helper app for obtaining Apex info.
+ *
+ * <p>It is not technically a test as it simply collects information, but it simplifies the usage
+ * and communication with host-side tests.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ApexDeviceTest {
+
+    @Before
+    public void before() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity();
+    }
+
+    @After
+    public void after() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
+    }
+
+    /**
+     * Collects all apk-in-apex apps on the device and writes them to disk.
+     */
+    @Test
+    public void testCollectApkInApexPaths() throws Exception {
+        Path detailsFilepath = new File("/sdcard/apk-in-apex-paths.txt").toPath();
+        final PackageManager pm = InstrumentationRegistry.getInstrumentation().getTargetContext()
+                .getPackageManager();
+        assertNotNull("No package manager instance!", pm);
+        final Set<String> lines = pm.getInstalledPackages(0).stream()
+                .map(pkg -> pkg.applicationInfo.sourceDir)
+                .filter(sourceDir -> sourceDir != null && sourceDir.contains("/apex/"))
+                .collect(Collectors.toSet());
+        Files.write(detailsFilepath, lines);
+    }
+}
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 cff7c22..1912811 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -20,12 +20,14 @@
 import static android.compat.testing.Classpaths.ClasspathType.SYSTEMSERVERCLASSPATH;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assume.assumeTrue;
 
 import android.compat.testing.Classpaths;
 import android.compat.testing.SharedLibraryInfo;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.modules.utils.build.testing.DeviceSdkLevel;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
@@ -33,10 +35,13 @@
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Multimap;
@@ -48,6 +53,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Set;
 import java.util.stream.Stream;
@@ -64,12 +70,14 @@
 public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
 
     private static final String ANDROID_TEST_MOCK_JAR = "/system/framework/android.test.mock.jar";
+    private static final String TEST_HELPER_PACKAGE = "android.compat.sjp.app";
+    private static final String TEST_HELPER_APK = "StrictJavaPackagesTestApp.apk";
 
     private static ImmutableList<String> sBootclasspathJars;
     private static ImmutableList<String> sSystemserverclasspathJars;
     private static ImmutableList<String> sSharedLibJars;
     private static ImmutableList<SharedLibraryInfo> sSharedLibs;
-    private static ImmutableSetMultimap<String, String> sJarsToClasses;
+    private static ImmutableMultimap<String, String> sJarsToClasses;
 
     private DeviceSdkLevel mDeviceSdkLevel;
 
@@ -205,6 +213,7 @@
                     "Landroid/hardware/usb/gadget/V1_2/UsbSpeed;",
                     "Landroid/os/CreateAppDataArgs;",
                     "Landroid/os/CreateAppDataResult;",
+                    "Landroid/os/ReconcileSdkDataArgs;",
                     "Lcom/android/internal/util/FrameworkStatsLog;"
             );
 
@@ -311,7 +320,418 @@
                     "Lorg/chromium/net/UrlRequest;",
                     "Lorg/chromium/net/UrlResponseInfo;"
             );
-
+    // TODO: b/223837004
+    private static final ImmutableSet<String> BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST =
+        ImmutableSet.of(
+                // Already duplicate in BCP.
+                "Landroid/hidl/base/V1_0/DebugInfo;",
+                "Landroid/hidl/base/V1_0/IBase;",
+                // /apex/com.android.bluetooth/javalib/framework-bluetooth.jar
+                "Lcom/android/bluetooth/x/android/sysprop/AdbProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/ApkVerityProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/BluetoothProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/CarProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/ContactsProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/CryptoProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/DeviceProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/DisplayProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/HdmiProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/HypervisorProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/InputProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/MediaProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/NetworkProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/OtaProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/PowerProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/SetupWizardProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/SocProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/TelephonyProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/TraceProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/VndkProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/VoldProperties;",
+                "Lcom/android/bluetooth/x/android/sysprop/WifiProperties;",
+                "Lcom/android/bluetooth/x/com/android/modules/utils/ISynchronousResultReceiver;",
+                "Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver-IA;",
+                "Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver;",
+                // /system/framework/services.jar
+                "Landroid/net/DataStallReportParcelable;",
+                "Landroid/net/DhcpResultsParcelable;",
+                "Landroid/net/IIpMemoryStore;",
+                "Landroid/net/IIpMemoryStoreCallbacks;",
+                "Landroid/net/INetworkMonitor;",
+                "Landroid/net/INetworkMonitorCallbacks;",
+                "Landroid/net/INetworkStackConnector;",
+                "Landroid/net/INetworkStackStatusCallback;",
+                "Landroid/net/InformationElementParcelable;",
+                "Landroid/net/InitialConfigurationParcelable;",
+                "Landroid/net/IpMemoryStoreClient;",
+                "Landroid/net/Layer2InformationParcelable;",
+                "Landroid/net/Layer2PacketParcelable;",
+                "Landroid/net/NattKeepalivePacketDataParcelable;",
+                "Landroid/net/NetworkFactory;",
+                "Landroid/net/NetworkFactoryShim;",
+                "Landroid/net/NetworkMonitorManager;",
+                "Landroid/net/NetworkTestResultParcelable;",
+                "Landroid/net/PrivateDnsConfigParcel;",
+                "Landroid/net/ProvisioningConfigurationParcelable;",
+                "Landroid/net/ScanResultInfoParcelable;",
+                "Landroid/net/TcpKeepalivePacketDataParcelable;",
+                "Landroid/net/dhcp/DhcpLeaseParcelable;",
+                "Landroid/net/dhcp/DhcpServingParamsParcel;",
+                "Landroid/net/dhcp/IDhcpEventCallbacks;",
+                "Landroid/net/dhcp/IDhcpServer;",
+                "Landroid/net/dhcp/IDhcpServerCallbacks;",
+                "Landroid/net/ip/IIpClient;",
+                "Landroid/net/ip/IIpClientCallbacks;",
+                "Landroid/net/ip/IpClientCallbacks;",
+                "Landroid/net/ip/IpClientManager;",
+                "Landroid/net/ip/IpClientUtil;",
+                "Landroid/net/ipmemorystore/Blob;",
+                "Landroid/net/ipmemorystore/IOnBlobRetrievedListener;",
+                "Landroid/net/ipmemorystore/IOnL2KeyResponseListener;",
+                "Landroid/net/ipmemorystore/IOnNetworkAttributesRetrievedListener;",
+                "Landroid/net/ipmemorystore/IOnSameL3NetworkResponseListener;",
+                "Landroid/net/ipmemorystore/IOnStatusAndCountListener;",
+                "Landroid/net/ipmemorystore/IOnStatusListener;",
+                "Landroid/net/ipmemorystore/NetworkAttributes;",
+                "Landroid/net/ipmemorystore/NetworkAttributesParcelable;",
+                "Landroid/net/ipmemorystore/OnBlobRetrievedListener;",
+                "Landroid/net/ipmemorystore/OnDeleteStatusListener;",
+                "Landroid/net/ipmemorystore/OnL2KeyResponseListener;",
+                "Landroid/net/ipmemorystore/OnNetworkAttributesRetrievedListener;",
+                "Landroid/net/ipmemorystore/OnSameL3NetworkResponseListener;",
+                "Landroid/net/ipmemorystore/OnStatusListener;",
+                "Landroid/net/ipmemorystore/SameL3NetworkResponse;",
+                "Landroid/net/ipmemorystore/SameL3NetworkResponseParcelable;",
+                "Landroid/net/ipmemorystore/Status;",
+                "Landroid/net/ipmemorystore/StatusParcelable;",
+                "Landroid/net/networkstack/NetworkStackClientBase;",
+                "Landroid/net/networkstack/aidl/NetworkMonitorParameters;",
+                "Landroid/net/networkstack/aidl/dhcp/DhcpOption;",
+                "Landroid/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable;",
+                "Landroid/net/networkstack/aidl/ip/ReachabilityLossReason;",
+                "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirk;",
+                "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable;",
+                "Landroid/net/shared/InitialConfiguration;",
+                "Landroid/net/shared/IpConfigurationParcelableUtil;",
+                "Landroid/net/shared/Layer2Information;",
+                "Landroid/net/shared/ParcelableUtil;",
+                "Landroid/net/shared/PrivateDnsConfig;",
+                "Landroid/net/shared/ProvisioningConfiguration;",
+                "Landroid/net/util/KeepalivePacketDataUtil;",
+                "Landroid/net/IpMemoryStore;",
+                "Landroid/net/NetworkFactoryLegacyImpl;",
+                "Landroid/net/networkstack/ModuleNetworkStackClient;",
+                "Landroid/net/NetworkFactoryImpl;",
+                // /system/framework/framework.jar
+                "Landroid/bluetooth/BluetoothProtoEnums;",
+                "Landroid/bluetooth/a2dp/BluetoothA2dpProtoEnums;",
+                "Landroid/bluetooth/hci/BluetoothHciProtoEnums;",
+                "Landroid/bluetooth/hfp/BluetoothHfpProtoEnums;",
+                "Landroid/bluetooth/smp/BluetoothSmpProtoEnums;",
+                "Landroid/hardware/radio/V1_0/ActivityStatsInfo;",
+                "Landroid/hardware/radio/V1_0/ApnAuthType;",
+                "Landroid/hardware/radio/V1_0/ApnTypes;",
+                "Landroid/hardware/radio/V1_0/AppState;",
+                "Landroid/hardware/radio/V1_0/AppStatus;",
+                "Landroid/hardware/radio/V1_0/AppType;",
+                "Landroid/hardware/radio/V1_0/Call;",
+                "Landroid/hardware/radio/V1_0/CallForwardInfo;",
+                "Landroid/hardware/radio/V1_0/CallForwardInfoStatus;",
+                "Landroid/hardware/radio/V1_0/CallPresentation;",
+                "Landroid/hardware/radio/V1_0/CallState;",
+                "Landroid/hardware/radio/V1_0/CardState;",
+                "Landroid/hardware/radio/V1_0/CardStatus;",
+                "Landroid/hardware/radio/V1_0/Carrier;",
+                "Landroid/hardware/radio/V1_0/CarrierMatchType;",
+                "Landroid/hardware/radio/V1_0/CarrierRestrictions;",
+                "Landroid/hardware/radio/V1_0/CdmaBroadcastSmsConfigInfo;",
+                "Landroid/hardware/radio/V1_0/CdmaCallWaiting;",
+                "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberPlan;",
+                "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberPresentation;",
+                "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberType;",
+                "Landroid/hardware/radio/V1_0/CdmaDisplayInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaInfoRecName;",
+                "Landroid/hardware/radio/V1_0/CdmaInformationRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaInformationRecords;",
+                "Landroid/hardware/radio/V1_0/CdmaLineControlInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaNumberInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaOtaProvisionStatus;",
+                "Landroid/hardware/radio/V1_0/CdmaRedirectingNumberInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaRedirectingReason;",
+                "Landroid/hardware/radio/V1_0/CdmaRoamingType;",
+                "Landroid/hardware/radio/V1_0/CdmaSignalInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaSignalStrength;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsAck;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsAddress;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsDigitMode;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsErrorClass;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsMessage;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsNumberMode;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsNumberPlan;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsNumberType;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsSubaddress;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsSubaddressType;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsWriteArgs;",
+                "Landroid/hardware/radio/V1_0/CdmaSmsWriteArgsStatus;",
+                "Landroid/hardware/radio/V1_0/CdmaSubscriptionSource;",
+                "Landroid/hardware/radio/V1_0/CdmaT53AudioControlInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CdmaT53ClirInfoRecord;",
+                "Landroid/hardware/radio/V1_0/CellIdentity;",
+                "Landroid/hardware/radio/V1_0/CellIdentityCdma;",
+                "Landroid/hardware/radio/V1_0/CellIdentityGsm;",
+                "Landroid/hardware/radio/V1_0/CellIdentityLte;",
+                "Landroid/hardware/radio/V1_0/CellIdentityTdscdma;",
+                "Landroid/hardware/radio/V1_0/CellIdentityWcdma;",
+                "Landroid/hardware/radio/V1_0/CellInfo;",
+                "Landroid/hardware/radio/V1_0/CellInfoCdma;",
+                "Landroid/hardware/radio/V1_0/CellInfoGsm;",
+                "Landroid/hardware/radio/V1_0/CellInfoLte;",
+                "Landroid/hardware/radio/V1_0/CellInfoTdscdma;",
+                "Landroid/hardware/radio/V1_0/CellInfoType;",
+                "Landroid/hardware/radio/V1_0/CellInfoWcdma;",
+                "Landroid/hardware/radio/V1_0/CfData;",
+                "Landroid/hardware/radio/V1_0/ClipStatus;",
+                "Landroid/hardware/radio/V1_0/Clir;",
+                "Landroid/hardware/radio/V1_0/DataCallFailCause;",
+                "Landroid/hardware/radio/V1_0/DataProfileId;",
+                "Landroid/hardware/radio/V1_0/DataProfileInfo;",
+                "Landroid/hardware/radio/V1_0/DataProfileInfoType;",
+                "Landroid/hardware/radio/V1_0/DataRegStateResult;",
+                "Landroid/hardware/radio/V1_0/DeviceStateType;",
+                "Landroid/hardware/radio/V1_0/Dial;",
+                "Landroid/hardware/radio/V1_0/EvdoSignalStrength;",
+                "Landroid/hardware/radio/V1_0/GsmBroadcastSmsConfigInfo;",
+                "Landroid/hardware/radio/V1_0/GsmSignalStrength;",
+                "Landroid/hardware/radio/V1_0/GsmSmsMessage;",
+                "Landroid/hardware/radio/V1_0/HardwareConfig;",
+                "Landroid/hardware/radio/V1_0/HardwareConfigModem;",
+                "Landroid/hardware/radio/V1_0/HardwareConfigSim;",
+                "Landroid/hardware/radio/V1_0/HardwareConfigState;",
+                "Landroid/hardware/radio/V1_0/HardwareConfigType;",
+                "Landroid/hardware/radio/V1_0/IccIo;",
+                "Landroid/hardware/radio/V1_0/IccIoResult;",
+                "Landroid/hardware/radio/V1_0/ImsSmsMessage;",
+                "Landroid/hardware/radio/V1_0/IndicationFilter;",
+                "Landroid/hardware/radio/V1_0/LastCallFailCause;",
+                "Landroid/hardware/radio/V1_0/LastCallFailCauseInfo;",
+                "Landroid/hardware/radio/V1_0/LceDataInfo;",
+                "Landroid/hardware/radio/V1_0/LceStatus;",
+                "Landroid/hardware/radio/V1_0/LceStatusInfo;",
+                "Landroid/hardware/radio/V1_0/LteSignalStrength;",
+                "Landroid/hardware/radio/V1_0/MvnoType;",
+                "Landroid/hardware/radio/V1_0/NeighboringCell;",
+                "Landroid/hardware/radio/V1_0/NvItem;",
+                "Landroid/hardware/radio/V1_0/NvWriteItem;",
+                "Landroid/hardware/radio/V1_0/OperatorInfo;",
+                "Landroid/hardware/radio/V1_0/OperatorStatus;",
+                "Landroid/hardware/radio/V1_0/P2Constant;",
+                "Landroid/hardware/radio/V1_0/PcoDataInfo;",
+                "Landroid/hardware/radio/V1_0/PersoSubstate;",
+                "Landroid/hardware/radio/V1_0/PhoneRestrictedState;",
+                "Landroid/hardware/radio/V1_0/PinState;",
+                "Landroid/hardware/radio/V1_0/PreferredNetworkType;",
+                "Landroid/hardware/radio/V1_0/RadioAccessFamily;",
+                "Landroid/hardware/radio/V1_0/RadioBandMode;",
+                "Landroid/hardware/radio/V1_0/RadioCapability;",
+                "Landroid/hardware/radio/V1_0/RadioCapabilityPhase;",
+                "Landroid/hardware/radio/V1_0/RadioCapabilityStatus;",
+                "Landroid/hardware/radio/V1_0/RadioCdmaSmsConst;",
+                "Landroid/hardware/radio/V1_0/RadioConst;",
+                "Landroid/hardware/radio/V1_0/RadioError;",
+                "Landroid/hardware/radio/V1_0/RadioIndicationType;",
+                "Landroid/hardware/radio/V1_0/RadioResponseInfo;",
+                "Landroid/hardware/radio/V1_0/RadioResponseType;",
+                "Landroid/hardware/radio/V1_0/RadioState;",
+                "Landroid/hardware/radio/V1_0/RadioTechnology;",
+                "Landroid/hardware/radio/V1_0/RadioTechnologyFamily;",
+                "Landroid/hardware/radio/V1_0/RegState;",
+                "Landroid/hardware/radio/V1_0/ResetNvType;",
+                "Landroid/hardware/radio/V1_0/RestrictedState;",
+                "Landroid/hardware/radio/V1_0/SapApduType;",
+                "Landroid/hardware/radio/V1_0/SapConnectRsp;",
+                "Landroid/hardware/radio/V1_0/SapDisconnectType;",
+                "Landroid/hardware/radio/V1_0/SapResultCode;",
+                "Landroid/hardware/radio/V1_0/SapStatus;",
+                "Landroid/hardware/radio/V1_0/SapTransferProtocol;",
+                "Landroid/hardware/radio/V1_0/SelectUiccSub;",
+                "Landroid/hardware/radio/V1_0/SendSmsResult;",
+                "Landroid/hardware/radio/V1_0/SetupDataCallResult;",
+                "Landroid/hardware/radio/V1_0/SignalStrength;",
+                "Landroid/hardware/radio/V1_0/SimApdu;",
+                "Landroid/hardware/radio/V1_0/SimRefreshResult;",
+                "Landroid/hardware/radio/V1_0/SimRefreshType;",
+                "Landroid/hardware/radio/V1_0/SmsAcknowledgeFailCause;",
+                "Landroid/hardware/radio/V1_0/SmsWriteArgs;",
+                "Landroid/hardware/radio/V1_0/SmsWriteArgsStatus;",
+                "Landroid/hardware/radio/V1_0/SrvccState;",
+                "Landroid/hardware/radio/V1_0/SsInfoData;",
+                "Landroid/hardware/radio/V1_0/SsRequestType;",
+                "Landroid/hardware/radio/V1_0/SsServiceType;",
+                "Landroid/hardware/radio/V1_0/SsTeleserviceType;",
+                "Landroid/hardware/radio/V1_0/StkCcUnsolSsResult;",
+                "Landroid/hardware/radio/V1_0/SubscriptionType;",
+                "Landroid/hardware/radio/V1_0/SuppServiceClass;",
+                "Landroid/hardware/radio/V1_0/SuppSvcNotification;",
+                "Landroid/hardware/radio/V1_0/TdScdmaSignalStrength;",
+                "Landroid/hardware/radio/V1_0/TimeStampType;",
+                "Landroid/hardware/radio/V1_0/TtyMode;",
+                "Landroid/hardware/radio/V1_0/UiccSubActStatus;",
+                "Landroid/hardware/radio/V1_0/UssdModeType;",
+                "Landroid/hardware/radio/V1_0/UusDcs;",
+                "Landroid/hardware/radio/V1_0/UusInfo;",
+                "Landroid/hardware/radio/V1_0/UusType;",
+                "Landroid/hardware/radio/V1_0/VoiceRegStateResult;",
+                "Landroid/hardware/radio/V1_0/WcdmaSignalStrength;",
+                "Landroid/hardware/radio/V1_0/IRadio;",
+                "Landroid/hardware/radio/V1_0/IRadioIndication;",
+                "Landroid/hardware/radio/V1_0/IRadioResponse;",
+                "Landroid/hardware/radio/V1_0/ISap;",
+                "Landroid/hardware/radio/V1_0/ISapCallback;",
+                "Lcom/android/internal/util/IState;",
+                "Lcom/android/internal/util/StateMachine;",
+                "Lcom/google/android/mms/ContentType;",
+                "Lcom/google/android/mms/MmsException;",
+                "Lcom/google/android/mms/pdu/Base64;",
+                "Lcom/google/android/mms/pdu/CharacterSets;",
+                "Lcom/google/android/mms/pdu/EncodedStringValue;",
+                "Lcom/google/android/mms/pdu/GenericPdu;",
+                "Lcom/google/android/mms/pdu/PduBody;",
+                "Lcom/google/android/mms/pdu/PduComposer;",
+                "Lcom/google/android/mms/pdu/PduContentTypes;",
+                "Lcom/google/android/mms/pdu/PduHeaders;",
+                "Lcom/google/android/mms/pdu/PduParser;",
+                "Lcom/google/android/mms/pdu/PduPart;",
+                "Lcom/google/android/mms/pdu/PduPersister;",
+                "Lcom/google/android/mms/pdu/QuotedPrintable;",
+                "Lcom/google/android/mms/util/AbstractCache;",
+                "Lcom/google/android/mms/util/DownloadDrmHelper;",
+                "Lcom/google/android/mms/util/DrmConvertSession;",
+                "Lcom/google/android/mms/util/PduCacheEntry;",
+                "Lcom/google/android/mms/util/SqliteWrapper;",
+                "Lcom/android/internal/util/State;",
+                "Lcom/google/android/mms/InvalidHeaderValueException;",
+                "Lcom/google/android/mms/pdu/AcknowledgeInd;",
+                "Lcom/google/android/mms/pdu/DeliveryInd;",
+                "Lcom/google/android/mms/pdu/MultimediaMessagePdu;",
+                "Lcom/google/android/mms/pdu/NotificationInd;",
+                "Lcom/google/android/mms/pdu/NotifyRespInd;",
+                "Lcom/google/android/mms/pdu/ReadOrigInd;",
+                "Lcom/google/android/mms/pdu/ReadRecInd;",
+                "Lcom/google/android/mms/pdu/SendConf;",
+                "Lcom/google/android/mms/util/PduCache;",
+                "Lcom/google/android/mms/pdu/RetrieveConf;",
+                "Lcom/google/android/mms/pdu/SendReq;"
+        );
+    private static final ImmutableSet<String> PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST =
+            ImmutableSet.of(
+                "Lcom/android/modules/utils/build/SdkLevel;",
+                "Lcom/android/settingslib/RestrictedLockUtils;"
+            );
+    // TODO: b/223837599
+    private static final ImmutableSet<String> TETHERING_APK_IN_APEX_BURNDOWN_LIST =
+            ImmutableSet.of(
+                "Landroid/hidl/base/V1_0/DebugInfo;",
+                // /system/framework/services.jar
+                "Landroid/net/DataStallReportParcelable;",
+                "Landroid/net/DhcpResultsParcelable;",
+                "Landroid/net/INetd;",
+                "Landroid/net/INetdUnsolicitedEventListener;",
+                "Landroid/net/INetworkStackConnector;",
+                "Landroid/net/INetworkStackStatusCallback;",
+                "Landroid/net/InformationElementParcelable;",
+                "Landroid/net/InitialConfigurationParcelable;",
+                "Landroid/net/InterfaceConfigurationParcel;",
+                "Landroid/net/Layer2InformationParcelable;",
+                "Landroid/net/Layer2PacketParcelable;",
+                "Landroid/net/MarkMaskParcel;",
+                "Landroid/net/NativeNetworkConfig;",
+                "Landroid/net/NattKeepalivePacketDataParcelable;",
+                "Landroid/net/NetworkTestResultParcelable;",
+                "Landroid/net/PrivateDnsConfigParcel;",
+                "Landroid/net/ProvisioningConfigurationParcelable;",
+                "Landroid/net/RouteInfoParcel;",
+                "Landroid/net/ScanResultInfoParcelable;",
+                "Landroid/net/TcpKeepalivePacketDataParcelable;",
+                "Landroid/net/TetherConfigParcel;",
+                "Landroid/net/TetherOffloadRuleParcel;",
+                "Landroid/net/TetherStatsParcel;",
+                "Landroid/net/UidRangeParcel;",
+                "Landroid/net/dhcp/DhcpLeaseParcelable;",
+                "Landroid/net/dhcp/DhcpServingParamsParcel;",
+                "Landroid/net/dhcp/IDhcpEventCallbacks;",
+                "Landroid/net/dhcp/IDhcpServer;",
+                "Landroid/net/dhcp/IDhcpServerCallbacks;",
+                "Landroid/net/ipmemorystore/Blob;",
+                "Landroid/net/ipmemorystore/NetworkAttributesParcelable;",
+                "Landroid/net/ipmemorystore/SameL3NetworkResponseParcelable;",
+                "Landroid/net/ipmemorystore/StatusParcelable;",
+                "Landroid/net/netd/aidl/NativeUidRangeConfig;",
+                "Landroid/net/networkstack/aidl/NetworkMonitorParameters;",
+                "Landroid/net/networkstack/aidl/dhcp/DhcpOption;",
+                "Landroid/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable;",
+                "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable;",
+                "Landroid/net/shared/NetdUtils;",
+                "Landroid/net/util/NetworkConstants;",
+                "Landroid/net/util/SharedLog;",
+                "Lcom/android/modules/utils/build/SdkLevel;",
+                ///system/framework/framework.jar
+                "Landroid/util/IndentingPrintWriter;",
+                "Lcom/android/internal/annotations/Keep;"
+            );
+    // TODO: b/223836161
+    private static final ImmutableSet<String> EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST =
+            ImmutableSet.of(
+                ///system/framework/framework.jar
+                "Landroid/view/displayhash/DisplayHashResultCallback;",
+                "Landroid/view/displayhash/DisplayHash;",
+                "Landroid/view/displayhash/VerifiedDisplayHash;"
+            );
+    // TODO: b/223836163
+    private static final ImmutableSet<String> ODA_APK_IN_APEX_BURNDOWN_LIST =
+            ImmutableSet.of(
+                // /apex/com.android.ondevicepersonalization/javalib/framework-ondevicepersonalization.jar
+                "Landroid/ondevicepersonalization/aidl/IInitOnDevicePersonalizationCallback;",
+                "Landroid/ondevicepersonalization/aidl/IOnDevicePersonalizationManagerService;"
+            );
+    // TODO: b/223837017
+    private static final ImmutableSet<String> CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST =
+            ImmutableSet.of(
+                // /system/framework/telephony-common.jar
+                "Lcom/android/cellbroadcastservice/CellBroadcastStatsLog;",
+                // /system/framework/framework.jar
+                "Lcom/android/internal/util/IState;",
+                "Lcom/android/internal/util/StateMachine;",
+                "Lcom/android/internal/util/State;"
+            );
+    private static final ImmutableMap<String, ImmutableSet<String>> FULL_APK_IN_APEX_BURNDOWN =
+        new ImmutableMap.Builder<String, ImmutableSet<String>>()
+            .put("/apex/com.android.bluetooth/app/Bluetooth/Bluetooth.apk",
+                BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.permission/priv-app/PermissionController/PermissionController.apk",
+                PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.permission/priv-app/GooglePermissionController/GooglePermissionController.apk",
+                PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.tethering/priv-app/TetheringNextGoogle/TetheringNextGoogle.apk",
+                TETHERING_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.tethering/priv-app/TetheringGoogle/TetheringGoogle.apk",
+                TETHERING_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.tethering/priv-app/TetheringNext/TetheringNext.apk",
+                TETHERING_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.tethering/priv-app/Tethering/Tethering.apk",
+                TETHERING_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.extservices/priv-app/GoogleExtServices/GoogleExtServices.apk",
+                EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.extservices/priv-app/ExtServices/ExtServices.apk",
+                EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.ondevicepersonalization/app/OnDevicePersonalizationGoogle/OnDevicePersonalizationGoogle.apk",
+                ODA_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.ondevicepersonalization/app/OnDevicePersonalization/OnDevicePersonalization.apk",
+                ODA_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.cellbroadcast/priv-app/GoogleCellBroadcastServiceModule/GoogleCellBroadcastServiceModule.apk",
+                CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST)
+            .put("/apex/com.android.cellbroadcast/priv-app/CellBroadcastServiceModule/CellBroadcastServiceModule.apk",
+                CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST)
+            .build();
     /**
      * Fetch all jar files in BCP, SSCP and shared libs and extract all the classes.
      *
@@ -335,6 +755,8 @@
                 .map(sharedLibraryInfo -> sharedLibraryInfo.paths)
                 .flatMap(ImmutableCollection::stream)
                 .filter(file -> doesFileExist(file, testInfo.getDevice()))
+                // GmsCore should not contribute to *classpath.
+                .filter(file -> !file.contains("GmsCore"))
                 .collect(ImmutableList.toImmutableList());
 
         final ImmutableSetMultimap.Builder<String, String> jarsToClasses =
@@ -512,6 +934,71 @@
     }
 
     /**
+     * Ensure that no apk-in-apex bundles classes that could be eclipsed by jars in
+     * BOOTCLASSPATH, SYSTEMSERVERCLASSPATH.
+     */
+    @Test
+    public void testApkInApex_nonClasspathClasses() throws Exception {
+        HashMultimap<String, Multimap<String, String>> perApkClasspathDuplicates =
+                HashMultimap.create();
+        Arrays.stream(collectApkInApexPaths())
+                .parallel()
+                .forEach(apk -> {
+                    try {
+                        final ImmutableSet<String> apkClasses =
+                                Classpaths.getClassDefsFromJar(getDevice(), apk).stream()
+                                        .map(ClassDef::getType)
+                                        .collect(ImmutableSet.toImmutableSet());
+                        final ImmutableSet<String> burndownClasses =
+                                FULL_APK_IN_APEX_BURNDOWN.getOrDefault(apk, ImmutableSet.of());
+                        final Multimap<String, String> duplicates =
+                                Multimaps.filterValues(sJarsToClasses, apkClasses::contains);
+                        final Multimap<String, String> filteredDuplicates =
+                                Multimaps.filterValues(duplicates,
+                                    className -> !burndownClasses.contains(className));
+                        if (!filteredDuplicates.isEmpty()) {
+                            synchronized (perApkClasspathDuplicates) {
+                                perApkClasspathDuplicates.put(apk, filteredDuplicates);
+                            }
+                        }
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+        assertThat(perApkClasspathDuplicates).isEmpty();
+    }
+
+    private String[] collectApkInApexPaths() {
+        try {
+            final CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+            final String installError = getDevice().installPackage(
+                    buildHelper.getTestFile(TEST_HELPER_APK), false);
+            assertWithMessage("Failed to install %s due to: %s", TEST_HELPER_APK, installError)
+                    .that(installError).isNull();
+            runDeviceTests(new DeviceTestRunOptions(TEST_HELPER_PACKAGE)
+                    .setDevice(getDevice())
+                    .setTestClassName(TEST_HELPER_PACKAGE + ".ApexDeviceTest")
+                    .setTestMethodName("testCollectApkInApexPaths"));
+            final String remoteFile = "/sdcard/apk-in-apex-paths.txt";
+            String content;
+            try {
+                content = getDevice().pullFileContents(remoteFile);
+            } finally {
+                getDevice().deleteFile(remoteFile);
+            }
+            return content.split("\n");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                getDevice().uninstallPackage(TEST_HELPER_PACKAGE);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    /**
      * Gets the duplicate classes within a list of jar files.
      *
      * @param jars a list of jar files.
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApexSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApexSignatureVerificationTest.java
index e9ab634..b73c8d7 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApexSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApexSignatureVerificationTest.java
@@ -19,6 +19,8 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.platform.test.annotations.RestrictedBuildTest;
 
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -190,10 +192,13 @@
         try {
             apexes = mDevice.getActiveApexes();
             for (ITestDevice.ApexInfo ap : apexes) {
-                mPreloadedApexPathMap.put(ap.name, ap.sourceDir);
+                if (!ap.sourceDir.startsWith("/data/")) {
+                    mPreloadedApexPathMap.put(ap.name, ap.sourceDir);
+                }
             }
 
-            assertThat(mPreloadedApexPathMap.size()).isAtLeast(0);
+            assumeTrue("No active APEX packages or all APEX packages have been already updated",
+                    mPreloadedApexPathMap.size() > 0);
         } catch (DeviceNotAvailableException e) {
             throw new AssertionError("getApexPackageList DeviceNotAvailableException" + e);
         }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index f2ca529..1bf6889 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -101,6 +101,12 @@
             "android.permission.ACCESS_MEDIA_LOCATION";
     private static final String PERM_READ_EXTERNAL_STORAGE =
             "android.permission.READ_EXTERNAL_STORAGE";
+    private static final String PERM_READ_MEDIA_IMAGES =
+            "android.permission.READ_MEDIA_IMAGES";
+    private static final String PERM_READ_MEDIA_AUDIO =
+            "android.permission.READ_MEDIA_AUDIO";
+    private static final String PERM_READ_MEDIA_VIDEO =
+            "android.permission.READ_MEDIA_VIDEO";
     private static final String PERM_WRITE_EXTERNAL_STORAGE =
             "android.permission.WRITE_EXTERNAL_STORAGE";
 
@@ -298,6 +304,9 @@
             for (int user : mUsers) {
                 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", true);
                 updatePermissions(WRITE_PKG_2, user, new String[] {
+                        PERM_READ_MEDIA_IMAGES,
+                        PERM_READ_MEDIA_VIDEO,
+                        PERM_READ_MEDIA_AUDIO,
                         PERM_READ_EXTERNAL_STORAGE,
                         PERM_WRITE_EXTERNAL_STORAGE,
                 }, true);
@@ -523,6 +532,9 @@
         waitForBroadcastIdle();
         for (int user : mUsers) {
             updatePermissions(config.pkg, user, new String[] {
+                    PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO,
                     PERM_READ_EXTERNAL_STORAGE,
                     PERM_WRITE_EXTERNAL_STORAGE,
             }, true);
@@ -551,6 +563,9 @@
 
         // revoke permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_WRITE_EXTERNAL_STORAGE,
         }, false);
@@ -576,6 +591,9 @@
 
         // revoke permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_WRITE_EXTERNAL_STORAGE,
         }, false);
@@ -592,9 +610,11 @@
     public void testGrantUriPermission() throws Exception {
         doGrantUriPermission(MEDIA, "testGrantUriPermission", new String[]{});
         doGrantUriPermission(MEDIA, "testGrantUriPermission",
-                new String[]{PERM_READ_EXTERNAL_STORAGE});
+                new String[]{PERM_READ_MEDIA_IMAGES, PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO, PERM_READ_EXTERNAL_STORAGE});
         doGrantUriPermission(MEDIA, "testGrantUriPermission",
-                new String[]{PERM_READ_EXTERNAL_STORAGE, PERM_WRITE_EXTERNAL_STORAGE});
+                new String[]{PERM_READ_EXTERNAL_STORAGE, PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO, PERM_READ_MEDIA_AUDIO, PERM_WRITE_EXTERNAL_STORAGE});
     }
 
     @Test
@@ -613,6 +633,9 @@
         for (int user : mUsers) {
             // Over revoke all permissions and grant necessary permissions later.
             updatePermissions(config.pkg, user, new String[] {
+                    PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO,
                     PERM_READ_EXTERNAL_STORAGE,
                     PERM_WRITE_EXTERNAL_STORAGE,
             }, false);
@@ -638,6 +661,9 @@
         installPackage(config.apk);
         for (int user : mUsers) {
             updatePermissions(config.pkg, user, new String[] {
+                    PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO,
                     PERM_READ_EXTERNAL_STORAGE,
                     PERM_WRITE_EXTERNAL_STORAGE,
             }, false);
@@ -663,6 +689,9 @@
         installPackage(config.apk);
         for (int user : mUsers) {
             updatePermissions(config.pkg, user, new String[] {
+                    PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO,
                     PERM_READ_EXTERNAL_STORAGE,
             }, true);
             updatePermissions(config.pkg, user, new String[] {
@@ -690,6 +719,9 @@
         installPackage(config.apk);
         for (int user : mUsers) {
             updatePermissions(config.pkg, user, new String[] {
+                    PERM_READ_MEDIA_IMAGES,
+                    PERM_READ_MEDIA_VIDEO,
+                    PERM_READ_MEDIA_AUDIO,
                     PERM_READ_EXTERNAL_STORAGE,
                     PERM_WRITE_EXTERNAL_STORAGE,
             }, true);
@@ -708,6 +740,9 @@
         // revoke all permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
                 PERM_ACCESS_MEDIA_LOCATION,
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_WRITE_EXTERNAL_STORAGE,
         }, false);
@@ -739,6 +774,9 @@
         // TODO: extend test to exercise secondary users
         int user = getDevice().getCurrentUser();
         updatePermissions(config.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
         }, true);
         updatePermissions(config.pkg, user, new String[] {
@@ -849,6 +887,9 @@
         }, true);
         // revoke permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_WRITE_EXTERNAL_STORAGE,
         }, false);
@@ -879,6 +920,9 @@
         int user = getDevice().getCurrentUser();
         // grant permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_ACCESS_MEDIA_LOCATION,
         }, true);
@@ -912,6 +956,9 @@
         int user = getDevice().getCurrentUser();
         // grant permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
         }, true);
         // revoke permission
@@ -949,6 +996,9 @@
         int user = getDevice().getCurrentUser();
         // grant permissions
         updatePermissions(MEDIA.pkg, user, new String[] {
+                PERM_READ_MEDIA_IMAGES,
+                PERM_READ_MEDIA_VIDEO,
+                PERM_READ_MEDIA_AUDIO,
                 PERM_READ_EXTERNAL_STORAGE,
                 PERM_ACCESS_MEDIA_LOCATION,
         }, true);
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/MediaStorageApp/AndroidManifest.xml
index 64f7657..4065604 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/AndroidManifest.xml
@@ -39,6 +39,9 @@
     <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.MANAGE_MEDIA"/>
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
diff --git a/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
index 779d405..af23b2b 100644
--- a/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
@@ -20,7 +20,8 @@
 
 import static org.junit.Assume.assumeTrue;
 
-import com.android.car.telemetry.TelemetryProto;
+import android.car.telemetry.TelemetryProto;
+
 import com.android.compatibility.common.util.PollingCheck;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
diff --git a/hostsidetests/classloaders/OWNERS b/hostsidetests/classloaders/OWNERS
index e7c6bf7..18f4805 100644
--- a/hostsidetests/classloaders/OWNERS
+++ b/hostsidetests/classloaders/OWNERS
@@ -1,6 +1,8 @@
 # Bug component: 86431
-calin@google.com
+jiakaiz@google.com
+mast@google.com
 ngeoffray@google.com
 oth@google.com
+rpl@google.com
 skvadrik@google.com
-vmarko@google.com
\ No newline at end of file
+vmarko@google.com
diff --git a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
index edcfaa4..d4a1164 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java
@@ -18,15 +18,22 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 
 import com.google.common.io.ByteStreams;
 
-import junit.framework.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -40,13 +47,21 @@
 /**
  * Tests background dex optimization which runs as idle job.
  */
-public final class BackgroundDexOptimizationTest extends DeviceTestCase {
+@RunWith(DeviceJUnit4ClassRunner.class)
+// Tests for post boot optimization must run first because they reboot the device into a clean
+// state, which can benefit other tests so that they don't have to reboot again.
+// Tests for idle optimizations won't work without a reboot in some cases. See
+// `testIdleOptimization*` for more details. However, we can't do a reboot for every test case
+// because it will cause the test to time out.
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test {
     private static final long REBOOT_TIMEOUT_MS = 600_000;
+    private static final long JOB_START_TIMEOUT_MS = 10_000;
     private static final long DEXOPT_TIMEOUT_MS = 1_200_000;
     // Cancel should be faster. It will be usually much shorter but we cannot make it too short
     // as CTS cannot enforce unspecified performance.
     private static final long DEXOPT_CANCEL_TIMEOUT_MS = 10_000;
-    private static final long POLLING_TIME_SLICE = 2;
+    private static final long POLLING_TIME_SLICE = 200;
 
     private static final String CMD_DUMP_PACKAGE_DEXOPT = "dumpsys -t 100 package dexopt";
 
@@ -70,31 +85,33 @@
 
     private ITestDevice mDevice;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() throws Exception {
         mDevice = getDevice();
-        // Should reboot to put the device into known states (= post boot optimization not run yet).
-        mDevice.reboot();
-        assertThat(mDevice.waitForBootComplete(REBOOT_TIMEOUT_MS)).isTrue();
-        // This requires PackageManager to be alive. So run after reboot as the previous failure
-        // may have device in booting state.
-        assumeTrue(checkDexOptEnabled());
     }
 
-    public void testPostBootOptimizationCompleted() throws Exception {
+    @Test
+    // Add an "A" in the name to make it run before other tests.
+    public void testAPostBootOptimizationCompleted() throws Exception {
+        // Should reboot to put the device into known states (= post boot optimization not run yet).
+        rebootAndCheckDexOptEnabled();
+
         // Note that post boot job runs only once until it is completed.
         completePostBootOptimization();
     }
 
-    public void testPostBootOptimizationCancelled() throws Exception {
+    @Test
+    // Add an "A" in the name to make it run before other tests.
+    public void testAPostBootOptimizationCancelled() throws Exception {
+        // Should reboot to put the device into known states (= post boot optimization not run yet).
+        rebootAndCheckDexOptEnabled();
+
         reinstallAppPackage();
         LastDeviceExecutionTime timeBefore = getLastExecutionTime();
         postJobSchedulerJob(CMD_START_POST_BOOT);
 
         // Wait until it is started.
-        pollingCheck("Post boot start timeout", DEXOPT_TIMEOUT_MS,
+        pollingCheck("Post boot start timeout", JOB_START_TIMEOUT_MS,
                 () -> getLastExecutionTime().startTime >= timeBefore.deviceCurrentTime);
 
         // Now cancel it.
@@ -116,23 +133,39 @@
         }
     }
 
+    @Test
     public void testIdleOptimizationCompleted() throws Exception {
-        completePostBootOptimization();
+        assumeTrue(checkDexOptEnabled());
+        // We check if post boot optimization is completed, and wait for it to be completed if not.
+        // Note that this won't work if the system server has been restarted (e.g., by a `stop &&
+        // start`) AND this test case is run individually, in which case,
+        // `checkFinishedPostBootUpdate` will return false because the system server will lose track
+        // of a completed post boot optimization run, but `completePostBootOptimization` will get
+        // stuck retrying to start the job since it has already completed.
+        ensurePostBootOptimizationCompleted();
 
         completeIdleOptimization();
         // idle job can run again.
         completeIdleOptimization();
     }
 
+    @Test
     public void testIdleOptimizationCancelled() throws Exception {
-        completePostBootOptimization();
+        assumeTrue(checkDexOptEnabled());
+        // We check if post boot optimization is completed, and wait for it to be completed if not.
+        // Note that this won't work if the system server has been restarted (e.g., by a `stop &&
+        // start`) AND this test case is run individually, in which case,
+        // `checkFinishedPostBootUpdate` will return false because the system server will lose track
+        // of a completed post boot optimization run, but `completePostBootOptimization` will get
+        // stuck retrying to start the job since it has already completed.
+        ensurePostBootOptimizationCompleted();
 
         reinstallAppPackage();
         LastDeviceExecutionTime timeBefore = getLastExecutionTime();
         postJobSchedulerJob(CMD_START_IDLE);
 
         // Wait until it is started.
-        pollingCheck("Idle start timeout", DEXOPT_TIMEOUT_MS,
+        pollingCheck("Idle start timeout", JOB_START_TIMEOUT_MS,
                 () -> getLastExecutionTime().startTime >= timeBefore.deviceCurrentTime);
 
         // Now cancel it.
@@ -189,13 +222,12 @@
         assertThat(status).isEqualTo(STATUS_OK);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         // Cancel all active dexopt jobs.
         executeShellCommand(CMD_CANCEL_IDLE);
         executeShellCommand(CMD_CANCEL_POST_BOOT);
         mDevice.uninstallPackage(APPLICATION_PACKAGE);
-        super.tearDown();
     }
 
     private void postJobSchedulerJob(String cmd) throws Exception {
@@ -315,7 +347,21 @@
             Thread.sleep(POLLING_TIME_SLICE);
         }
 
-        Assert.fail(message.toString());
+        fail(message.toString());
+    }
+
+    private void rebootAndCheckDexOptEnabled() throws Exception {
+        mDevice.reboot();
+        assertThat(mDevice.waitForBootComplete(REBOOT_TIMEOUT_MS)).isTrue();
+        // This requires PackageManager to be alive. So run after reboot as the previous failure
+        // may have device in booting state.
+        assumeTrue(checkDexOptEnabled());
+    }
+
+    private void ensurePostBootOptimizationCompleted() throws Exception {
+        if (!checkFinishedPostBootUpdate()) {
+            completePostBootOptimization();
+        }
     }
 
     private static class LastDeviceExecutionTime {
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java
deleted file mode 100644
index a4dffde..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.delegate;
-
-import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import android.app.admin.DevicePolicyManager;
-
-import java.util.List;
-
-/**
- * Test that an app given the {@link DevicePolicyManager#DELEGATION_BLOCK_UNINSTALL} scope via
- * {@link DevicePolicyManager#setDelegatedScopes} can choose packages that are block uninstalled.
- */
-public class BlockUninstallDelegateTest extends BaseJUnit3TestCase {
-
-    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
-
-    public void testCannotAccessApis() {
-        assertFalse("DelegateApp should not be a block uninstall delegate",
-            amIBlockUninstallDelegate());
-
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.setUninstallBlocked(null, TEST_APP_PKG, true);
-                });
-    }
-
-    public void testCanAccessApis() {
-        assertTrue("DelegateApp is not a block uninstall delegate",
-            amIBlockUninstallDelegate());
-        try {
-            // Exercise setUninstallBlocked.
-            mDpm.setUninstallBlocked(null, TEST_APP_PKG, true);
-            assertTrue("App not uninstall blocked", mDpm.isUninstallBlocked(null, TEST_APP_PKG));
-        } finally {
-            mDpm.setUninstallBlocked(null, TEST_APP_PKG, false);
-            assertFalse("App still uninstall blocked", mDpm.isUninstallBlocked(null, TEST_APP_PKG));
-        }
-    }
-
-    private boolean amIBlockUninstallDelegate() {
-        final String packageName = getInstrumentation().getContext().getPackageName();
-        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
-        return scopes.contains(DELEGATION_BLOCK_UNINSTALL);
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java
deleted file mode 100644
index f8c4225..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.delegate;
-
-import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Intent;
-
-import java.util.List;
-
-/**
- * Test that an app given the {@link DevicePolicyManager#DELEGATION_PERMISSION_GRANT} scope via
- * {@link DevicePolicyManager#setDelegatedScopes} can grant permissions and check permission grant
- * state.
- */
-public class EnableSystemAppDelegateTest extends BaseJUnit3TestCase {
-
-    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
-
-    public void testCannotAccessApis() {
-        assertFalse("DelegateApp should not be an enable system app delegate",
-            amIEnableSystemAppDelegate());
-
-        // Exercise enableSystemApp(String).
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.enableSystemApp(null, TEST_APP_PKG);
-                });
-
-        // Exercise enableSystemApp(Intent).
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.enableSystemApp(null, new Intent().setPackage(TEST_APP_PKG));
-                });
-    }
-
-    public void testCanAccessApis() {
-        assertTrue("DelegateApp is not an enable system app delegate",
-            amIEnableSystemAppDelegate());
-
-        // Exercise enableSystemApp(String).
-        assertExpectException(IllegalArgumentException.class,
-                "Only system apps can be enabled this way", () -> {
-                    mDpm.enableSystemApp(null, TEST_APP_PKG);
-                });
-
-        // Exercise enableSystemApp(Intent).
-        mDpm.enableSystemApp(null, new Intent());
-    }
-
-    private boolean amIEnableSystemAppDelegate() {
-        final String packageName = getInstrumentation().getContext().getPackageName();
-        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
-        return scopes.contains(DELEGATION_ENABLE_SYSTEM_APP);
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/NetworkLoggingDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/NetworkLoggingDelegateTest.java
deleted file mode 100644
index 72dbd7c..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/NetworkLoggingDelegateTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.delegate;
-
-import static android.app.admin.DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.IntentFilter;
-import android.os.UserManager;
-import android.util.Log;
-
-import com.android.bedstead.dpmwrapper.TestAppHelper;
-import com.android.cts.delegate.DelegateTestUtils.DelegatedLogsReceiver;
-
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Tests that a delegate app with DELEGATION_NETWORK_LOGGING is able to control and access
- * network logging.
- */
-public final class NetworkLoggingDelegateTest extends BaseJUnit3TestCase {
-
-    private static final String TAG = "NetworkLoggingDelegateTest";
-
-    private static final String[] URL_LIST = {
-            "example.edu",
-            "ipv6.google.com",
-            "google.co.jp",
-            "google.fr",
-            "google.com.br",
-            "google.com.tr",
-            "google.co.uk",
-            "google.de"
-    };
-
-    // TODO(b/176993670): receiver needed to forward intents from device owner user to current user
-    // on headless system user mode. Might be removed once tests are refactor to use proper IPC.
-    private DelegatedLogsReceiver mReceiver;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        if (UserManager.isHeadlessSystemUserMode()) {
-            mReceiver = new DelegatedLogsReceiver();
-            TestAppHelper.registerTestCaseReceiver(mContext, mReceiver,
-                    new IntentFilter(ACTION_NETWORK_LOGS_AVAILABLE));
-        }
-
-        DelegatedLogsReceiver.sBatchCountDown = new CountDownLatch(1);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-
-        if (mReceiver != null) {
-            TestAppHelper.unregisterTestCaseReceiver(mContext, mReceiver);
-        }
-    }
-
-
-    public void testCanAccessApis() throws Throwable {
-        assertThat(mDpm.getDelegatedScopes(null, mContext.getPackageName())).contains(
-                DevicePolicyManager.DELEGATION_NETWORK_LOGGING);
-        testNetworkLogging();
-    }
-
-    public void testCannotAccessApis()throws Exception {
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.isNetworkLoggingEnabled(null));
-
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.setNetworkLoggingEnabled(null, true));
-
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.retrieveNetworkLogs(null, 0));
-    }
-
-    public void testNetworkLogging() throws Throwable {
-        mDpm.setNetworkLoggingEnabled(null, true);
-        assertTrue(mDpm.isNetworkLoggingEnabled(null));
-
-        try {
-            for (final String url : URL_LIST) {
-                connectToWebsite(url);
-            }
-            mDevice.executeShellCommand("dpm force-network-logs");
-
-            DelegateTestUtils.DelegatedLogsReceiver.waitForBroadcast();
-        } finally {
-            mDpm.setNetworkLoggingEnabled(null, false);
-            assertFalse(mDpm.isNetworkLoggingEnabled(null));
-        }
-    }
-
-    private void connectToWebsite(String server) throws Exception {
-        final URL url = new URL("http://" + server);
-        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
-        try (AutoCloseable ac = () -> urlConnection.disconnect()){
-            urlConnection.setConnectTimeout(2000);
-            urlConnection.setReadTimeout(2000);
-            urlConnection.getResponseCode();
-        } catch (IOException e) {
-            Log.w(TAG, "Failed to connect to " + server, e);
-        }
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java
deleted file mode 100644
index c996e5f..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.delegate;
-
-import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-
-import java.util.List;
-
-/**
- * Test that an app given the {@link DevicePolicyManager#DELEGATION_PACKAGE_ACCESS} scope via
- * {@link DevicePolicyManager#setDelegatedScopes} can manage package hide and suspend status.
- */
-public class PackageAccessDelegateTest extends BaseJUnit3TestCase {
-
-    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
-
-    public void testCannotAccessApis() throws NameNotFoundException {
-        assertFalse("DelegateApp should not be a package access delegate",
-            amIPackageAccessDelegate());
-
-        // Exercise isApplicationHidden.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.isApplicationHidden(null, TEST_APP_PKG);
-                });
-
-        // Exercise setApplicationHidden.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.setApplicationHidden(null, TEST_APP_PKG, true /* hide */);
-                });
-
-        // Exercise isPackageSuspended.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.isPackageSuspended(null, TEST_APP_PKG);
-                });
-
-        // Exercise setPackagesSuspended.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.setPackagesSuspended(null, new String[] {TEST_APP_PKG}, true /* suspend */);
-                });
-    }
-
-    public void testCanAccessApis() throws NameNotFoundException {
-        assertTrue("DelegateApp is not a package access delegate", amIPackageAccessDelegate());
-
-        // Exercise isApplicationHidden.
-        assertFalse("Package should not be hidden", mDpm.isApplicationHidden(null, TEST_APP_PKG));
-
-        // Exercise setApplicationHidden.
-        assertTrue("Package not hidden successfully",
-                mDpm.setApplicationHidden(null, TEST_APP_PKG, true /* hide */));
-        assertTrue("Package should be hidden", mDpm.isApplicationHidden(null, TEST_APP_PKG));
-
-        // Exercise isPackageSuspended.
-        assertFalse("Package should not be suspended", mDpm.isPackageSuspended(null, TEST_APP_PKG));
-
-        // Exercise setPackagesSuspended.
-        String[] suspended = mDpm.setPackagesSuspended(null, new String[] {TEST_APP_PKG},
-                true /* suspend */);
-        assertTrue("Package not suspended successfully", suspended.length == 0);
-        assertTrue("Package should be suspended", mDpm.isPackageSuspended(null, TEST_APP_PKG));
-    }
-
-    private boolean amIPackageAccessDelegate() {
-        final String packageName = getInstrumentation().getContext().getPackageName();
-        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
-        return scopes.contains(DELEGATION_PACKAGE_ACCESS);
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java
deleted file mode 100644
index 9c6ac58..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.delegate;
-
-import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
-import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
-import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
-import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY;
-import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import android.app.admin.DevicePolicyManager;
-
-import java.util.List;
-
-/**
- * Test that an app given the {@link DevicePolicyManager#DELEGATION_PERMISSION_GRANT} scope via
- * {@link DevicePolicyManager#setDelegatedScopes} can grant permissions and check permission grant
- * state.
- */
-public class PermissionGrantDelegateTest extends BaseJUnit3TestCase {
-
-    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
-    private static final String TEST_PERMISSION = "android.permission.READ_CONTACTS";
-
-    public void testCannotAccessApis() {
-        assertFalse("DelegateApp should not be a permisssion grant delegate",
-            amIPermissionGrantDelegate());
-
-        // Exercise setPermissionPolicy.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.setPermissionPolicy(null, PERMISSION_POLICY_AUTO_GRANT);
-                });
-        assertFalse("Permission policy should not have been set",
-                PERMISSION_POLICY_AUTO_GRANT == mDpm.getPermissionPolicy(null));
-
-        // Exercise setPermissionGrantState.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.setPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION,
-                            PERMISSION_GRANT_STATE_GRANTED);
-                });
-
-        // Exercise getPermissionGrantState.
-        assertExpectException(SecurityException.class,
-                "Calling identity is not authorized", () -> {
-                    mDpm.getPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION);
-                });
-    }
-
-    public void testCanAccessApis() {
-        assertTrue("DelegateApp is not a permission grant delegate",
-            amIPermissionGrantDelegate());
-
-        // Exercise setPermissionPolicy.
-        mDpm.setPermissionPolicy(null, PERMISSION_POLICY_AUTO_DENY);
-        assertTrue("Permission policy was not set",
-                PERMISSION_POLICY_AUTO_DENY == mDpm.getPermissionPolicy(null));
-
-        // Exercise setPermissionGrantState.
-        assertTrue("Permission grant state was not set successfully",
-                mDpm.setPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION,
-                    PERMISSION_GRANT_STATE_DENIED));
-
-        // Exercise getPermissionGrantState.
-        assertEquals("Permission grant state is not denied", PERMISSION_GRANT_STATE_DENIED,
-                mDpm.getPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION));
-    }
-
-    private boolean amIPermissionGrantDelegate() {
-        final String packageName = getInstrumentation().getContext().getPackageName();
-        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
-        return scopes.contains(DELEGATION_PERMISSION_GRANT);
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
index baaac8d3..88e4452 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
@@ -177,11 +177,6 @@
         mDevicePolicyManager.enableSystemApp(ADMIN_RECEIVER_COMPONENT, intent);
     }
 
-    public void testSetUninstallBlockedLogged() {
-        mDevicePolicyManager.setUninstallBlocked(ADMIN_RECEIVER_COMPONENT, PACKAGE_NAME, true);
-        mDevicePolicyManager.setUninstallBlocked(ADMIN_RECEIVER_COMPONENT, PACKAGE_NAME, false);
-    }
-
     public void testSetPreferentialNetworkServiceEnabledLogged() {
         mDevicePolicyManager.setPreferentialNetworkServiceEnabled(true);
         mDevicePolicyManager.setPreferentialNetworkServiceEnabled(false);
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
index 2707856..3c4f75b 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
@@ -104,6 +104,8 @@
             .add("setPermittedInputMethods")
             .add("getDrawable")
             .add("getDrawableForDensity")
+            .add("getDevicePolicyManagementRoleHolderPackage")
+            .add("getDrawableAsIcon")
             .build();
 
     private static final String LOG_TAG = "ParentProfileTest";
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
index 918094c..5e1f248 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivity.java
@@ -20,10 +20,10 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
 import android.view.WindowManager;
 
-import java.lang.Override;
-
 /**
  * A simple activity to install for various users to test LauncherApps.
  */
@@ -46,6 +46,11 @@
         Intent reply = new Intent();
         reply.setAction(ACTIVITY_LAUNCHED_ACTION);
         sendBroadcast(reply);
+
+        final WindowInsetsController insetsController = getWindow().getInsetsController();
+        if (insetsController != null) {
+            insetsController.hide(WindowInsets.Type.navigationBars());
+        }
     }
 
     @Override
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index a1cbf9f..7f3be30 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -30,7 +30,6 @@
 
 import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.TemporarilyIgnoreOnHeadlessSystemUserMode;
 import com.android.cts.devicepolicy.annotations.LockSettingsTest;
-import com.android.cts.devicepolicy.metrics.DevicePolicyEventLogVerifier;
 import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -44,7 +43,6 @@
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -82,21 +80,12 @@
     private static final String SIMPLE_PRE_M_APP_PKG = "com.android.cts.launcherapps.simplepremapp";
     private static final String SIMPLE_PRE_M_APP_APK = "CtsSimplePreMApp.apk";
 
-    private static final String APP_RESTRICTIONS_TARGET_APP_PKG
-            = "com.android.cts.apprestrictions.targetapp";
-    private static final String APP_RESTRICTIONS_TARGET_APP_APK = "CtsAppRestrictionsTargetApp.apk";
-
     public static final String CERT_INSTALLER_PKG = "com.android.cts.certinstaller";
     public static final String CERT_INSTALLER_APK = "CtsCertInstallerApp.apk";
 
     protected static final String DELEGATE_APP_PKG = "com.android.cts.delegate";
     protected static final String DELEGATE_APP_APK = "CtsDelegateApp.apk";
     private static final String DELEGATION_CERT_INSTALL = "delegation-cert-install";
-    private static final String DELEGATION_APP_RESTRICTIONS = "delegation-app-restrictions";
-    private static final String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall";
-    private static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
-    private static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
-    private static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";
     private static final String DELEGATION_CERT_SELECTION = "delegation-cert-selection";
 
     protected static final String TEST_APP_APK = "CtsSimpleApp.apk";
@@ -106,23 +95,13 @@
     protected static final String PACKAGE_INSTALLER_PKG = "com.android.cts.packageinstaller";
     protected static final String PACKAGE_INSTALLER_APK = "CtsPackageInstallerApp.apk";
 
-    private static final String ACCOUNT_MANAGEMENT_PKG
-            = "com.android.cts.devicepolicy.accountmanagement";
-    private static final String ACCOUNT_MANAGEMENT_APK = "CtsAccountManagementDevicePolicyApp.apk";
-
     private static final String VPN_APP_PKG = "com.android.cts.vpnfirewall";
     private static final String VPN_APP_APK = "CtsVpnFirewallApp.apk";
     private static final String VPN_APP_API23_APK = "CtsVpnFirewallAppApi23.apk";
     private static final String VPN_APP_API24_APK = "CtsVpnFirewallAppApi24.apk";
     private static final String VPN_APP_NOT_ALWAYS_ON_APK = "CtsVpnFirewallAppNotAlwaysOn.apk";
 
-    private static final String COMMAND_BLOCK_ACCOUNT_TYPE = "block-accounttype";
-    private static final String COMMAND_UNBLOCK_ACCOUNT_TYPE = "unblock-accounttype";
-
-    private static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
     private static final String DISALLOW_REMOVE_USER = "no_remove_user";
-    private static final String ACCOUNT_TYPE
-            = "com.android.cts.devicepolicy.accountmanagement.account.type";
 
     private static final String CUSTOMIZATION_APP_PKG = "com.android.cts.customizationapp";
     private static final String CUSTOMIZATION_APP_APK = "CtsCustomizationApp.apk";
@@ -158,9 +137,6 @@
     protected static final String ASSIST_INTERACTION_SERVICE =
             ASSIST_APP_PKG + "/.MyInteractionService";
 
-    private static final String ARG_ALLOW_FAILURE = "allowFailure";
-    private static final String ARG_LOGGING_TEST = "loggingTest";
-
     private static final String RESTRICT_BACKGROUND_GET_CMD =
         "cmd netpolicy get restrict-background";
     private static final String RESTRICT_BACKGROUND_ON_CMD =
@@ -199,10 +175,8 @@
         getDevice().uninstallPackage(DEVICE_ADMIN_PKG);
         getDevice().uninstallPackage(PERMISSIONS_APP_PKG);
         getDevice().uninstallPackage(SIMPLE_PRE_M_APP_PKG);
-        getDevice().uninstallPackage(APP_RESTRICTIONS_TARGET_APP_PKG);
         getDevice().uninstallPackage(CERT_INSTALLER_PKG);
         getDevice().uninstallPackage(DELEGATE_APP_PKG);
-        getDevice().uninstallPackage(ACCOUNT_MANAGEMENT_PKG);
         getDevice().uninstallPackage(VPN_APP_PKG);
         getDevice().uninstallPackage(VPN_APP_API23_APK);
         getDevice().uninstallPackage(VPN_APP_API24_APK);
@@ -234,93 +208,6 @@
             "testAssertCallerIsApplicationRestrictionsManagingPackage", mUserId);
     }
 
-    /**
-     * Returns a list of delegation tests that should run. Add delegations tests applicable to both
-     * device owner and profile owners to this method directly. DO or PO specific tests should be
-     * added to {@link #getAdditionalDelegationTests} in the subclass.
-     */
-    private Map<String, DevicePolicyEventWrapper[]> getDelegationTests() {
-        final Map<String, DevicePolicyEventWrapper[]> result = new HashMap<>();
-        result.put(".BlockUninstallDelegateTest", null);
-        result.put(".PermissionGrantDelegateTest", null);
-        result.put(".PackageAccessDelegateTest", null);
-        result.put(".EnableSystemAppDelegateTest", null);
-        result.putAll(getAdditionalDelegationTests());
-        return result;
-    }
-
-    Map<String, DevicePolicyEventWrapper[]> getAdditionalDelegationTests() {
-        return Collections.<String, DevicePolicyEventWrapper[]>emptyMap();
-    }
-
-    /**
-     * Returns a list of delegation scopes that are needed to run delegation tests. Add scopes
-     * which are applicable to both device owner and profile owners to this method directly.
-     * DO or PO specific scopes should be added to {@link #getAdditionalDelegationScopes}
-     * in the subclass.
-     */
-    private List<String> getDelegationScopes() {
-        final List<String> result = new ArrayList<>(Arrays.asList(
-                DELEGATION_APP_RESTRICTIONS,
-                DELEGATION_CERT_INSTALL,
-                DELEGATION_BLOCK_UNINSTALL,
-                DELEGATION_PERMISSION_GRANT,
-                DELEGATION_PACKAGE_ACCESS,
-                DELEGATION_ENABLE_SYSTEM_APP
-                ));
-        result.addAll(getAdditionalDelegationScopes());
-        return result;
-    }
-
-    List<String> getAdditionalDelegationScopes() {
-        return Collections.<String>emptyList();
-    }
-
-    /**
-     * General instructions to add a new delegation test:
-     *
-     * <p>Implement the delegate's positive/negate functionaility tests in a new test class
-     * in CtsDelegateApp.apk. Main entry point are {@code testCanAccessApis} and
-     * {@code testCannotAccessApis}. Once implemented, add the delegation scope and the test
-     * class name to {@link #getDelegationScopes}, {@link #getDelegationTests} to make the test
-     * run on DO/PO/PO on primary user.  If the test should only run on a subset of these
-     * combinations, add them to the subclass's {@link #getAdditionalDelegationScopes} and
-     * {@link #getDelegationScopes} instead.
-     * <p>Alternatively, create a separate hostside method to drive the test, similar to
-     * {@link #testDelegationCertSelection}. This is preferred if the delegated functionalities
-     * already exist in another app.
-     */
-    @Test
-    public void testDelegation() throws Exception {
-        // Install relevant apps.
-        installDelegateApp();
-        installAppAsUser(TEST_APP_APK, mUserId);
-        installAppAsUser(APP_RESTRICTIONS_TARGET_APP_APK, mUserId);
-        if (isHeadlessSystemUserMode()) {
-            installAppAsUser(TEST_APP_APK, mDeviceOwnerUserId);
-            installAppAsUser(APP_RESTRICTIONS_TARGET_APP_APK, mDeviceOwnerUserId);
-        }
-
-        try {
-            final Map<String, DevicePolicyEventWrapper[]> delegationTests = getDelegationTests();
-            // APIs are not accessible by default.
-            executeDelegationTests(delegationTests, false /* negative result */);
-
-            // Granting the appropriate delegation scopes makes APIs accessible.
-            final List<String> scopes = getDelegationScopes();
-            setDelegatedScopes(DELEGATE_APP_PKG, scopes);
-            executeDelegationTests(delegationTests, true /* positive result */);
-
-            // APIs are not accessible after revoking delegations.
-            setDelegatedScopes(DELEGATE_APP_PKG, null);
-            executeDelegationTests(delegationTests, false /* negative result */);
-
-        } finally {
-            // Remove any remaining delegations.
-            setDelegatedScopes(DELEGATE_APP_PKG, null);
-        }
-    }
-
     protected void installDelegateApp() throws Exception {
         installAppAsUser(DELEGATE_APP_APK, mUserId);
     }
@@ -1547,19 +1434,6 @@
     }
 
     @Test
-    public void testSetUninstallBlockedLogged() throws Exception {
-        installAppAsUser(PERMISSIONS_APP_APK, mUserId);
-        assertMetricsLogged(getDevice(), () -> {
-            executeDeviceTestMethod(".DevicePolicyLoggingTest",
-                    "testSetUninstallBlockedLogged");
-        }, new DevicePolicyEventWrapper.Builder(EventId.SET_UNINSTALL_BLOCKED_VALUE)
-                .setAdminPackageName(DEVICE_ADMIN_PKG)
-                .setBoolean(false)
-                .setStrings(PERMISSIONS_APP_PKG)
-                .build());
-    }
-
-    @Test
     public void testIsDeviceOrganizationOwnedWithManagedProfile() throws Exception {
         executeDeviceTestMethod(".DeviceOwnershipTest",
                 "testCallingIsOrganizationOwnedWithManagedProfileExpectingFalse");
@@ -1684,57 +1558,11 @@
         runDeviceTestsAsUser(INTENT_SENDER_PKG, ".SuspendPackageTest", testName, mUserId);
     }
 
-    private void executeAccountTest(String testName) throws DeviceNotAvailableException {
-        runDeviceTestsAsUser(ACCOUNT_MANAGEMENT_PKG, ".AccountManagementTest",
-                testName, mUserId);
-        // Send a home intent to dismiss an error dialog.
-        String command = "am start -a android.intent.action.MAIN"
-                + " -c android.intent.category.HOME";
-        CLog.i("Output for command " + command + ": " + getDevice().executeShellCommand(command));
-    }
-
-    private void executeAppRestrictionsManagingPackageTest(String testName) throws Exception {
-        runDeviceTestsAsUser(DELEGATE_APP_PKG,
-                ".AppRestrictionsDelegateTest", testName, mUserId);
-    }
-
-    private void executeDelegationTests(Map<String, DevicePolicyEventWrapper[]> delegationTests,
-            boolean positive)
-            throws Exception {
-        for (Map.Entry<String, DevicePolicyEventWrapper[]> entry : delegationTests.entrySet()) {
-            final String delegationTestClass = entry.getKey();
-            CLog.i("executeDelegationTests(): executing %s (%s)", delegationTestClass,
-                    positive ? "positive" : "negative");
-            final DevicePolicyEventWrapper[] expectedMetrics = entry.getValue();
-            final DevicePolicyEventLogVerifier.Action testRun = () -> {
-                runDeviceTestsAsUser(DELEGATE_APP_PKG, delegationTestClass,
-                        positive ? "testCanAccessApis" : "testCannotAccessApis", mUserId);
-            };
-            if (expectedMetrics != null && positive) {
-                assertMetricsLogged(getDevice(), testRun, expectedMetrics);
-            } else {
-                testRun.apply();
-            }
-        }
-    }
-
     private void changeUserRestrictionOrFail(String key, boolean value, int userId)
             throws DeviceNotAvailableException {
         changeUserRestrictionOrFail(key, value, userId, DEVICE_ADMIN_PKG);
     }
 
-    private void changeAccountManagement(String command, String accountType, int userId)
-            throws DeviceNotAvailableException {
-        changePolicyOrFail(command, "--es extra-account-type " + accountType, userId);
-    }
-
-    private void changeApplicationRestrictionsManagingPackage(String packageName)
-            throws DeviceNotAvailableException {
-        String packageNameExtra = (packageName != null)
-                ? "--es extra-package-name " + packageName : "";
-        changePolicyOrFail("set-app-restrictions-manager", packageNameExtra, mUserId);
-    }
-
     protected void setDelegatedScopes(String packageName, List<String> scopes)
             throws DeviceNotAvailableException {
         final String packageNameExtra = "--es extra-package-name " + packageName;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 2087326..6080a3c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -516,6 +516,10 @@
                     "addCrossProfileIntents", mProfileUserId);
             runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileSharingTest",
                     "startSwitchToOtherProfileIntent", mProfileUserId);
+
+            // TODO(b/223178698): Investigate potential increase in latency
+            Thread.sleep(30000);
+
             assertResolverActivityInForeground(mProfileUserId);
         } finally {
             pressHome();
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index 1cde96f..7326b8b 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -36,10 +36,8 @@
 import org.junit.Test;
 
 import java.io.FileNotFoundException;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -48,9 +46,6 @@
  */
 public final class MixedDeviceOwnerTest extends DeviceAndProfileOwnerTest {
 
-    private static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
-    private static final String LOG_TAG_DEVICE_OWNER = "device-owner";
-
     private static final String ARG_SECURITY_LOGGING_BATCH_NUMBER = "batchNumber";
     private static final int SECURITY_EVENTS_BATCH_SIZE = 100;
 
@@ -122,14 +117,6 @@
     @Test
     @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
             reason = "Will be migrated to new test infra")
-    public void testDelegation() throws Exception {
-        super.testDelegation();
-    }
-
-    @Override
-    @Test
-    @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "218408549",
-            reason = "Will be migrated to new test infra")
     public void testDelegationCertSelection() throws Exception {
         super.testDelegationCertSelection();
     }
@@ -198,38 +185,6 @@
         executeDeviceTestMethod(".TimeManagementTest", "testSetTimeZone_failIfAutoTimeZoneEnabled");
     }
 
-    Map<String, DevicePolicyEventWrapper[]> getAdditionalDelegationTests() {
-        final Map<String, DevicePolicyEventWrapper[]> result = new HashMap<>();
-        DevicePolicyEventWrapper[] expectedMetrics = new DevicePolicyEventWrapper[] {
-                new DevicePolicyEventWrapper.Builder(EventId.SET_NETWORK_LOGGING_ENABLED_VALUE)
-                        .setAdminPackageName(DELEGATE_APP_PKG)
-                        .setBoolean(true)
-                        .setInt(1)
-                        .setStrings(LOG_TAG_DEVICE_OWNER)
-                        .build(),
-                new DevicePolicyEventWrapper.Builder(EventId.RETRIEVE_NETWORK_LOGS_VALUE)
-                        .setAdminPackageName(DELEGATE_APP_PKG)
-                        .setBoolean(true)
-                        .setStrings(LOG_TAG_DEVICE_OWNER)
-                        .build(),
-                new DevicePolicyEventWrapper.Builder(EventId.SET_NETWORK_LOGGING_ENABLED_VALUE)
-                        .setAdminPackageName(DELEGATE_APP_PKG)
-                        .setBoolean(true)
-                        .setInt(0)
-                        .setStrings(LOG_TAG_DEVICE_OWNER)
-                        .build(),
-        };
-        result.put(".NetworkLoggingDelegateTest", expectedMetrics);
-        return result;
-    }
-
-    @Override
-    List<String> getAdditionalDelegationScopes() {
-        final List<String> result = new ArrayList<>();
-        result.add(DELEGATION_NETWORK_LOGGING);
-        return result;
-    }
-
     @Test
     public void testLockScreenInfo() throws Exception {
         executeDeviceTestClass(".LockScreenInfoTest");
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index a936df2..de04f84 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -31,9 +31,6 @@
 
 import org.junit.Test;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Set of tests for managed profile owner use cases that also apply to device owners.
  * Tests that should be run identically in both cases are added in DeviceAndProfileOwnerTest.
@@ -398,11 +395,4 @@
                     "testSetNetworkLogsEnabled_false", mUserId);
         }
     }
-
-    @Override
-    List<String> getAdditionalDelegationScopes() {
-        final List<String> result = new ArrayList<>();
-        result.add(DELEGATION_NETWORK_LOGGING);
-        return result;
-    }
 }
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index 4311426..f7c8e14 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -151,6 +151,11 @@
     public static final File CEC_MAP_FOLDER =
             new File(System.getProperty("java.io.tmpdir"), "cec-cts-temp");
 
+    // CEC Settings
+    public static final String SETTING_VOLUME_CONTROL_ENABLED = "volume_control_enabled";
+
+    // CEC Settings Values
+    public static final String VOLUME_CONTROL_ENABLED = "1";
 
     // Power Control Modes for source devices
     public static final String POWER_CONTROL_MODE_BROADCAST = "broadcast";
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index 18fe41f..baaccc8 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -30,7 +30,6 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -205,13 +204,18 @@
      * not turned on.
      */
     @Test
-    @Ignore("b/218266432")
     public void cect_sendVolumeKeyPressToTv() throws Exception {
         ITestDevice device = getDevice();
         String ucpMessage;
         String command = "cmd hdmi_control setsam ";
 
         simulateCecSinkConnected(device, getTargetLogicalAddress());
+        String volumeControlEnabled =
+                getSettingsValue(device, HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED);
+        setSettingsValue(
+                device,
+                HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED,
+                HdmiCecConstants.VOLUME_CONTROL_ENABLED);
 
         boolean wasSystemAudioModeOn = isSystemAudioModeOn(device);
         if (wasSystemAudioModeOn) {
@@ -243,6 +247,8 @@
             if (wasSystemAudioModeOn) {
                 device.executeShellCommand(command + "on");
             }
+            setSettingsValue(
+                    device, HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED, volumeControlEnabled);
         }
     }
 }
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
index 718ae56..e8c0a3c 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
@@ -28,7 +28,6 @@
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Rule;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
 import org.junit.runner.RunWith;
@@ -57,21 +56,34 @@
      * the audio rendering.
      */
     @Test
-    @Ignore("b/218266432")
     public void cect_hf4_10_5_RemoteControlCommandsWithSystemAudioControlProperty()
             throws Exception {
         setCec20();
 
         ITestDevice device = getDevice();
-        // Broadcast <Set System Audio Mode> ["off"].
-        broadcastSystemAudioModeMessage(false);
-        // All remote control commands should forward to the TV.
-        sendVolumeUpCommandAndCheckForUcp(LogicalAddress.TV);
+        String volumeControlEnabled =
+                getSettingsValue(device, HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED);
 
-        // Broadcast <Set System Audio Mode> ["on"].
-        broadcastSystemAudioModeMessage(true);
-        // All remote control commands should forward to the audio rendering device.
-        sendVolumeUpCommandAndCheckForUcp(LogicalAddress.AUDIO_SYSTEM);
+        try {
+            simulateCecSinkConnected(device, getTargetLogicalAddress());
+            setSettingsValue(
+                    device,
+                    HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED,
+                    HdmiCecConstants.VOLUME_CONTROL_ENABLED);
+
+            // Broadcast <Set System Audio Mode> ["off"].
+            broadcastSystemAudioModeMessage(false);
+            // All remote control commands should forward to the TV.
+            sendVolumeUpCommandAndCheckForUcp(LogicalAddress.TV);
+
+            // Broadcast <Set System Audio Mode> ["on"].
+            broadcastSystemAudioModeMessage(true);
+            // All remote control commands should forward to the audio rendering device.
+            sendVolumeUpCommandAndCheckForUcp(LogicalAddress.AUDIO_SYSTEM);
+        } finally {
+            setSettingsValue(
+                    device, HdmiCecConstants.SETTING_VOLUME_CONTROL_ENABLED, volumeControlEnabled);
+        }
     }
 
     private void broadcastSystemAudioModeMessage(boolean val) throws Exception {
diff --git a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
index fb37109..76bdaf7 100644
--- a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
+++ b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
@@ -30,6 +30,7 @@
 import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_2;
 import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_3;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -46,6 +47,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -53,6 +55,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 @LargeTest
 public class MediaRouter2Test {
@@ -77,14 +80,14 @@
         List<String> features = new ArrayList<>();
         features.add("A test feature");
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(features, /*activeScan=*/false).build();
+                new RouteDiscoveryPreference.Builder(features, /*activeScan=*/ false).build();
         mRouter2.registerRouteCallback(mExecutor, mRouterDummyCallback, preference);
     }
 
     @Test
     public void dontDedupeByDefault() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/  true).build();
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true).build();
         Map<String, MediaRoute2Info> routes =
                 waitAndGetRoutes(preference, Set.of(ROUTE_ID_1_1, ROUTE_ID_2_1, ROUTE_ID_3_1));
 
@@ -102,7 +105,7 @@
     @Test
     public void setDeduplicationPackageOrder1() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_1_PACKAGE,
@@ -126,7 +129,7 @@
     @Test
     public void setDeduplicationPackageOrder2() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_3_PACKAGE,
@@ -150,7 +153,7 @@
     @Test
     public void setDeduplicationPackageOrder3() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_2_PACKAGE,
@@ -171,6 +174,89 @@
         assertFalse(routes.containsKey(ROUTE_ID_3_3));
     }
 
+    @Test
+    public void testRouteCallbacks() throws Exception {
+        Set<String> addedRouteIds = new HashSet<>();
+        Set<String> removedRouteIds = new HashSet<>();
+
+        AtomicReference<CountDownLatch> addLatchRef = new AtomicReference<>();
+        AtomicReference<CountDownLatch> removeLatchRef = new AtomicReference<>();
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+
+        RouteDiscoveryPreference preference =
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
+                        .setAllowedPackages(List.of(MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+                        .setDeduplicationPackageOrder(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_3_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+                        .build();
+        MediaRouter2.RouteCallback routeCallback =
+                new MediaRouter2.RouteCallback() {
+                    @Override
+                    public void onRoutesAdded(List<MediaRoute2Info> routes) {
+                        for (MediaRoute2Info route : routes) {
+                            if (!route.isSystemRoute()) {
+                                addedRouteIds.add(route.getOriginalId());
+                            }
+                        }
+                        addLatchRef.get().countDown();
+                    }
+
+                    @Override
+                    public void onRoutesRemoved(List<MediaRoute2Info> routes) {
+                        for (MediaRoute2Info route : routes) {
+                            removedRouteIds.add(route.getOriginalId());
+                        }
+                        removeLatchRef.get().countDown();
+                    }
+                };
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertFalse(removeLatchRef.get().await(WAIT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_1_1, ROUTE_ID_1_2, ROUTE_ID_1_3), addedRouteIds);
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+        RouteDiscoveryPreference preference2 =
+                new RouteDiscoveryPreference.Builder(preference)
+                        .setAllowedPackages(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE))
+                        .build();
+
+        addedRouteIds.clear();
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference2);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_2_1, ROUTE_ID_2_2, ROUTE_ID_2_3), addedRouteIds);
+        assertEquals(Set.of(ROUTE_ID_1_2), removedRouteIds);
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+        RouteDiscoveryPreference preference3 =
+                new RouteDiscoveryPreference.Builder(preference)
+                        .setAllowedPackages(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_3_PACKAGE))
+                        .build();
+
+        addedRouteIds.clear();
+        removedRouteIds.clear();
+
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference3);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_3_1, ROUTE_ID_3_2), addedRouteIds);
+        assertEquals(Set.of(ROUTE_ID_1_3), removedRouteIds);
+    }
+
     // It returns original route id -> route for convenience
     private static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
         Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
index df6ebeb..32adb1e 100644
--- a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
+++ b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
@@ -66,4 +66,10 @@
         runDeviceTests(
                 MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "setDeduplicationPackageOrder3");
     }
+
+    @AppModeFull
+    @RequiresDevice
+    public void testCallback() throws Exception {
+        runDeviceTests(MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testRouteCallbacks");
+    }
 }
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index 57abfec..d50ff73 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -33,6 +33,22 @@
 }
 
 android_test_helper_app {
+    name: "CtsScopedStorageTestAppA31",
+    manifest: "ScopedStorageTestHelper/TestAppA31.xml",
+    static_libs: ["cts-scopedstorage-lib"],
+    sdk_version: "test_current",
+    target_sdk_version: "31",
+    min_sdk_version: "30",
+    srcs: ["ScopedStorageTestHelper/src/**/*.java"],
+    // Tag as a CTS artifact
+    test_suites: [
+        "general-tests",
+        "mts-mediaprovider",
+        "cts",
+    ],
+}
+
+android_test_helper_app {
     name: "CtsScopedStorageTestAppB",
     manifest: "ScopedStorageTestHelper/TestAppB.xml",
     static_libs: ["cts-scopedstorage-lib"],
@@ -213,6 +229,7 @@
     min_sdk_version: "30",
     java_resources: [
         ":CtsScopedStorageTestAppA",
+        ":CtsScopedStorageTestAppA31",
         ":CtsScopedStorageTestAppB",
         ":CtsScopedStorageTestAppC",
         ":CtsScopedStorageTestAppCLegacy",
diff --git a/hostsidetests/scopedstorage/AndroidManifest.xml b/hostsidetests/scopedstorage/AndroidManifest.xml
index 9d45439..39dc12e 100644
--- a/hostsidetests/scopedstorage/AndroidManifest.xml
+++ b/hostsidetests/scopedstorage/AndroidManifest.xml
@@ -19,6 +19,10 @@
 
     <uses-sdk android:minSdkVersion="30" />
 
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
diff --git a/hostsidetests/scopedstorage/CoreTest.xml b/hostsidetests/scopedstorage/CoreTest.xml
index f9eaa20..1aac1dd 100644
--- a/hostsidetests/scopedstorage/CoreTest.xml
+++ b/hostsidetests/scopedstorage/CoreTest.xml
@@ -24,6 +24,7 @@
         <option name="test-file-name" value="ScopedStorageTest.apk" />
         <option name="test-file-name" value="LegacyStorageTest.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppA.apk" />
+        <option name="test-file-name" value="CtsScopedStorageTestAppA31.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppB.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
     </target_preparer>
diff --git a/hostsidetests/scopedstorage/PublicVolumeTest.xml b/hostsidetests/scopedstorage/PublicVolumeTest.xml
index 1dc4017..c52a067 100644
--- a/hostsidetests/scopedstorage/PublicVolumeTest.xml
+++ b/hostsidetests/scopedstorage/PublicVolumeTest.xml
@@ -20,6 +20,7 @@
         <option name="test-file-name" value="ScopedStorageTest.apk" />
         <option name="test-file-name" value="LegacyStorageTest.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppA.apk" />
+        <option name="test-file-name" value="CtsScopedStorageTestAppA31.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppB.apk" />
         <option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
     </target_preparer>
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA.xml
index b9b3f0c..885497b 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA.xml
@@ -22,6 +22,9 @@
     <uses-sdk android:minSdkVersion="30" />
 
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
 
     <application android:label="TestAppA">
         <activity android:name="android.scopedstorage.cts.ScopedStorageTestHelper" android:exported="true" >
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA31.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA31.xml
new file mode 100644
index 0000000..68e6a15
--- /dev/null
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppA31.xml
@@ -0,0 +1,45 @@
+<?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.scopedstorage.cts.testapp.A31.withres"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="31"/>
+
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+    <application android:label="TestAppA">
+        <activity android:name="android.scopedstorage.cts.ScopedStorageTestHelper" android:exported="true" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="android.scopedstorage.cts.testapp.A31.withres"
+            android:exported="false"
+            android:grantUriPermissions="true">
+          <meta-data
+              android:name="android.support.FILE_PROVIDER_PATHS"
+              android:resource="@xml/file_paths" />
+        </provider>
+    </application>
+</manifest>
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC.xml
index cf9c7fe..a6d1cb8 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC.xml
@@ -21,6 +21,9 @@
 
   <uses-sdk android:minSdkVersion="30" />
 
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC30.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC30.xml
index 17f63d1..4010295 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC30.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppC30.xml
@@ -21,6 +21,9 @@
 
   <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
 
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManager.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManager.xml
index dd01db9..e49af51 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManager.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManager.xml
@@ -21,6 +21,9 @@
 
     <uses-sdk android:minSdkVersion="30" />
 
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
 
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml
index 29b7151..5b9c657 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml
@@ -21,6 +21,9 @@
 
     <uses-sdk android:minSdkVersion="30" />
 
+    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
 
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml
index ae0ec51..2813a03 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml
@@ -22,6 +22,9 @@
 
   <uses-sdk android:minSdkVersion="30" />
 
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index ee63a8a..2f37855 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -52,6 +52,7 @@
 import android.media.ExifInterface;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.provider.MediaStore;
 
 import androidx.annotation.Nullable;
@@ -158,10 +159,11 @@
         try {
             final String mode = queryType.equals(IS_URI_REDACTED_VIA_FILE_DESCRIPTOR_FOR_WRITE)
                     ? "w" : "r";
-            FileDescriptor fd = getContentResolver().openFileDescriptor(uri,
-                    mode).getFileDescriptor();
-            ExifInterface exifInterface = new ExifInterface(fd);
-            intent.putExtra(queryType, exifInterface.getGpsDateTime() == -1);
+            try (ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, mode)) {
+                FileDescriptor fd = pfd.getFileDescriptor();
+                ExifInterface exifInterface = new ExifInterface(fd);
+                intent.putExtra(queryType, exifInterface.getGpsDateTime() == -1);
+            }
         } catch (Exception e) {
             intent.putExtra(INTENT_EXCEPTION, e);
         }
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
index 2e8ccdae5..b23f945 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/RedactUriDeviceTest.java
@@ -50,6 +50,7 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
 import android.provider.MediaStore;
 
 import androidx.test.filters.SdkSuppress;
@@ -447,9 +448,10 @@
         try {
             assertUriIsUnredacted(img);
 
-            InputStream is = getContentResolver().openInputStream(redactedUri);
-            ExifInterface redactedExifInf = new ExifInterface(is);
-            assertUriIsRedacted(redactedExifInf);
+            try (InputStream is = getContentResolver().openInputStream(redactedUri)) {
+                ExifInterface redactedExifInf = new ExifInterface(is);
+                assertUriIsRedacted(redactedExifInf);
+            }
         } finally {
             img.delete();
         }
@@ -462,10 +464,12 @@
         try {
             assertUriIsUnredacted(img);
 
-            FileDescriptor fd = getContentResolver().openFileDescriptor(redactedUri,
-                    "r").getFileDescriptor();
-            ExifInterface redactedExifInf = new ExifInterface(fd);
-            assertUriIsRedacted(redactedExifInf);
+            try (ParcelFileDescriptor pfd =
+                    getContentResolver().openFileDescriptor(redactedUri, "r")) {
+                FileDescriptor fd = pfd.getFileDescriptor();
+                ExifInterface redactedExifInf = new ExifInterface(fd);
+                assertUriIsRedacted(redactedExifInf);
+            }
         } finally {
             img.delete();
         }
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 756e425..1a3bff9 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -198,10 +198,14 @@
 
     // The following apps are installed before the tests are run via a target_preparer.
     // See test config for details.
-    // An app with READ_EXTERNAL_STORAGE permission
-    private static final TestApp APP_A_HAS_RES = new TestApp("TestAppA",
-            "android.scopedstorage.cts.testapp.A.withres", 1, false,
-            "CtsScopedStorageTestAppA.apk");
+    // An app with READ_EXTERNAL_STORAGE and READ_MEDIA_* permissions
+    private static final TestApp APP_A_HAS_RES =
+            new TestApp(
+                    "TestAppA",
+                    "android.scopedstorage.cts.testapp.A.withres",
+                    1,
+                    false,
+                    "CtsScopedStorageTestAppA.apk");
     // An app with no permissions
     private static final TestApp APP_B_NO_PERMS = new TestApp("TestAppB",
             "android.scopedstorage.cts.testapp.B.noperms", 1, false,
@@ -895,11 +899,11 @@
         try {
             assertThat(file.createNewFile()).isTrue();
 
-            ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
-            ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
-
-            assertRWR(readPfd, writePfd);
-            assertUpperFsFd(writePfd); // With cache
+            try (ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
+                 ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw")) {
+                assertRWR(readPfd, writePfd);
+                assertUpperFsFd(writePfd); // With cache
+            }
         } finally {
             file.delete();
         }
@@ -913,11 +917,11 @@
         try {
             assertThat(file.createNewFile()).isTrue();
 
-            ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
-            ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
-
-            assertRWR(readPfd, writePfd);
-            assertLowerFsFdWithPassthrough(writePfd);
+            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
+                 ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
+                assertRWR(readPfd, writePfd);
+                assertLowerFsFdWithPassthrough(writePfd);
+            }
         } finally {
             file.delete();
         }
@@ -931,11 +935,11 @@
         try {
             assertThat(file.createNewFile()).isTrue();
 
-            ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
-            ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
-
-            assertRWR(readPfd, writePfd);
-            assertUpperFsFd(readPfd); // With cache
+            try (ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
+                 ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw")) {
+                assertRWR(readPfd, writePfd);
+                assertUpperFsFd(readPfd); // With cache
+            }
         } finally {
             file.delete();
         }
@@ -949,11 +953,11 @@
         try {
             assertThat(file.createNewFile()).isTrue();
 
-            ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
-            ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
-
-            assertRWR(readPfd, writePfd);
-            assertLowerFsFdWithPassthrough(readPfd);
+            try (ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
+                 ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
+                assertRWR(readPfd, writePfd);
+                assertLowerFsFdWithPassthrough(readPfd);
+            }
         } finally {
             file.delete();
         }
@@ -968,13 +972,13 @@
             assertThat(file.createNewFile()).isTrue();
 
             // We upgrade 'w' only to 'rw'
-            ParcelFileDescriptor writePfd = openWithMediaProvider(file, "w");
-            ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
-
-            assertRWR(readPfd, writePfd);
-            assertRWR(writePfd, readPfd); // Can read on 'w' only pfd
-            assertLowerFsFdWithPassthrough(writePfd);
-            assertLowerFsFdWithPassthrough(readPfd);
+            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "w");
+                 ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw")) {
+                assertRWR(readPfd, writePfd);
+                assertRWR(writePfd, readPfd); // Can read on 'w' only pfd
+                assertLowerFsFdWithPassthrough(writePfd);
+                assertLowerFsFdWithPassthrough(readPfd);
+            }
         } finally {
             file.delete();
         }
@@ -991,15 +995,13 @@
 
             // Even if we close the original fd, since we have a dup open
             // the FUSE IO should still bypass the cache
-            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw")) {
-                try (ParcelFileDescriptor writePfdDup = writePfd.dup();
-                     ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(
-                             file, MODE_READ_WRITE)) {
-                    writePfd.close();
+            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
+                 ParcelFileDescriptor writePfdDup = writePfd.dup();
+                 ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
+                writePfd.close();
 
-                    assertRWR(readPfd, writePfdDup);
-                    assertLowerFsFdWithPassthrough(writePfdDup);
-                }
+                assertRWR(readPfd, writePfdDup);
+                assertLowerFsFdWithPassthrough(writePfdDup);
             }
         } finally {
             file.delete();
@@ -1026,12 +1028,13 @@
             writePfd.close();
 
             // Upper fs open and read without direct_io
-            ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
-            Os.pread(readPfd.getFileDescriptor(), readBuffer, 0, 10, 0);
+            try (ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
+                Os.pread(readPfd.getFileDescriptor(), readBuffer, 0, 10, 0);
 
-            // Last write on lower fs is visible via upper fs
-            assertThat(readBuffer).isEqualTo(writeBuffer);
-            assertThat(readPfd.getStatSize()).isEqualTo(writeBuffer.length);
+                // Last write on lower fs is visible via upper fs
+                assertThat(readBuffer).isEqualTo(writeBuffer);
+                assertThat(readPfd.getStatSize()).isEqualTo(writeBuffer.length);
+            }
         } finally {
             file.delete();
         }
@@ -1260,9 +1263,12 @@
 
     @Test
     public void testReadStorageInvalidation() throws Exception {
-        testAppOpInvalidation(APP_C, new File(getDcimDir(), "read_storage.jpg"),
-                Manifest.permission.READ_EXTERNAL_STORAGE,
-                AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, /* forWrite */ false);
+        testAppOpInvalidation(
+                APP_C,
+                new File(getDcimDir(), "read_storage.jpg"),
+                Manifest.permission.READ_MEDIA_IMAGES,
+                AppOpsManager.OPSTR_READ_MEDIA_IMAGES,
+                /* forWrite */ false);
     }
 
     @Test
@@ -1435,7 +1441,6 @@
             Thread.sleep(200);
         }
         assertThat(canOpenFileAs(app, file, forWrite)).isTrue();
-
         // Deny
         if (permission != null) {
             revokePermission(packageName, permission);
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageCoreHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageCoreHostTest.java
index 7d8a6e7..c2414dd 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageCoreHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageCoreHostTest.java
@@ -61,8 +61,12 @@
 
     @Before
     public void revokeStoragePermissions() throws Exception {
-        revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
-                "android.permission.READ_EXTERNAL_STORAGE");
+        revokePermissions(
+                "android.permission.WRITE_EXTERNAL_STORAGE",
+                "android.permission.READ_EXTERNAL_STORAGE",
+                "android.permission.READ_MEDIA_AUDIO",
+                "android.permission.READ_MEDIA_VIDEO",
+                "android.permission.READ_MEDIA_IMAGES");
     }
 
     @After
@@ -93,10 +97,71 @@
     @Test
     public void testAccess_file() throws Exception {
         grantPermissions("android.permission.READ_EXTERNAL_STORAGE");
+        grantPermissions("android.permission.READ_MEDIA_IMAGES");
         try {
             runDeviceTest("testAccess_file");
         } finally {
             revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
+            revokePermissions("android.permission.READ_MEDIA_IMAGES");
+        }
+    }
+
+    @Test
+    public void testAccess_MediaFile() throws Exception {
+        grantPermissions("android.permission.READ_MEDIA_IMAGES");
+        grantPermissions("android.permission.READ_MEDIA_AUDIO");
+        grantPermissions("android.permission.READ_MEDIA_VIDEO");
+        try {
+            runDeviceTest("testAccess_MediaFile");
+        } finally {
+            revokePermissions("android.permission.READ_MEDIA_IMAGES");
+            revokePermissions("android.permission.READ_MEDIA_AUDIO");
+            revokePermissions("android.permission.READ_MEDIA_VIDEO");
+        }
+    }
+
+    @Test
+    public void testAccess_OnlyAudioFile() throws Exception {
+        grantPermissions("android.permission.READ_MEDIA_AUDIO");
+        try {
+            runDeviceTest("testAccess_OnlyAudioFile");
+        } finally {
+            revokePermissions("android.permission.READ_MEDIA_AUDIO");
+        }
+    }
+
+    @Test
+    public void testAccess_OnlyVideoFile() throws Exception {
+        grantPermissions("android.permission.READ_MEDIA_VIDEO");
+        try {
+            runDeviceTest("testAccess_OnlyVideoFile");
+        } finally {
+            revokePermissions("android.permission.READ_MEDIA_VIDEO");
+        }
+    }
+
+    @Test
+    public void testAccess_OnlyImageFile() throws Exception {
+        grantPermissions("android.permission.READ_MEDIA_IMAGES");
+        try {
+            runDeviceTest("testAccess_OnlyImageFile");
+        } finally {
+            revokePermissions("android.permission.READ_MEDIA_IMAGES");
+        }
+    }
+
+    @Test
+    public void testAccess_MediaFileLegacy() throws Exception {
+        runDeviceTest("testAccess_MediaFileLegacy");
+    }
+
+    @Test
+    public void testAccess_MediaFileWithRES() throws Exception {
+        grantPermissions("android.permission.READ_EXTERNAL_STORAGE");
+        try {
+            runDeviceTest("testAccess_MediaFileWithRES");
+        } finally {
+            revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
         }
     }
 
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 314dbb4..7c27ee7 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -586,6 +586,9 @@
             assertThat(InstallUtils.getInstalledVersion(packageName)).isEqualTo(1);
             if (grantStoragePermission) {
                 grantPermission(packageName, Manifest.permission.READ_EXTERNAL_STORAGE);
+                grantPermission(packageName, Manifest.permission.READ_MEDIA_IMAGES);
+                grantPermission(packageName, Manifest.permission.READ_MEDIA_AUDIO);
+                grantPermission(packageName, Manifest.permission.READ_MEDIA_VIDEO);
             }
         } finally {
             uiAutomation.dropShellPermissionIdentity();
@@ -856,8 +859,7 @@
      * Returns whether we can open the file.
      */
     public static boolean canOpen(File file, boolean forWrite) {
-        try {
-            openWithFilePath(file, forWrite);
+        try (ParcelFileDescriptor ignore = openWithFilePath(file, forWrite)) {
             return true;
         } catch (IOException expected) {
             return false;
@@ -1702,7 +1704,7 @@
     private static boolean isVolumeMounted(String type) {
         try {
             final String volume = executeShellCommand("sm list-volumes " + type).trim();
-            return volume != null && volume.contains("mounted");
+            return volume != null && volume.contains(" mounted");
         } catch (Exception e) {
             return false;
         }
@@ -1716,6 +1718,18 @@
         return isVolumeMounted("emulated");
     }
 
+    private static boolean isFuseReady() {
+        for (String volumeName : MediaStore.getExternalVolumeNames(getContext())) {
+            final Uri uri = MediaStore.Files.getContentUri(volumeName);
+            try (Cursor c = getContentResolver().query(uri, null, null, null)) {
+                assertThat(c).isNotNull();
+            } catch (IllegalArgumentException e) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Prepare or create a public volume for testing
      */
@@ -1734,6 +1748,8 @@
                     "Timed out while waiting for public volume");
             pollForCondition(TestUtils::isEmulatedVolumeMounted,
                     "Timed out while waiting for emulated volume");
+            pollForCondition(TestUtils::isFuseReady,
+                    "Timed out while waiting for fuse");
         }
     }
 
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index ebc8f10..14bbcb0 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -28,6 +28,7 @@
 import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
 import static android.scopedstorage.cts.lib.TestUtils.assertThrows;
 import static android.scopedstorage.cts.lib.TestUtils.canOpen;
+import static android.scopedstorage.cts.lib.TestUtils.canOpenFileAs;
 import static android.scopedstorage.cts.lib.TestUtils.canReadAndWriteAs;
 import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
 import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
@@ -135,10 +136,25 @@
 
     // The following apps are installed before the tests are run via a target_preparer.
     // See test config for details.
-    // An app with READ_EXTERNAL_STORAGE permission
-    private static final TestApp APP_A_HAS_RES = new TestApp("TestAppA",
-            "android.scopedstorage.cts.testapp.A.withres", 1, false,
-            "CtsScopedStorageTestAppA.apk");
+
+    // An app with READ_EXTERNAL_STORAGE and READ_MEDIA_* permissions.
+    // R_E_S permission isn't actually used since the app targets T+,
+    // the R_M_* permissions will be checked instead.
+    private static final TestApp APP_A_HAS_READ_MEDIA_ALL =
+            new TestApp(
+                    "TestAppA",
+                    "android.scopedstorage.cts.testapp.A.withres",
+                    1,
+                    false,
+                    "CtsScopedStorageTestAppA.apk");
+    // An app with READ_EXTERNAL_STORAGE permission with targetSdk 31
+    private static final TestApp APP_A_HAS_RES_31 =
+            new TestApp(
+                    "TestAppA31",
+                    "android.scopedstorage.cts.testapp.A31.withres",
+                    1,
+                    false,
+                    "CtsScopedStorageTestAppA31.apk");
     // An app with no permissions
     private static final TestApp APP_B_NO_PERMS = new TestApp("TestAppB",
             "android.scopedstorage.cts.testapp.B.noperms", 1, false,
@@ -212,10 +228,10 @@
 
         // Let app A create a file in its data dir
         final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
-                THIS_PACKAGE_NAME, APP_A_HAS_RES.getPackageName()));
+                THIS_PACKAGE_NAME, APP_A_HAS_READ_MEDIA_ALL.getPackageName()));
         final File otherAppExternalDataFile = new File(otherAppExternalDataDir,
                 NONMEDIA_FILE_NAME);
-        assertCreateFilesAs(APP_A_HAS_RES, otherAppExternalDataFile);
+        assertCreateFilesAs(APP_A_HAS_READ_MEDIA_ALL, otherAppExternalDataFile);
 
         // File Manager app gets global access with MANAGE_EXTERNAL_STORAGE permission, however,
         // file manager app doesn't have access to other app's external files directory
@@ -223,7 +239,8 @@
         assertThat(canOpen(otherAppExternalDataFile, /* forWrite */ true)).isFalse();
         assertThat(otherAppExternalDataFile.delete()).isFalse();
 
-        assertThat(deleteFileAs(APP_A_HAS_RES, otherAppExternalDataFile.getPath())).isTrue();
+        assertThat(deleteFileAs(APP_A_HAS_READ_MEDIA_ALL,
+            otherAppExternalDataFile.getPath())).isTrue();
 
         assertThrows(IOException.class,
                 () -> {
@@ -282,8 +299,167 @@
     }
 
     @Test
+    public void testAccess_OnlyImageFile() throws Exception {
+        pollForPermission(Manifest.permission.READ_MEDIA_IMAGES, /*granted*/ true);
+
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // We can read the other app's image file only because we hold R_M_I.
+            assertCannotReadOrWrite(otherAppAudio);
+            assertFileAccess_readOnly(otherAppImage);
+            assertCannotReadOrWrite(otherAppVideo);
+
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+        }
+    }
+
+    @Test
+    public void testAccess_OnlyVideoFile() throws Exception {
+        pollForPermission(Manifest.permission.READ_MEDIA_VIDEO, /*granted*/ true);
+
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // We can read the other app's video file only because we hold R_M_V.
+            assertCannotReadOrWrite(otherAppImage);
+            assertFileAccess_readOnly(otherAppVideo);
+            assertCannotReadOrWrite(otherAppAudio);
+
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+        }
+    }
+
+    @Test
+    public void testAccess_OnlyAudioFile() throws Exception {
+        pollForPermission(Manifest.permission.READ_MEDIA_AUDIO, /*granted*/ true);
+
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // We can read the other app's audio file only because we hold R_M_A.
+            assertCannotReadOrWrite(otherAppImage);
+            assertFileAccess_readOnly(otherAppAudio);
+            assertCannotReadOrWrite(otherAppVideo);
+
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+        }
+    }
+
+    @Test
+    public void testAccess_MediaFile() throws Exception {
+        pollForPermission(Manifest.permission.READ_MEDIA_IMAGES, /*granted*/ true);
+        pollForPermission(Manifest.permission.READ_MEDIA_AUDIO, /*granted*/ true);
+        pollForPermission(Manifest.permission.READ_MEDIA_VIDEO, /*granted*/ true);
+
+        final File downloadDir = getDownloadDir();
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+        final File myAppPdf = new File(downloadDir, "my-" + NONMEDIA_FILE_NAME);
+
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // We can read our image and pdf files.
+            assertThat(myAppPdf.createNewFile()).isTrue();
+            assertFileAccess_readWrite(myAppPdf);
+
+            // We can read the other app media files because we hold R_M_*.
+            assertFileAccess_readOnly(otherAppImage);
+            assertFileAccess_readOnly(otherAppVideo);
+            assertFileAccess_readOnly(otherAppAudio);
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+            myAppPdf.delete();
+        }
+    }
+
+    /** R_E_S can't give access to media files anymore. */
+    @Test
+    public void testAccess_MediaFileWithRES() throws Exception {
+        pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
+
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // Can't read the other app media even with R_E_S.
+            assertCannotReadOrWrite(otherAppImage);
+            assertCannotReadOrWrite(otherAppVideo);
+            assertCannotReadOrWrite(otherAppAudio);
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+        }
+    }
+
+    // R_E_S with targetsdk 31 can still access media files.
+    @Test
+    public void testAccess_MediaFileLegacy() throws Exception {
+        final File otherAppImage = new File(getDcimDir(), "other-" + IMAGE_FILE_NAME);
+        final File otherAppVideo = new File(getDcimDir(), "other-" + VIDEO_FILE_NAME);
+        final File otherAppAudio = new File(getMusicDir(), "other-" + AUDIO_FILE_NAME);
+        try {
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImage.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideo.getPath())).isTrue();
+            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudio.getPath())).isTrue();
+
+            // Can read the other app media files because of holding R_E_S with targetsdk31.
+            assertThat(canOpenFileAs(APP_A_HAS_RES_31, otherAppImage, false /* forWrite */))
+                    .isTrue();
+            assertThat(canOpenFileAs(APP_A_HAS_RES_31, otherAppVideo, false /* forWrite */))
+                    .isTrue();
+            assertThat(canOpenFileAs(APP_A_HAS_RES_31, otherAppAudio, false /* forWrite */))
+                    .isTrue();
+        } finally {
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImage.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideo.getAbsolutePath());
+            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppAudio.getAbsolutePath());
+        }
+    }
+
+    @Test
     public void testAccess_file() throws Exception {
         pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
+        pollForPermission(Manifest.permission.READ_MEDIA_IMAGES, /*granted*/ true);
 
         final File downloadDir = getDownloadDir();
         final File otherAppPdf = new File(downloadDir, "other-" + NONMEDIA_FILE_NAME);
@@ -301,7 +477,7 @@
             assertThat(myAppPdf.createNewFile()).isTrue();
             assertFileAccess_readWrite(myAppPdf);
 
-            // We can read the other app's image file because we hold R_E_S, but we can
+            // We can read the other app's image file because we hold R_M_I, but we can
             // check only exists for the pdf files.
             assertFileAccess_readOnly(otherAppImage);
             assertFileAccess_existsOnly(otherAppPdf);
@@ -768,7 +944,9 @@
             assertCanQueryAndOpenFile(otherPendingFile, "r");
 
             // We can also read other app's pending file via MediaStore API
-            assertNotNull(openWithMediaProvider(otherPendingFile, "r"));
+            try (ParcelFileDescriptor pfd = openWithMediaProvider(otherPendingFile, "r")) {
+                assertNotNull(pfd);
+            }
         } finally {
             deleteFileAsNoThrow(APP_B_NO_PERMS, otherPendingFile.getAbsolutePath());
         }
@@ -798,10 +976,10 @@
         }
         // Let app A create a file in its data dir
         final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
-                THIS_PACKAGE_NAME, APP_A_HAS_RES.getPackageName()));
+                THIS_PACKAGE_NAME, APP_A_HAS_READ_MEDIA_ALL.getPackageName()));
         final File otherAppExternalDataFile = new File(otherAppExternalDataDir,
                 NONMEDIA_FILE_NAME);
-        assertCreateFilesAs(APP_A_HAS_RES, otherAppExternalDataFile);
+        assertCreateFilesAs(APP_A_HAS_READ_MEDIA_ALL, otherAppExternalDataFile);
 
         // File Manager app gets global access with MANAGE_EXTERNAL_STORAGE permission, however,
         // file manager app doesn't have access to other app's external files directory
@@ -809,7 +987,8 @@
         assertThat(canOpen(otherAppExternalDataFile, /* forWrite */ true)).isFalse();
         assertThat(otherAppExternalDataFile.delete()).isFalse();
 
-        assertThat(deleteFileAs(APP_A_HAS_RES, otherAppExternalDataFile.getPath())).isTrue();
+        assertThat(deleteFileAs(APP_A_HAS_READ_MEDIA_ALL,
+            otherAppExternalDataFile.getPath())).isTrue();
 
         assertThrows(IOException.class,
                 () -> {
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.bp
index 9b5a6ca..5e9597d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9537/Android.bp
@@ -30,8 +30,11 @@
         "external/aac/libSYS/include",
         "external/aac/libAACdec/include",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
     cflags: [
         "-DCHECK_OVERFLOW",
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9549/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9549/Android.bp
index 5b9e6dd..651c36f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9549/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9549/Android.bp
@@ -25,8 +25,11 @@
     srcs : [
         "poc.cpp",
     ],
-    shared_libs : [
-        "libbluetooth",
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
+    shared_libs: [
+        "liblog",
     ],
     include_dirs : [
         "external/aac/libSBRdec/src",
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
index e750829..8494e2c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/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.
@@ -20,6 +20,9 @@
 #include <nfc_api.h>
 #include <rw_int.h>
 
+#define INITIAL_VALUE 0xBE
+#define NUM_BYTES 1
+
 bool isTestInProgress = false;
 struct sigaction new_action, old_action;
 void sigabrt_handler(int signum, siginfo_t *info, void *context) {
@@ -30,9 +33,6 @@
     exit(EXIT_FAILURE);
 }
 
-#define INITIAL_VALUE 0xBE
-#define NUM_BYTES 1
-
 extern tRW_CB rw_cb;
 void rw_init(void);
 void rw_t2t_handle_rsp(uint8_t *p_data);
@@ -63,6 +63,7 @@
     p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
     p_t2t->bytes_count = NUM_BYTES;
     p_t2t->tlv_value[1] = UINT8_MAX;
+    p_t2t->p_cur_cmd_buf = (NFC_HDR *)GKI_getpoolbuf(NFC_RW_POOL_ID);
     uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
     memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
     uint8_t data[T2T_READ_DATA_LEN];
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp
index b85abba..31572ca 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9247/Android.bp
@@ -32,7 +32,10 @@
         "external/aac/libFDK/include/",
         "cts/hostsidetests/securitybulletin/securityPatch/includes/",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9308/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9308/Android.bp
index 250b45b..8834e75 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9308/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9308/Android.bp
@@ -29,7 +29,10 @@
         "external/aac/libSYS/include",
         "external/aac/libAACdec/include",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9357/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9357/Android.bp
index 9a7a370..56804eb 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9357/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9357/Android.bp
@@ -30,7 +30,10 @@
         "external/aac/libAACdec/src",
         "external/aac/libSYS/include",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9362/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9362/Android.bp
index 1cb71e3..30507a9 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2019-9362/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-9362/Android.bp
@@ -25,8 +25,11 @@
     srcs: [
         "poc.cpp",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
     include_dirs: [
         "external/aac/libSACdec/src",
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp
index 69ce4b1..cd1a59f 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0451/Android.bp
@@ -37,7 +37,10 @@
         "external/aac/libDRCdec/include",
         "external/aac/libSBRdec/src",
     ],
+    static_libs: [
+        "libFraunhoferAAC",
+    ],
     shared_libs: [
-        "libbluetooth",
+        "liblog",
     ],
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/Android.bp
new file mode 100644
index 0000000..0c8ffff
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/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"],
+}
+
+cc_test {
+    name: "CVE-2021-39665",
+    defaults: [
+        "cts_hostsidetests_securitybulletin_defaults",
+    ],
+    srcs: [
+        "poc.cpp",
+    ],
+    shared_libs: [
+        "libutils",
+        "libmediaplayerservice",
+        "libstagefright_foundation",
+    ],
+    include_dirs: [
+        "frameworks/av/media/libstagefright/rtsp/include/media/stagefright/rtsp",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
new file mode 100644
index 0000000..4571a6d
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39665/poc.cpp
@@ -0,0 +1,85 @@
+/**
+ * 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.
+ */
+
+#include <dlfcn.h>
+
+#include "../includes/common.h"
+
+#define private public
+#include "AAVCAssembler.h"
+
+using namespace android;
+
+bool isOverloadingEnabled = false;
+
+bool isTestInProgress = false;
+
+struct sigaction newAction, oldAction;
+
+static void *(*realMalloc)(size_t) = nullptr;
+
+void *malloc(size_t size) {
+    if (!realMalloc) {
+        realMalloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
+        if (!realMalloc) {
+            return nullptr;
+        }
+    }
+    if (isOverloadingEnabled && (size == 0)) {
+        size_t pageSize = sysconf(_SC_PAGE_SIZE);
+        void *ptr = memalign(pageSize, pageSize);
+        mprotect(ptr, pageSize, PROT_NONE);
+        return ptr;
+    }
+    return realMalloc(size);
+}
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+    if (isTestInProgress && info->si_signo == SIGSEGV) {
+        (*oldAction.sa_sigaction)(signum, info, context);
+        return;
+    }
+    _exit(EXIT_FAILURE);
+}
+
+int main() {
+    sigemptyset(&newAction.sa_mask);
+    newAction.sa_flags = SA_SIGINFO;
+    newAction.sa_sigaction = sigsegv_handler;
+    sigaction(SIGSEGV, &newAction, &oldAction);
+
+    sp<ABuffer> buffer(new ABuffer(16));
+    FAIL_CHECK(buffer != nullptr);
+
+    sp<AMessage> meta = buffer->meta();
+    FAIL_CHECK(meta != nullptr);
+
+    uint32_t rtpTime = 16;
+    meta->setInt32("rtp-time", rtpTime);
+
+    AAVCAssembler *assembler = new AAVCAssembler(meta);
+    FAIL_CHECK(assembler != nullptr);
+
+    isOverloadingEnabled = true;
+    sp<ABuffer> zeroSizedBuffer(new ABuffer(0));
+    isOverloadingEnabled = false;
+
+    isTestInProgress = true;
+    assembler->checkSpsUpdated(zeroSizedBuffer);
+    isTestInProgress = false;
+
+    return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index c9c1d61..a4d088d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.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.
@@ -14,22 +14,28 @@
  * limitations under the License.
  */
 
+
 package android.security.cts;
 
 import android.platform.test.annotations.AsbSecurityTest;
 
 import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.regex.Pattern;
+
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class CVE_2018_9558 extends SecurityTestCase {
 
     /**
      * b/112161557
      * Vulnerability Behaviour: SIGABRT in self
+     * Vulnerable Library: libnfc-nci (As per AOSP code)
+     * Vulnerable Function: rw_t2t_handle_tlv_detect_rsp (As per AOSP code)
      */
     @Test
     @AsbSecurityTest(cveBugId = 112161557)
@@ -37,11 +43,15 @@
         AdbUtils.assumeHasNfc(getDevice());
         assumeIsSupportedNfcDevice(getDevice());
         pocPusher.only64();
-        String binaryName = "CVE-2018-9558";
         String[] signals = {CrashUtils.SIGABRT};
+        String binaryName = "CVE-2018-9558";
         AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
-        testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
-        testConfig.config.setSignals(CrashUtils.SIGABRT);
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+                .setBacktraceIncludes(new BacktraceFilterPattern("libnfc-nci",
+                        "rw_t2t_handle_tlv_detect_rsp"));
+        testConfig.config
+                .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+        testConfig.config.setSignals(signals);
         AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
     }
 }
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
new file mode 100644
index 0000000..311b5ce
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39665.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39665 extends SecurityTestCase {
+
+    /**
+     * b/204077881
+     * Vulnerability Behavior: SIGSEGV in self
+     * Vulnerable Library: libmediaplayerservice (As per AOSP code)
+     * Vulnerable Function: android::AAVCAssembler::checkSpsUpdated (As per AOSP code)
+     */
+    @AsbSecurityTest(cveBugId = 204077881)
+    @Test
+    public void testPocCVE_2021_39665() throws Exception {
+        String[] signals = {CrashUtils.SIGSEGV};
+        String binaryName = "CVE-2021-39665";
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+        testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+                .setBacktraceIncludes(new BacktraceFilterPattern("libmediaplayerservice",
+                        "android::AAVCAssembler::checkSpsUpdated"));
+        testConfig.config.setSignals(signals);
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+}
diff --git a/hostsidetests/systemui/Android.bp b/hostsidetests/systemui/Android.bp
index 6fd9c8c..a5918f4 100644
--- a/hostsidetests/systemui/Android.bp
+++ b/hostsidetests/systemui/Android.bp
@@ -30,6 +30,7 @@
     static_libs: [
         "cts-statsd-atom-host-test-utils",
         "platformprotos",
+        "CompatChangeGatingTestBase",
     ],
     // Tag this module as a cts test artifact
     test_suites: [
diff --git a/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java b/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
index f8fe6c0..02b403a 100644
--- a/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
+++ b/hostsidetests/systemui/app/src/android/systemui/cts/TestActiveTileService.java
@@ -22,6 +22,9 @@
 
 public class TestActiveTileService extends TestTileService {
 
+    private static final String EXTRA_BAD_PACKAGE = "android.systemui.cts.EXTRA_BAD_PACKAGE";
+    private static final String TAG = "TestActiveTileService";
+
     @Override
     public void onTileAdded() {
         Log.i(TAG, TEST_PREFIX + "onTileAdded");
@@ -32,7 +35,18 @@
         public void onReceive(Context context, Intent intent) {
             Log.i(TestActiveTileService.class.getSimpleName(),
                     TEST_PREFIX + "requestListeningState");
-            requestListeningState(context, new ComponentName(context, TestActiveTileService.class));
+            ComponentName componentName;
+            boolean useBadPackage = intent.getBooleanExtra(EXTRA_BAD_PACKAGE, false);
+            if (useBadPackage) {
+                componentName = ComponentName.unflattenFromString("pkg/.cls");
+            } else {
+                componentName = new ComponentName(context, TestActiveTileService.class);
+            }
+            try {
+                requestListeningState(context, componentName);
+            } catch (SecurityException e) {
+                Log.i(TAG, TEST_PREFIX + "SecurityException");
+            }
         }
     }
 }
diff --git a/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java b/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java
new file mode 100644
index 0000000..d861e40
--- /dev/null
+++ b/hostsidetests/systemui/src/android/host/systemui/ActiveTileServiceCompatChangeTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.host.systemui;
+
+import android.compat.cts.CompatChangeGatingTestCase;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.util.Set;
+
+public class ActiveTileServiceCompatChangeTest extends CompatChangeGatingTestCase {
+
+    // Constants for generating commands below.
+    private static final String PACKAGE = "android.systemui.cts";
+
+    // Commands used on the device.
+    private static final String ADD_TILE = "cmd statusbar add-tile ";
+    private static final String REM_TILE = "cmd statusbar remove-tile ";
+
+    public static final String REQUEST_SUPPORTED = "cmd statusbar check-support";
+    public static final String TEST_PREFIX = "TileTest_";
+
+    // Time between checks for logs we expect.
+    private static final long CHECK_DELAY = 500;
+    // Number of times to check before failing.
+    private static final long CHECK_RETRIES = 30;
+
+    private final String mService = "TestActiveTileService";
+    private final String mComponent = PACKAGE + "/." + mService;
+
+    private static final long REQUEST_LISTENING_MUST_MATCH_PACKAGE = 172251878L;
+
+    private static final String EXTRA_BAD_PACKAGE = "android.systemui.cts.EXTRA_BAD_PACKAGE";
+    private static final String ACTION_REQUEST_LISTENING =
+            "android.sysui.testtile.REQUEST_LISTENING";
+
+    private static final String REQUEST_LISTENING = "am broadcast -a " + ACTION_REQUEST_LISTENING
+            + " " + PACKAGE;
+
+    private static final String REQUEST_LISTENING_BAD =
+            REQUEST_LISTENING + " -ez " + EXTRA_BAD_PACKAGE + " true";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        clearLogcat();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        if (!supported()) return;
+        remTile();
+        // Try to wait for a onTileRemoved.
+        waitFor("onTileRemoved");
+    }
+
+    public void testRequestListening_changeEnabled() throws Exception {
+        runTest(true);
+    }
+
+    public void testRequestListening_changeDisabled() throws Exception {
+        runTest(false);
+    }
+
+    public void testRequestListeningBadPackage_changeEnabled_SecurityException() throws Exception {
+        if (!supported()) return;
+        Set<Long> enabledSet = Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE);
+        Set<Long> disabledSet = Set.of();
+
+        setCompatConfig(enabledSet, disabledSet, PACKAGE);
+
+        addTile();
+        assertTrue(waitFor("onDestroy"));
+
+        // Request the listening state but use a bad component name (not in the same package)
+        getDevice().executeShellCommand(REQUEST_LISTENING_BAD);
+        assertTrue(waitFor("SecurityException"));
+    }
+
+    private void runTest(boolean enabled) throws Exception {
+        if (!supported()) return;
+        Set<Long> enabledSet = enabled ? Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE) : Set.of();
+        Set<Long> disabledSet = enabled ? Set.of() : Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE);
+
+        setCompatConfig(enabledSet, disabledSet, PACKAGE);
+
+        final long configId = getClass().getCanonicalName().hashCode();
+        createAndUploadStatsdConfig(configId, PACKAGE);
+
+        try {
+            executeRequestListeningTest();
+        } finally {
+            resetCompatChanges(Set.of(REQUEST_LISTENING_MUST_MATCH_PACKAGE), PACKAGE);
+            validatePostRunStatsdReport(configId, PACKAGE, enabledSet, disabledSet);
+        }
+    }
+
+    private void executeRequestListeningTest() throws Exception {
+        addTile();
+        assertTrue(waitFor("onDestroy"));
+
+        // Request the listening state and verify that it gets an onStartListening.
+        getDevice().executeShellCommand(REQUEST_LISTENING);
+        assertTrue(waitFor("requestListeningState"));
+        assertTrue(waitFor("onStartListening"));
+    }
+
+    private void addTile() throws Exception {
+        execute(ADD_TILE + mComponent);
+    }
+
+    private void remTile() throws Exception {
+        execute(REM_TILE + mComponent);
+    }
+
+    private void execute(String cmd) throws Exception {
+        getDevice().executeShellCommand(cmd);
+        // All of the status bar commands tend to have animations associated
+        // everything seems to be happier if you give them time to finish.
+        Thread.sleep(100);
+    }
+
+    protected boolean waitFor(String str) throws DeviceNotAvailableException, InterruptedException {
+        final String searchStr = TEST_PREFIX + str;
+        int ct = 0;
+        while (!hasLog(searchStr) && (ct++ < CHECK_RETRIES)) {
+            Thread.sleep(CHECK_DELAY);
+        }
+        return hasLog(searchStr);
+    }
+
+    protected boolean hasLog(String str) throws DeviceNotAvailableException {
+        String logs = getDevice().executeAdbCommand("logcat", "-v", "brief", "-d", mService + ":I",
+                "*:S");
+        return logs.contains(str);
+    }
+
+    private void clearLogcat() throws DeviceNotAvailableException {
+        getDevice().executeAdbCommand("logcat", "-c");
+    }
+
+    protected boolean supported() throws DeviceNotAvailableException {
+        return supportedHardware() && supportedSoftware();
+    }
+
+    private boolean supportedSoftware() throws DeviceNotAvailableException {
+        String supported = getDevice().executeShellCommand(REQUEST_SUPPORTED);
+        return Boolean.parseBoolean(supported);
+    }
+
+    private boolean supportedHardware() throws DeviceNotAvailableException {
+        String features = getDevice().executeShellCommand("pm list features");
+        return !features.contains("android.hardware.type.television")
+                && !features.contains("android.hardware.type.watch");
+    }
+}
diff --git a/tests/PhotoPicker/AndroidTest.xml b/tests/PhotoPicker/AndroidTest.xml
index d0bf797..c52543e 100644
--- a/tests/PhotoPicker/AndroidTest.xml
+++ b/tests/PhotoPicker/AndroidTest.xml
@@ -20,7 +20,7 @@
         <option name="test-file-name" value="CtsPhotoPickerTest.apk" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
-        <option name="force-root" value="true" />
+        <option name="force-root" value="false" />
     </target_preparer>
 
     <option
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index a8f9132..aa0c954 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -52,7 +52,6 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -66,7 +65,6 @@
  * Photo Picker Device only tests for common flows.
  */
 @RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = 31, codeName = "S")
 public class CloudPhotoPickerTest extends PhotoPickerBaseTest {
     private final List<Uri> mUriList = new ArrayList<>();
     private MediaGenerator mCloudPrimaryMediaGenerator;
@@ -242,7 +240,7 @@
     }
 
     @Test
-    public void testUriAccess() throws Exception {
+    public void testUriAccessWithValidProjection() throws Exception {
         initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
 
         final ClipData clipData = fetchPickerMedia(1);
@@ -276,9 +274,29 @@
         assertRedactedReadOnlyAccess(clipData.getItemAt(0).getUri());
     }
 
-    @Ignore("b/215187981: For some reason, it hits a timeout and crashes the other tests on cf")
+    @Test
+    public void testUriAccessWithInvalidProjection() throws Exception {
+        initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
+
+        final ClipData clipData = fetchPickerMedia(1);
+        final List<String> mediaIds = extractMediaIds(clipData, 1);
+
+        assertThat(mediaIds).containsExactly(CLOUD_ID1);
+
+        final ContentResolver resolver = mContext.getContentResolver();
+
+        assertThrows(IllegalArgumentException.class, () -> resolver.query(
+                        clipData.getItemAt(0).getUri(),
+                        new String[] {MediaStore.MediaColumns.RELATIVE_PATH}, null, null));
+    }
+
     @Test
     public void testCloudEventNotification() throws Exception {
+        // Create a placeholder local image to ensure that the picker UI is never empty.
+        // The PhotoPickerUiUtils#findItemList needs to select an item and it times out if the
+        // Picker UI is empty.
+        createImages(1, mContext.getUserId(), mUriList);
+
         // Cloud provider isn't set
         assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
                         CloudProviderPrimary.AUTHORITY)).isFalse();
@@ -349,8 +367,7 @@
 
     private ClipData fetchPickerMedia(int maxCount) throws Exception {
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
         final List<UiObject> itemList = findItemList(maxCount);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index 67623ac..12bd8ae 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -16,17 +16,13 @@
 
 package android.photopicker.cts;
 
-import android.Manifest;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
-import android.provider.DeviceConfig;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.uiautomator.UiDevice;
 
-import com.android.modules.utils.build.SdkLevel;
-
 import org.junit.Before;
 
 /**
@@ -45,8 +41,6 @@
         final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
         mDevice = UiDevice.getInstance(inst);
 
-        enablePhotoPickerFlag(inst);
-
         final String setSyncDelayCommand =
                 "setprop  persist.sys.photopicker.pickerdb.default_sync_delay_ms 0";
         mDevice.executeShellCommand(setSyncDelayCommand);
@@ -65,18 +59,4 @@
         mActivity.clearResult();
         mDevice.waitForIdle();
     }
-
-    private void enablePhotoPickerFlag(Instrumentation inst) throws Exception {
-        if (SdkLevel.isAtLeastS()) {
-            inst.getUiAutomation().adoptShellPermissionIdentity(
-                    Manifest.permission.WRITE_DEVICE_CONFIG);
-            DeviceConfig.setProperty(
-                    DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
-                    "picker_intent_enabled" /* name */,
-                    "true" /* value */,
-                    false /* makeDefault */);
-        } else {
-            mDevice.executeShellCommand("setprop persist.sys.storage_picker_enabled true");
-        }
-    }
 }
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index fcef908..1092406 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -136,8 +136,7 @@
 
     private void assertBlockedByAdmin(boolean isInvokedFromWorkProfile) throws Exception {
         Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
         // Click the profile button to change to work profile
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index b9f8f33..7ad44e1 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -17,6 +17,7 @@
 package android.photopicker.cts;
 
 import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertMimeType;
+import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPersistedGrant;
 import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
 import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
 import static android.photopicker.cts.util.PhotoPickerFilesUtils.createDNGVideos;
@@ -44,7 +45,6 @@
 import androidx.test.uiautomator.UiSelector;
 
 import org.junit.After;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -83,10 +83,66 @@
 
         final Uri uri = mActivity.getResult().data.getData();
         assertPickerUriFormat(uri, mContext.getUserId());
+        assertPersistedGrant(uri, mContext.getContentResolver());
         assertRedactedReadOnlyAccess(uri);
     }
 
     @Test
+    public void testSingleSelectForFavoritesAlbum() throws Exception {
+        final int itemCount = 1;
+        createImages(itemCount, mContext.getUserId(), mUriList, true);
+
+        final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+        mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+        UiObject albumsTab = mDevice.findObject(new UiSelector().text(
+                "Albums"));
+        clickAndWait(albumsTab);
+        final UiObject album = findItemList(1).get(0);
+        clickAndWait(album);
+
+        final UiObject item = findItemList(itemCount).get(0);
+        clickAndWait(item);
+
+        final Uri uri = mActivity.getResult().data.getData();
+        assertPickerUriFormat(uri, mContext.getUserId());
+        assertRedactedReadOnlyAccess(uri);
+    }
+
+    @Test
+    public void testLaunchPreviewMultipleForVideoAlbum() throws Exception {
+        final int videoCount = 2;
+        createVideos(videoCount, mContext.getUserId(), mUriList);
+
+        final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+        intent.setType("video/*");
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+        mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+        UiObject albumsTab = mDevice.findObject(new UiSelector().text(
+                "Albums"));
+        clickAndWait(albumsTab);
+        final UiObject album = findItemList(1).get(0);
+        clickAndWait(album);
+
+        final List<UiObject> itemList = findItemList(videoCount);
+        final int itemCount = itemList.size();
+
+        assertThat(itemCount).isEqualTo(videoCount);
+
+        for (int i = 0; i < itemCount; i++) {
+            clickAndWait(itemList.get(i));
+        }
+
+        clickAndWait(findViewSelectedButton());
+
+        // Wait for playback to start. This is needed in some devices where playback
+        // buffering -> ready state takes around 10s.
+        final long playbackStartTimeout = 10000;
+        (findPreviewVideoImageView()).waitUntilGone(playbackStartTimeout);
+    }
+
+    @Test
     public void testSingleSelectWithPreview() throws Exception {
         final int itemCount = 1;
         createImages(itemCount, mContext.getUserId(), mUriList);
@@ -110,8 +166,7 @@
     @Test
     public void testMultiSelect_invalidParam() throws Exception {
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 101 with MediaStore.getPickImagesMaxLimit() + 1
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 101);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1);
         mActivity.startActivityForResult(intent, REQUEST_CODE);
         final GetResultActivity.Result res = mActivity.getResult();
         assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
@@ -174,6 +229,7 @@
 
         final Uri uri = mActivity.getResult().data.getData();
         assertPickerUriFormat(uri, mContext.getUserId());
+        assertPersistedGrant(uri, mContext.getContentResolver());
         assertRedactedReadOnlyAccess(uri);
     }
 
@@ -182,8 +238,7 @@
         final int imageCount = 4;
         createImages(imageCount, mContext.getUserId(), mUriList);
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
         final List<UiObject> itemList = findItemList(imageCount);
@@ -201,6 +256,7 @@
         for (int i = 0; i < count; i++) {
             final Uri uri = clipData.getItemAt(i).getUri();
             assertPickerUriFormat(uri, mContext.getUserId());
+            assertPersistedGrant(uri, mContext.getContentResolver());
             assertRedactedReadOnlyAccess(uri);
         }
     }
@@ -210,8 +266,7 @@
         final int videoCount = 3;
         createDNGVideos(videoCount, mContext.getUserId(), mUriList);
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         intent.setType("video/*");
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
@@ -248,6 +303,7 @@
         for (int i = 0; i < count; i++) {
             final Uri uri = clipData.getItemAt(i).getUri();
             assertPickerUriFormat(uri, mContext.getUserId());
+            assertPersistedGrant(uri, mContext.getContentResolver());
             assertRedactedReadOnlyAccess(uri);
         }
     }
@@ -257,8 +313,7 @@
         final int imageCount = 4;
         createImages(imageCount, mContext.getUserId(), mUriList);
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
         final List<UiObject> itemList = findItemList(imageCount);
@@ -287,39 +342,31 @@
         for (int i = 0; i < count; i++) {
             final Uri uri = clipData.getItemAt(i).getUri();
             assertPickerUriFormat(uri, mContext.getUserId());
+            assertPersistedGrant(uri, mContext.getContentResolver());
             assertRedactedReadOnlyAccess(uri);
         }
     }
 
     @Test
-    @Ignore("Re-enable once b/218794887 is fixed")
-    public void testMultiSelect_PreviewVideoPlayPause() throws Exception {
-        launchPreviewMultipleWithVideos(/* videoCount */ 4);
+    public void testMultiSelect_previewVideoPlayPause() throws Exception {
+        launchPreviewMultipleWithVideos(/* videoCount */ 3);
 
         // Check Play/Pause in first video
         testVideoPreviewPlayPause();
 
-        // Move to second video
+        // Move to third video
         swipeLeftAndWait();
-        // Check Play/Pause in second video
+        swipeLeftAndWait();
+        // Check Play/Pause in third video
         testVideoPreviewPlayPause();
 
-        // Move to fourth video
-        swipeLeftAndWait();
-        swipeLeftAndWait();
-        // Check Play/Pause in fourth video
-        testVideoPreviewPlayPause();
-
-        final UiObject addButton = findPreviewAddButton();
-        addButton.click();
         // We don't test the result of the picker here because the intention of the test is only to
         // test the video controls
     }
 
     @Test
-    @Ignore("Re-enable once b/218794887 is fixed")
-    public void testMultiSelect_PreviewVideoMuteButton() throws Exception {
-        launchPreviewMultipleWithVideos(/* videoCount */ 4);
+    public void testMultiSelect_previewVideoMuteButtonInitial() throws Exception {
+        launchPreviewMultipleWithVideos(/* videoCount */ 1);
 
         final UiObject playPauseButton = findPlayPauseButton();
         final UiObject muteButton = findMuteButton();
@@ -340,8 +387,42 @@
         // Click on the muteButton and check that mute button status is now `selected`
         clickAndWait(muteButton);
         assertThat(muteButton.isSelected()).isTrue();
+        // Click on the muteButton and check that mute button status is now `not selected`
+        clickAndWait(muteButton);
+        assertThat(muteButton.isSelected()).isFalse();
 
-        // Test 3: Swipe resumes mute state, with state of mute button = `not selected`
+        // Test 3: Next preview resumes mute state
+        // Go back and launch preview again
+        mDevice.pressBack();
+        clickAndWait(findViewSelectedButton());
+        // set-up and wait for player controls to be sticky
+        setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+        assertThat(muteButton.isSelected()).isFalse();
+
+        // We don't test the result of the picker here because the intention of the test is only to
+        // test the video controls
+    }
+
+    @Test
+    public void testMultiSelect_previewVideoMuteButtonOnSwipe() throws Exception {
+        launchPreviewMultipleWithVideos(/* videoCount */ 3);
+
+        final UiObject playPauseButton = findPlayPauseButton();
+        final UiObject muteButton = findMuteButton();
+        final UiObject playerView = findPlayerView();
+
+        // set-up and wait for player controls to be sticky
+        setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+
+        // Test 1: Swipe resumes mute state, with state of the button = `selected`
+        assertThat(muteButton.isSelected()).isTrue();
+        // Swipe to next page and check that muteButton is selected
+        swipeLeftAndWait();
+        // set-up and wait for player controls to be sticky
+        setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
+        assertThat(muteButton.isSelected()).isTrue();
+
+        // Test 2: Swipe resumes mute state, with state of mute button = `not selected`
         // Click muteButton again to check the next video resumes the previous video's mute state
         clickAndWait(muteButton);
         assertThat(muteButton.isSelected()).isFalse();
@@ -351,44 +432,18 @@
         setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
         assertThat(muteButton.isSelected()).isFalse();
 
-        // Test 4: Swipe resumes mute state, with state of the button = `selected`
-        // Click muteButton again to check the next video resumes the previous video's mute state
-        clickAndWait(muteButton);
-        assertThat(muteButton.isSelected()).isTrue();
-        // Swipe to next page and check that muteButton is selected
-        swipeLeftAndWait();
-        // set-up and wait for player controls to be sticky
-        setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
-        assertThat(muteButton.isSelected()).isTrue();
-
-        // Test 5: Next preview resumes mute state
-        // Click muteButton again to check if next Preview launch resumes the muteButton state
-        clickAndWait(muteButton);
-        assertThat(muteButton.isSelected()).isFalse();
-        // Go back and launch preview again
-        mDevice.pressBack();
-        // set-up and wait for player controls to be sticky
-        clickAndWait(findViewSelectedButton());
-        setUpAndAssertStickyPlayerControls(playerView, playPauseButton, muteButton);
-        assertThat(muteButton.isSelected()).isFalse();
-
-        clickAndWait(findPreviewAddButton());
         // We don't test the result of the picker here because the intention of the test is only to
         // test the video controls
     }
 
     @Test
-    @Ignore("Re-enable once b/218794887 is fixed")
-    public void testMultiSelect_PreviewVideoControlsVisibility() throws Exception {
+    public void testMultiSelect_previewVideoControlsVisibility() throws Exception {
         launchPreviewMultipleWithVideos(/* videoCount */ 3);
 
         mDevice.waitForIdle();
 
         final UiObject playPauseButton = findPlayPauseButton();
         final UiObject muteButton = findMuteButton();
-        // Check that the player controls are visible
-        assertPlayerControlsVisible(playPauseButton, muteButton);
-
         // Check that buttons auto hide.
         assertPlayerControlsAutoHide(playPauseButton, muteButton);
 
@@ -421,8 +476,6 @@
         // Check that the player controls are auto hidden in 1s
         assertPlayerControlsAutoHide(playPauseButton, muteButton);
 
-        final UiObject addButton = findPreviewAddButton();
-        addButton.click();
         // We don't test the result of the picker here because the intention of the test is only to
         // test the video controls
     }
@@ -437,8 +490,7 @@
         final String mimeType = "video/dng";
 
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         intent.setType(mimeType);
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
@@ -458,6 +510,7 @@
         for (int i = 0; i < count; i++) {
             final Uri uri = clipData.getItemAt(i).getUri();
             assertPickerUriFormat(uri, mContext.getUserId());
+            assertPersistedGrant(uri, mContext.getContentResolver());
             assertRedactedReadOnlyAccess(uri);
             assertMimeType(uri, mimeType);
         }
@@ -488,8 +541,7 @@
     private void launchPreviewMultipleWithVideos(int videoCount) throws  Exception {
         createVideos(videoCount, mContext.getUserId(), mUriList);
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         intent.setType("video/*");
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
@@ -512,8 +564,8 @@
 
     private void setUpAndAssertStickyPlayerControls(UiObject playerView, UiObject playPauseButton,
             UiObject muteButton) throws Exception {
-        // Check that buttons auto hide.
-        assertPlayerControlsAutoHide(playPauseButton, muteButton);
+        // Wait for 1s or Play/Pause button to hide
+        playPauseButton.waitUntilGone(1000);
         // Click on StyledPlayerView to make the video controls visible
         clickAndWait(playerView);
         assertPlayerControlsVisible(playPauseButton, muteButton);
@@ -590,7 +642,7 @@
     private void swipeLeftAndWait() {
         final int width = mDevice.getDisplayWidth();
         final int height = mDevice.getDisplayHeight();
-        mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 20);
+        mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 10);
         mDevice.waitForIdle();
     }
 }
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index a4ec998..22d6a9d 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -48,6 +48,7 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
@@ -112,6 +113,7 @@
     }
 
     @Test
+    @Ignore("Re-enable once b/223224727 is fixed")
     public void testBasicVideoPreview() throws Exception {
         initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
 
@@ -144,6 +146,7 @@
     }
 
     @Test
+    @Ignore("Re-enable once b/223224727 is fixed")
     public void testSwipeAdjacentVideoPreview() throws Exception {
         initCloudProviderWithVideo(
                 Arrays.asList(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2)));
@@ -179,6 +182,7 @@
     }
 
     @Test
+    @Ignore("Re-enable once b/223224727 is fixed")
     public void testSwipeImageVideoPreview() throws Exception {
         initCloudProviderWithImage(Arrays.asList(Pair.create(null, CLOUD_ID1)));
         initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID2)));
@@ -299,8 +303,7 @@
 
     private void launchPreviewMultiple(int count) throws Exception {
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
-        // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
-        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
         final List<UiObject> itemList = findItemList(count);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
index a9894a9..9eb7d59 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
@@ -16,8 +16,6 @@
 
 package android.photopicker.cts.util;
 
-import static android.os.SystemProperties.getBoolean;
-import static android.provider.MediaStore.Files.FileColumns;
 import static android.provider.MediaStore.PickerMediaColumns;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -27,6 +25,8 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.UriPermission;
 import android.database.Cursor;
 import android.media.ExifInterface;
 import android.net.Uri;
@@ -41,7 +41,9 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Photo Picker Utility methods for test assertions.
@@ -58,6 +60,20 @@
         assertThat(auth).isEqualTo("picker");
     }
 
+    public static void assertPersistedGrant(Uri uri, ContentResolver resolver) {
+        resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
+        final List<Uri> uris = new ArrayList<>();
+        for (UriPermission perm : uriPermissions) {
+            if (perm.isReadPermission()) {
+                uris.add(perm.getUri());
+            }
+        }
+
+        assertThat(uris).contains(uri);
+    }
+
     public static void assertMimeType(Uri uri, String expectedMimeType) throws Exception {
         final Context context = InstrumentationRegistry.getTargetContext();
         final String resultMimeType = context.getContentResolver().getType(uri);
@@ -73,12 +89,7 @@
             assertThat(c).isNotNull();
             assertThat(c.moveToFirst()).isTrue();
 
-            final String mimeType;
-            if (getBoolean("sys.photopicker.pickerdb.enabled", true)) {
-                mimeType = c.getString(c.getColumnIndex(PickerMediaColumns.MIME_TYPE));
-            } else {
-                mimeType = c.getString(c.getColumnIndex(FileColumns.MIME_TYPE));
-            }
+            final String mimeType = c.getString(c.getColumnIndex(PickerMediaColumns.MIME_TYPE));
 
             if (mimeType.startsWith("image")) {
                 assertImageRedactedReadOnlyAccess(uri, resolver);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
index 87be764..3705ddd 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
@@ -44,8 +44,13 @@
 
     public static void createImages(int count, int userId, List<Uri> uriList)
             throws Exception {
+        createImages(count, userId, uriList, false);
+    }
+
+    public static void createImages(int count, int userId, List<Uri> uriList, boolean isFavorite)
+            throws Exception {
         for (int i = 0; i < count; i++) {
-            final Uri uri = createImage(userId);
+            final Uri uri = createImage(userId, isFavorite);
             uriList.add(uri);
             clearMediaOwner(uri, userId);
         }
@@ -101,13 +106,14 @@
         return uri;
     }
 
-    private static Uri createImage(int userId) throws Exception {
+    private static Uri createImage(int userId, boolean isFavorite) throws Exception {
         final Uri uri = stageMedia(R.raw.lg_g4_iso_800_jpg,
-                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId);
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId, isFavorite);
         return uri;
     }
 
-    private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId) throws
+    private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId,
+            boolean isFavorite) throws
             Exception {
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         uiAutomation.adoptShellPermissionIdentity(
@@ -118,17 +124,24 @@
             final Context userContext = userId == context.getUserId() ? context :
                     context.createPackageContextAsUser("android", /* flags= */ 0,
                             UserHandle.of(userId));
-            return stageMedia(resId, collectionUri, mimeType, userContext);
+            return stageMedia(resId, collectionUri, mimeType, userContext, isFavorite);
         } finally {
             uiAutomation.dropShellPermissionIdentity();
         }
     }
 
-    private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, Context context)
+    private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, int userId) throws
+            Exception {
+        return stageMedia(resId, collectionUri, mimeType, userId, false);
+    }
+
+    private static Uri stageMedia(int resId, Uri collectionUri, String mimeType, Context context,
+            boolean isFavorite)
             throws IOException {
         final String displayName = DISPLAY_NAME_PREFIX + System.nanoTime();
         final MediaStoreUtils.PendingParams params = new MediaStoreUtils.PendingParams(
                 collectionUri, displayName, mimeType);
+        params.setIsFavorite(isFavorite);
         final Uri pendingUri = MediaStoreUtils.createPending(context, params);
         try (MediaStoreUtils.PendingSession session = MediaStoreUtils.openPending(context,
                 pendingUri)) {
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 1a359dd..0f5afd1 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -109,12 +109,14 @@
 
     @Rule
     public final RuleChain mRuleChain = RuleChain
-            .outerRule(mSpeakingAndVibratingAccessibilityServiceRule)
+            // SettingsStateChangerRule will suppress accessibility services, so it should be
+            // executed before enabling a11y services and after disabling a11y services.
+            .outerRule(mAudioDescriptionSetterRule)
+            .around(mSpeakingAndVibratingAccessibilityServiceRule)
             .around(mVibratingAccessibilityServiceRule)
             .around(mSpeakingAccessibilityServiceRule)
             // Inner rule capture failure and dump data before finishing activity and a11y service
-            .around(mDumpOnFailureRule)
-            .around(mAudioDescriptionSetterRule);
+            .around(mDumpOnFailureRule);
 
     private AccessibilityManager mAccessibilityManager;
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
index 715c040..1ef0724 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -420,14 +420,22 @@
                 .setMode(MAGNIFICATION_MODE_WINDOW)
                 .setScale(2.0f)
                 .build();
-        mService.runOnServiceSync(
-                () -> controller.setMagnificationConfig(config, /* animate= */ false));
 
-        sUiAutomation.executeAndWaitForEvent(
-                () -> mService.runOnServiceSync(() -> mService.disableSelfAndRemove()),
-                event -> sUiAutomation.getWindows().stream().noneMatch(
-                        accessibilityWindowInfo -> accessibilityWindowInfo.getType()
-                                == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);
+        try {
+            sUiAutomation.executeAndWaitForEvent(
+                    () -> controller.setMagnificationConfig(config, false),
+                    event -> sUiAutomation.getWindows().stream().anyMatch(
+                            accessibilityWindowInfo -> accessibilityWindowInfo.getType()
+                                    == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);
+
+            sUiAutomation.executeAndWaitForEvent(
+                    () -> mService.runOnServiceSync(() -> mService.disableSelfAndRemove()),
+                    event -> sUiAutomation.getWindows().stream().noneMatch(
+                            accessibilityWindowInfo -> accessibilityWindowInfo.getType()
+                                    == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);
+        } finally {
+            controller.resetCurrentMagnification(false);
+        }
     }
 
     @Test
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index 3530c6a..f34bcd6 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -31,7 +31,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.os.Process;
@@ -697,32 +696,6 @@
         }
     }
 
-    public void testSetUninstallBlocked_failIfNotProfileOwner() {
-        if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testSetUninstallBlocked_failIfNotProfileOwner");
-            return;
-        }
-        try {
-            mDevicePolicyManager.setUninstallBlocked(mComponent,
-                    "android.admin.cts", true);
-            fail("did not throw expected SecurityException");
-        } catch (SecurityException e) {
-            assertProfileOwnerMessage(e.getMessage());
-        }
-    }
-
-    public void testSetUninstallBlocked_succeedForNotInstalledApps() {
-        if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testSetUninstallBlocked_succeedForNotInstalledApps");
-            return;
-        }
-        ComponentName profileOwner = DeviceAdminInfoTest.getProfileOwnerComponent();
-        mDevicePolicyManager.setUninstallBlocked(profileOwner,
-                "android.admin.not.installed", true);
-        assertFalse(mDevicePolicyManager.isUninstallBlocked(profileOwner,
-              "android.admin.not.installed"));
-    }
-
     public void testSetPermittedAccessibilityServices_failIfNotProfileOwner() {
         if (!mDeviceAdmin) {
             Log.w(TAG, "Skipping testSetPermittedAccessibilityServices_failIfNotProfileOwner");
diff --git a/tests/app/app/src/android/app/stubs/SendBubbleActivity.java b/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
index 9c29acc..0281671 100644
--- a/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
+++ b/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
@@ -16,8 +16,6 @@
 
 package android.app.stubs;
 
-import static android.app.stubs.BubbledActivity.EXTRA_LOCUS_ID;
-
 import android.app.Activity;
 import android.app.Notification;
 import android.app.Notification.BubbleMetadata;
@@ -56,23 +54,6 @@
         sendBroadcast(i);
     }
 
-    public void startBubbleActivity(int id) {
-        startBubbleActivity(id, true /* addLocusId */);
-    }
-
-    /**
-     * Starts the same activity that is in the bubble produced by this activity.
-     */
-    public void startBubbleActivity(int id, boolean addLocusId) {
-        final Intent intent = new Intent(getApplicationContext(), BubbledActivity.class);
-        // Clear any previous instance of this activity
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
-        if (addLocusId) {
-            intent.putExtra(EXTRA_LOCUS_ID, String.valueOf(id));
-        }
-        startActivity(intent);
-    }
-
     /**
      * Sends a notification that has bubble metadata but the rest of the notification isn't
      * configured correctly so the system won't allow it to bubble.
diff --git a/tests/app/app/src/android/app/stubs/TestNotificationListener.java b/tests/app/app/src/android/app/stubs/TestNotificationListener.java
index eabde5c..65ba550 100644
--- a/tests/app/app/src/android/app/stubs/TestNotificationListener.java
+++ b/tests/app/app/src/android/app/stubs/TestNotificationListener.java
@@ -34,6 +34,7 @@
     public ArrayList<StatusBarNotification> mPosted = new ArrayList<>();
     public Map<String, Integer> mRemoved = new HashMap<>();
     public RankingMap mRankingMap;
+    public Map<String, Boolean> mIntercepted = new HashMap<>();
 
     /**
      * This controls whether there is a listener connected or not. Depending on the method, if the
@@ -89,6 +90,7 @@
     public void resetData() {
         mPosted.clear();
         mRemoved.clear();
+        mIntercepted.clear();
     }
 
     public void addTestPackage(String packageName) {
@@ -103,6 +105,7 @@
     public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
         if (sbn == null || !mTestPackages.contains(sbn.getPackageName())) { return; }
         mRankingMap = rankingMap;
+        updateInterceptedRecords(rankingMap);
         mPosted.add(sbn);
     }
 
@@ -111,11 +114,26 @@
             int reason) {
         if (sbn == null || !mTestPackages.contains(sbn.getPackageName())) { return; }
         mRankingMap = rankingMap;
+        updateInterceptedRecords(rankingMap);
         mRemoved.put(sbn.getKey(), reason);
     }
 
     @Override
     public void onNotificationRankingUpdate(RankingMap rankingMap) {
         mRankingMap = rankingMap;
+        updateInterceptedRecords(rankingMap);
+    }
+
+    // update the local cache of intercepted records based on the given ranking map; should be run
+    // every time the listener gets updated ranking map info
+    private void updateInterceptedRecords(RankingMap rankingMap) {
+        for (String key : rankingMap.getOrderedKeys()) {
+            Ranking rank = new Ranking();
+            if (rankingMap.getRanking(key, rank)) {
+                // matchesInterruptionFilter is true if the notifiation can bypass and false if
+                // blocked so the "is intercepted" boolean is the opposite of that.
+                mIntercepted.put(key, !rank.matchesInterruptionFilter());
+            }
+        }
     }
 }
diff --git a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
index 82000a4..f4fda53 100644
--- a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
@@ -20,6 +20,7 @@
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
+import static android.app.stubs.BubbledActivity.EXTRA_LOCUS_ID;
 import static android.app.stubs.BubblesTestService.EXTRA_TEST_CASE;
 import static android.app.stubs.BubblesTestService.TEST_CALL;
 import static android.app.stubs.BubblesTestService.TEST_MESSAGING;
@@ -30,6 +31,7 @@
 
 import static org.junit.Assert.assertThrows;
 
+import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.Instrumentation;
 import android.app.KeyguardManager;
@@ -213,7 +215,7 @@
      * @return the SendBubbleActivity that was opened.
      */
     private SendBubbleActivity startSendBubbleActivity() {
-        final CountDownLatch latch = new CountDownLatch(2);
+        final CountDownLatch latch = new CountDownLatch(1);
         mBubbleBroadcastReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -240,14 +242,7 @@
         SendBubbleActivity sendBubbleActivity = (SendBubbleActivity) monitor.waitForActivity();
 
         // Make sure device is unlocked
-        KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
-        keyguardManager.requestDismissKeyguard(sendBubbleActivity,
-                new KeyguardManager.KeyguardDismissCallback() {
-                    @Override
-                    public void onDismissSucceeded() {
-                        latch.countDown();
-                    }
-                });
+        ensureDeviceUnlocked(sendBubbleActivity);
         try {
             latch.await(500, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
@@ -266,6 +261,53 @@
         return monitor;
     }
 
+    private BubbledActivity startBubbleActivity(int id) {
+        return startBubbleActivity(id, true /* addLocusId */);
+    }
+
+    /**
+     * Starts the same activity that is in the bubble produced by this activity.
+     */
+    private BubbledActivity startBubbleActivity(int id, boolean addLocusId) {
+        Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
+
+        final Intent intent = new Intent(mContext, BubbledActivity.class);
+        // Clear any previous instance of this activity
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+        if (addLocusId) {
+            intent.putExtra(EXTRA_LOCUS_ID, String.valueOf(id));
+        }
+
+        InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        BubbledActivity bubbledActivity = (BubbledActivity) monitor.waitForActivity();
+        ensureDeviceUnlocked(bubbledActivity);
+        return bubbledActivity;
+    }
+
+    /**
+     * Make sure device is unlocked so the activity can become visible
+     */
+    private void ensureDeviceUnlocked(Activity activity) {
+        // Make sure device is unlocked
+        KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+        if (keyguardManager.isKeyguardLocked()) {
+            CountDownLatch latch = new CountDownLatch(1);
+            keyguardManager.requestDismissKeyguard(activity,
+                    new KeyguardManager.KeyguardDismissCallback() {
+                        @Override
+                        public void onDismissSucceeded() {
+                            latch.countDown();
+                        }
+                    });
+            try {
+                latch.await(500, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException ignored) {
+            }
+        }
+    }
+
     private void cleanupSendBubbleActivity() {
         mContext.unregisterReceiver(mBubbleBroadcastReceiver);
     }
@@ -852,13 +894,8 @@
             verifyNotificationBubbleState(notifId, true /* shouldBeBubble */);
             mListener.resetData();
 
-            // Prep to find bubbled activity
-            Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
-
             // Launch same activity as whats in the bubble
-            a.startBubbleActivity(notifId);
-            BubbledActivity activity = (BubbledActivity) monitor.waitForActivity();
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+            BubbledActivity activity = startBubbleActivity(notifId);
 
             // It should have the locusId
             assertEquals(new LocusId(String.valueOf(notifId)),
@@ -900,13 +937,8 @@
             verifyNotificationBubbleState(BUBBLE_NOTIF_ID, true /* shouldBeBubble */);
             mListener.resetData();
 
-            // Prep to find bubbled activity
-            Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
-
             // Launch same activity as whats in the bubble
-            a.startBubbleActivity(BUBBLE_NOTIF_ID);
-            BubbledActivity activity = (BubbledActivity) monitor.waitForActivity();
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+            BubbledActivity activity = startBubbleActivity(BUBBLE_NOTIF_ID);
 
             // It should have the locusId
             assertEquals(new LocusId(String.valueOf(BUBBLE_NOTIF_ID)),
@@ -948,13 +980,8 @@
             verifyNotificationBubbleState(BUBBLE_NOTIF_ID, true /* shouldBeBubble */);
             mListener.resetData();
 
-            // Prep to find bubbled activity
-            Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
-
             // Launch same activity as whats in the bubble
-            a.startBubbleActivity(BUBBLE_NOTIF_ID, false /* addLocusId */);
-            BubbledActivity activity = (BubbledActivity) monitor.waitForActivity();
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+            BubbledActivity activity = startBubbleActivity(BUBBLE_NOTIF_ID, false /* addLocusId */);
 
             // It shouldn't have the locusId
             assertNull(activity.getLocusId());
@@ -997,13 +1024,8 @@
             verifyNotificationBubbleState(BUBBLE_NOTIF_ID, true /* shouldBeBubble */);
             mListener.resetData();
 
-            // Prep to find bubbled activity
-            Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
-
             // Launch same activity as whats in the bubble
-            a.startBubbleActivity(BUBBLE_NOTIF_ID, true /* addLocusId */);
-            BubbledActivity activity = (BubbledActivity) monitor.waitForActivity();
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+            BubbledActivity activity = startBubbleActivity(BUBBLE_NOTIF_ID, true /* addLocusId */);
 
             // Activity has the locus
             assertNotNull(activity.getLocusId());
@@ -1051,13 +1073,8 @@
             assertTrue(sbn.getNotification().getBubbleMetadata().isBubbleSuppressable());
             assertFalse(sbn.getNotification().getBubbleMetadata().isBubbleSuppressed());
 
-            // Prep to find bubbled activity
-            Instrumentation.ActivityMonitor monitor = startBubbledActivityMonitor();
-
             // Launch same activity as whats in the bubble
-            a.startBubbleActivity(notifId);
-            BubbledActivity activity = (BubbledActivity) monitor.waitForActivity();
-            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+            BubbledActivity activity = startBubbleActivity(notifId);
 
             // It should have the locusId
             assertEquals(new LocusId(String.valueOf(notifId)),
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index e3a86ef..cedaae9 100755
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -2625,6 +2625,76 @@
         }
     }
 
+    public void testRepeatCallers_repeatCallNotIntercepted_contactAfterPhone() throws Exception {
+        toggleListenerAccess(true);
+        Thread.sleep(500); // wait for listener to be allowed
+        mListener = TestNotificationListener.getInstance();
+        assertNotNull(mListener);
+
+        // if a call is recorded with just phone number info (not a contact's uri), which may
+        // happen when the same contact calls across multiple apps (or if the contact uri provided
+        // is otherwise inconsistent), check for the contact's phone number
+        toggleNotificationPolicyAccess(mContext.getPackageName(),
+                InstrumentationRegistry.getInstrumentation(), true);
+        int origFilter = mNotificationManager.getCurrentInterruptionFilter();
+        Policy origPolicy = mNotificationManager.getNotificationPolicy();
+        Uri aliceUri = null;
+        long startTime = System.currentTimeMillis();
+        try {
+            mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
+                    PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0));
+            // turn on manual DND
+            mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY);
+            assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY);
+
+            insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, false);
+            aliceUri = lookupContact(ALICE_PHONE);
+            Uri alicePhoneUri = makePhoneUri(ALICE_PHONE);
+
+            // no one has called; matchesCallFilter should return false for both URIs
+            assertFalse(mNotificationManager.matchesCallFilter(aliceUri));
+            assertFalse(mNotificationManager.matchesCallFilter(alicePhoneUri));
+
+            // register a call from Alice via just the phone number
+            sendNotification(1, null, R.drawable.blue, true, alicePhoneUri);
+            Thread.sleep(1000); // give the listener some time to receive info
+
+            // check that the first notification is intercepted
+            StatusBarNotification sbn = findPostedNotification(1, false);
+            assertNotNull(sbn);
+            assertTrue(mListener.mIntercepted.containsKey(sbn.getKey()));
+            assertTrue(mListener.mIntercepted.get(sbn.getKey()));  // should be intercepted
+
+            // cancel first notification
+            cancelAndPoll(1);
+
+            // now send a call with only Alice's contact Uri as the info
+            // Note that this is a test of the repeat caller check, not matchesCallFilter itself
+            sendNotification(2, null, R.drawable.blue, true, aliceUri);
+            // wait for contact lookup, which may take a while
+            Thread.sleep(3000);
+
+            // now check that the second notification is not intercepted
+            StatusBarNotification sbn2 = findPostedNotification(2, true);
+            assertTrue(mListener.mIntercepted.containsKey(sbn2.getKey()));
+            assertFalse(mListener.mIntercepted.get(sbn2.getKey()));  // should not be intercepted
+
+            // cancel second notification
+            cancelAndPoll(2);
+        } finally {
+            mNotificationManager.setInterruptionFilter(origFilter);
+            mNotificationManager.setNotificationPolicy(origPolicy);
+            if (aliceUri != null) {
+                // delete the contact
+                deleteSingleContact(aliceUri);
+            }
+
+            // clean up the recorded calls
+            SystemUtil.runWithShellPermissionIdentity(() ->
+                    mNotificationManager.cleanUpCallersAfter(startTime));
+        }
+    }
+
     public void testMatchesCallFilter_allCallers() throws Exception {
         // allow all callers
         toggleNotificationPolicyAccess(mContext.getPackageName(),
diff --git a/tests/appsearch/helper-app/src/com/android/cts/appsearch/helper/AppSearchTestService.java b/tests/appsearch/helper-app/src/com/android/cts/appsearch/helper/AppSearchTestService.java
index 0b25b55..306d8d5 100644
--- a/tests/appsearch/helper-app/src/com/android/cts/appsearch/helper/AppSearchTestService.java
+++ b/tests/appsearch/helper-app/src/com/android/cts/appsearch/helper/AppSearchTestService.java
@@ -99,7 +99,7 @@
                 String packageName, String databaseName, String namespace, String id) {
             try {
                 AppSearchBatchResult<String, GenericDocument> getResult =
-                        mGlobalSearchSessionShim.getByDocumentId(
+                        mGlobalSearchSessionShim.getByDocumentIdAsync(
                                 packageName,
                                 databaseName,
                                 new GetByDocumentIdRequest.Builder(namespace)
diff --git a/tests/appsearch/src/com/android/cts/appsearch/app/GlobalSearchSessionPlatformCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/app/GlobalSearchSessionPlatformCtsTest.java
index cd96c50..1f74690 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/app/GlobalSearchSessionPlatformCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/app/GlobalSearchSessionPlatformCtsTest.java
@@ -329,7 +329,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, "database",
+                            .getByDocumentIdAsync(PKG_A, "database",
                                     new GetByDocumentIdRequest.Builder("namespace")
                                             .addIds("id1")
                                             .build()).get();
@@ -360,7 +360,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, "database",
+                            .getByDocumentIdAsync(PKG_A, "database",
                                     new GetByDocumentIdRequest.Builder("namespace")
                                             .addIds("id1")
                                             .build()).get();
@@ -376,7 +376,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, "database",
+                            .getByDocumentIdAsync(PKG_A, "database",
                                     new GetByDocumentIdRequest.Builder("namespace")
                                             .addIds("id1")
                                             .build()).get();
@@ -392,7 +392,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, "database",
+                            .getByDocumentIdAsync(PKG_A, "database",
                                     new GetByDocumentIdRequest.Builder("namespace")
                                             .addIds("id1")
                                             .build()).get();
@@ -408,7 +408,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, "database",
+                            .getByDocumentIdAsync(PKG_A, "database",
                                     new GetByDocumentIdRequest.Builder("namespace")
                                             .addIds("id1")
                                             .build()).get();
@@ -423,7 +423,7 @@
         mGlobalSearchSession =
                 GlobalSearchSessionShimImpl.createGlobalSearchSession(mContext).get();
         AppSearchBatchResult<String, GenericDocument> nonExistentResult = mGlobalSearchSession
-                .getByDocumentId(PKG_A, "database",
+                .getByDocumentIdAsync(PKG_A, "database",
                         new GetByDocumentIdRequest.Builder("namespace")
                                 .addIds("id1")
                                 .build()).get();
@@ -439,7 +439,7 @@
         mGlobalSearchSession =
                 GlobalSearchSessionShimImpl.createGlobalSearchSession(mContext).get();
         AppSearchBatchResult<String, GenericDocument> unAuthResult = mGlobalSearchSession
-                .getByDocumentId(PKG_A, "database",
+                .getByDocumentIdAsync(PKG_A, "database",
                         new GetByDocumentIdRequest.Builder("namespace")
                                 .addIds("id1")
                                 .build()).get();
@@ -463,7 +463,7 @@
 
                     // Can get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, DB_NAME,
+                            .getByDocumentIdAsync(PKG_A, DB_NAME,
                                     new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                             .addIds("id1")
                                             .build()).get();
@@ -472,7 +472,7 @@
 
                     // Can't get non existent document
                     AppSearchBatchResult<String, GenericDocument> nonExistent = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, DB_NAME,
+                            .getByDocumentIdAsync(PKG_A, DB_NAME,
                                     new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                             .addIds("id2")
                                             .build()).get();
@@ -494,7 +494,7 @@
 
                     // Can't get the document
                     AppSearchBatchResult<String, GenericDocument> result = mGlobalSearchSession
-                            .getByDocumentId(PKG_A, DB_NAME,
+                            .getByDocumentIdAsync(PKG_A, DB_NAME,
                                     new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                             .addIds("id1")
                                             .build()).get();
@@ -517,7 +517,7 @@
                             GlobalSearchSessionShimImpl.createGlobalSearchSession(mContext).get();
 
                     AppSearchBatchResult<String, GenericDocument> nonExistentResult =
-                            mGlobalSearchSession.getByDocumentId(PKG_A, DB_NAME,
+                            mGlobalSearchSession.getByDocumentIdAsync(PKG_A, DB_NAME,
                                     new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                             .addIds("id1")
                                             .build()).get();
@@ -538,7 +538,7 @@
                             GlobalSearchSessionShimImpl.createGlobalSearchSession(mContext).get();
 
                     AppSearchBatchResult<String, GenericDocument> unAuthResult =
-                            mGlobalSearchSession.getByDocumentId(PKG_A, DB_NAME,
+                            mGlobalSearchSession.getByDocumentIdAsync(PKG_A, DB_NAME,
                                     new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                             .addIds("id1")
                                             .build()).get();
@@ -560,7 +560,7 @@
                 GlobalSearchSessionShimImpl.createGlobalSearchSession(mContext).get();
 
         AppSearchBatchResult<String, GenericDocument> noGlobalResult = mGlobalSearchSession
-                .getByDocumentId(PKG_A, DB_NAME,
+                .getByDocumentIdAsync(PKG_A, DB_NAME,
                         new GetByDocumentIdRequest.Builder(NAMESPACE_NAME)
                                 .addIds("id1")
                                 .build()).get();
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchResultCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchResultCtsTest.java
index 2691ecf..6adcfce 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchResultCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchResultCtsTest.java
@@ -23,6 +23,14 @@
 import org.junit.Test;
 
 public class AppSearchResultCtsTest {
+    @Test
+    public void testNewSuccessfulResult() {
+        AppSearchResult<String> result = AppSearchResult.newSuccessfulResult("String");
+        assertThat(result.getResultCode()).isEqualTo(AppSearchResult.RESULT_OK);
+        assertThat(result.getResultValue()).isEqualTo("String");
+        assertThat(result.isSuccess()).isTrue();
+        assertThat(result.getErrorMessage()).isNull();
+    }
 
     @Test
     public void testResultEquals_identical() {
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
index 5efc5a8..4e186a3 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java
@@ -26,12 +26,14 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.annotation.NonNull;
+import android.app.appsearch.AppSearchBatchResult;
 import android.app.appsearch.AppSearchResult;
 import android.app.appsearch.AppSearchSchema;
 import android.app.appsearch.AppSearchSchema.PropertyConfig;
 import android.app.appsearch.AppSearchSessionShim;
 import android.app.appsearch.Features;
 import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByDocumentIdRequest;
 import android.app.appsearch.GetSchemaResponse;
 import android.app.appsearch.GlobalSearchSessionShim;
 import android.app.appsearch.PutDocumentsRequest;
@@ -130,6 +132,59 @@
     }
 
     @Test
+    public void testGlobalGetById() throws Exception {
+        assumeTrue(
+                mGlobalSearchSession
+                        .getFeatures()
+                        .isFeatureSupported(Features.GLOBAL_SEARCH_SESSION_GET_BY_ID));
+        SearchSpec exactSearchSpec =
+                new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY).build();
+
+        // Schema registration
+        mDb1.setSchema(new SetSchemaRequest.Builder().addSchemas(AppSearchEmail.SCHEMA).build())
+                .get();
+
+        AppSearchBatchResult<String, GenericDocument> nonExistent =
+                mGlobalSearchSession
+                        .getByDocumentIdAsync(
+                                mContext.getPackageName(),
+                                DB_NAME_1,
+                                new GetByDocumentIdRequest.Builder("namespace")
+                                        .addIds("id1")
+                                        .build())
+                        .get();
+
+        assertThat(nonExistent.isSuccess()).isFalse();
+        assertThat(nonExistent.getSuccesses()).isEmpty();
+        assertThat(nonExistent.getFailures()).containsKey("id1");
+        assertThat(nonExistent.getFailures().get("id1").getResultCode())
+                .isEqualTo(AppSearchResult.RESULT_NOT_FOUND);
+
+        // Index a document
+        AppSearchEmail inEmail =
+                new AppSearchEmail.Builder("namespace", "id1")
+                        .setFrom("from@example.com")
+                        .setTo("to1@example.com", "to2@example.com")
+                        .setSubject("testPut example")
+                        .setBody("This is the body of the testPut email")
+                        .build();
+        checkIsBatchResultSuccess(
+                mDb1.put(new PutDocumentsRequest.Builder().addGenericDocuments(inEmail).build()));
+
+        // Query for the document
+        AppSearchBatchResult<String, GenericDocument> afterPutDocuments =
+                mGlobalSearchSession
+                        .getByDocumentIdAsync(
+                                mContext.getPackageName(),
+                                DB_NAME_1,
+                                new GetByDocumentIdRequest.Builder("namespace")
+                                        .addIds("id1")
+                                        .build())
+                        .get();
+        assertThat(afterPutDocuments.getSuccesses()).containsExactly("id1", inEmail);
+    }
+
+    @Test
     public void testGlobalQuery_oneInstance() throws Exception {
         // Snapshot what documents may already exist on the device.
         SearchSpec exactSearchSpec =
@@ -1474,6 +1529,33 @@
     }
 
     @Test
+    public void testGlobalGetByDocumentId_notSupported() throws Exception {
+        assumeFalse(
+                mGlobalSearchSession
+                        .getFeatures()
+                        .isFeatureSupported(Features.GLOBAL_SEARCH_SESSION_GET_BY_ID));
+
+        Context context = ApplicationProvider.getApplicationContext();
+
+        UnsupportedOperationException e =
+                assertThrows(
+                        UnsupportedOperationException.class,
+                        () ->
+                                mGlobalSearchSession.getByDocumentIdAsync(
+                                        context.getPackageName(),
+                                        DB_NAME_1,
+                                        new GetByDocumentIdRequest.Builder("namespace")
+                                                .addIds("id")
+                                                .build()));
+
+        assertThat(e)
+                .hasMessageThat()
+                .isEqualTo(
+                        Features.GLOBAL_SEARCH_SESSION_GET_BY_ID
+                                + " is not supported on this AppSearch implementation.");
+    }
+
+    @Test
     public void testAddObserver_schemaChange_added() throws Exception {
         // Register an observer
         TestObserverCallback observer = new TestObserverCallback();
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
index 8171168..d72b482 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/SetSchemaRequestCtsTest.java
@@ -274,6 +274,62 @@
     }
 
     @Test
+    public void testClearSchemaTypeVisibleForPermissions() {
+        SetSchemaRequest.Builder setSchemaRequestBuilder =
+                new SetSchemaRequest.Builder()
+                        .addSchemas(
+                                new AppSearchSchema.Builder("Schema1").build(),
+                                new AppSearchSchema.Builder("Schema2").build())
+                        .addRequiredPermissionsForSchemaTypeVisibility(
+                                "Schema1",
+                                ImmutableSet.of(
+                                        SetSchemaRequest.READ_SMS, SetSchemaRequest.READ_CALENDAR))
+                        .addRequiredPermissionsForSchemaTypeVisibility(
+                                "Schema1",
+                                ImmutableSet.of(SetSchemaRequest.READ_HOME_APP_SEARCH_DATA))
+                        .addRequiredPermissionsForSchemaTypeVisibility(
+                                "Schema2", ImmutableSet.of(SetSchemaRequest.READ_EXTERNAL_STORAGE));
+
+        SetSchemaRequest request = setSchemaRequestBuilder.build();
+
+        assertThat(request.getRequiredPermissionsForSchemaTypeVisibility())
+                .containsExactly(
+                        "Schema1",
+                                ImmutableSet.of(
+                                        ImmutableSet.of(
+                                                SetSchemaRequest.READ_SMS,
+                                                SetSchemaRequest.READ_CALENDAR),
+                                        ImmutableSet.of(
+                                                SetSchemaRequest.READ_HOME_APP_SEARCH_DATA)),
+                        "Schema2",
+                                ImmutableSet.of(
+                                        ImmutableSet.of(SetSchemaRequest.READ_EXTERNAL_STORAGE)));
+
+        // Clear the permissions in the builder
+        setSchemaRequestBuilder.clearRequiredPermissionsForSchemaTypeVisibility("Schema1");
+
+        // New object should be updated
+        assertThat(setSchemaRequestBuilder.build().getRequiredPermissionsForSchemaTypeVisibility())
+                .containsExactly(
+                        "Schema2",
+                        ImmutableSet.of(ImmutableSet.of(SetSchemaRequest.READ_EXTERNAL_STORAGE)));
+
+        // Old object should remain unchanged
+        assertThat(request.getRequiredPermissionsForSchemaTypeVisibility())
+                .containsExactly(
+                        "Schema1",
+                                ImmutableSet.of(
+                                        ImmutableSet.of(
+                                                SetSchemaRequest.READ_SMS,
+                                                SetSchemaRequest.READ_CALENDAR),
+                                        ImmutableSet.of(
+                                                SetSchemaRequest.READ_HOME_APP_SEARCH_DATA)),
+                        "Schema2",
+                                ImmutableSet.of(
+                                        ImmutableSet.of(SetSchemaRequest.READ_EXTERNAL_STORAGE)));
+    }
+
+    @Test
     public void testSchemaTypeVisibilityForPackage_visible() {
         AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
 
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/observer/DocumentChangeInfoCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/observer/DocumentChangeInfoCtsTest.java
new file mode 100644
index 0000000..2459214
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/observer/DocumentChangeInfoCtsTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 android.app.appsearch.cts.observer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.observer.DocumentChangeInfo;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+
+public class DocumentChangeInfoCtsTest {
+    @Test
+    public void testConstructor() {
+        DocumentChangeInfo DocumentChangeInfo =
+                new DocumentChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        "namespace",
+                        "SchemaName",
+                        ImmutableSet.of("documentId1", "documentId2"));
+        assertThat(DocumentChangeInfo.getPackageName()).isEqualTo("packageName");
+        assertThat(DocumentChangeInfo.getDatabaseName()).isEqualTo("databaseName");
+        assertThat(DocumentChangeInfo.getNamespace()).isEqualTo("namespace");
+        assertThat(DocumentChangeInfo.getSchemaName()).isEqualTo("SchemaName");
+        assertThat(DocumentChangeInfo.getChangedDocumentIds())
+                .containsExactly("documentId1", "documentId2");
+    }
+
+    @Test
+    public void testEqualsAndHasCode() {
+        DocumentChangeInfo info1Copy1 =
+                new DocumentChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        "namespace",
+                        "SchemaName",
+                        ImmutableSet.of("documentId1", "documentId2"));
+        DocumentChangeInfo info1Copy2 =
+                new DocumentChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        "namespace",
+                        "SchemaName",
+                        ImmutableSet.of("documentId1", "documentId2"));
+        DocumentChangeInfo info2 =
+                new DocumentChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        "namespace",
+                        "SchemaName",
+                        ImmutableSet.of("documentId3", "documentId2"));
+
+        assertThat(info1Copy1).isEqualTo(info1Copy2);
+        assertThat(info1Copy1.hashCode()).isEqualTo(info1Copy2.hashCode());
+        assertThat(info1Copy1).isNotEqualTo(info2);
+        assertThat(info1Copy1.hashCode()).isNotEqualTo(info2.hashCode());
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/observer/ObserverSpecCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/observer/ObserverSpecCtsTest.java
new file mode 100644
index 0000000..bdce40c
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/observer/ObserverSpecCtsTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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 android.app.appsearch.cts.observer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.observer.ObserverSpec;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+
+public class ObserverSpecCtsTest {
+    @Test
+    public void testFilterSchemas() {
+        ObserverSpec observerSpec =
+                new ObserverSpec.Builder()
+                        .addFilterSchemas("Schema1", "Schema2")
+                        .addFilterSchemas(ImmutableSet.of("Schema3", "Schema4"))
+                        .build();
+        assertThat(observerSpec.getFilterSchemas())
+                .containsExactly("Schema1", "Schema2", "Schema3", "Schema4");
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/observer/SchemaChangeInfoCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/observer/SchemaChangeInfoCtsTest.java
new file mode 100644
index 0000000..a2f1004
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/observer/SchemaChangeInfoCtsTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.app.appsearch.cts.observer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.observer.SchemaChangeInfo;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+
+public class SchemaChangeInfoCtsTest {
+    @Test
+    public void testConstructor() {
+        SchemaChangeInfo schemaChangeInfo =
+                new SchemaChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        ImmutableSet.of("schemaName1", "schemaName2"));
+        assertThat(schemaChangeInfo.getPackageName()).isEqualTo("packageName");
+        assertThat(schemaChangeInfo.getDatabaseName()).isEqualTo("databaseName");
+        assertThat(schemaChangeInfo.getChangedSchemaNames())
+                .containsExactly("schemaName1", "schemaName2");
+    }
+
+    @Test
+    public void testEqualsAndHasCode() {
+        SchemaChangeInfo info1Copy1 =
+                new SchemaChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        ImmutableSet.of("schemaName1", "schemaName2"));
+        SchemaChangeInfo info1Copy2 =
+                new SchemaChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        ImmutableSet.of("schemaName1", "schemaName2"));
+        SchemaChangeInfo info2 =
+                new SchemaChangeInfo(
+                        "packageName",
+                        "databaseName",
+                        ImmutableSet.of("schemaName3", "schemaName2"));
+
+        assertThat(info1Copy1).isEqualTo(info1Copy2);
+        assertThat(info1Copy1.hashCode()).isEqualTo(info1Copy2.hashCode());
+        assertThat(info1Copy1).isNotEqualTo(info2);
+        assertThat(info1Copy1.hashCode()).isNotEqualTo(info2.hashCode());
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
index 55f94ef..ae7a665 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
@@ -109,7 +109,7 @@
         }
 
         protected static InlineUiBot getInlineUiBot() {
-            return sDefaultUiBot2;
+            return new InlineUiBot(getContext());
         }
 
         protected static UiBot getDropdownUiBot() {
@@ -485,7 +485,6 @@
     }
 
     protected static final UiBot sDefaultUiBot = new UiBot();
-    protected static final InlineUiBot sDefaultUiBot2 = new InlineUiBot();
 
     private AutoFillServiceTestCase() {
         throw new UnsupportedOperationException("Contain static stuff only");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index 6149ec9..6c2afe0 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -771,6 +771,7 @@
 
     /**
      * Gets the total number of nodes in an structure.
+     * A node that has a non-null IdPackage which does not match the test package is not counted.
      */
     public static int getNumberNodes(AssistStructure structure,
             CharSequence windowTitle) {
@@ -798,14 +799,18 @@
 
     /**
      * Gets the total number of nodes in an node, including all descendants and the node itself.
+     * A node that has a non-null IdPackage which does not match the test package is not counted.
      */
     public static int getNumberNodes(ViewNode node) {
+        if (node.getIdPackage() != null && !node.getIdPackage().equals(MY_PACKAGE)) {
+            Log.w(TAG, "ViewNode ignored in getNumberNodes because of mismatched package: "
+                    + node.getIdPackage());
+            return 0;
+        }
         int count = 1;
         final int childrenSize = node.getChildCount();
-        if (childrenSize > 0) {
-            for (int i = 0; i < childrenSize; i++) {
-                count += getNumberNodes(node.getChildAt(i));
-            }
+        for (int i = 0; i < childrenSize; i++) {
+            count += getNumberNodes(node.getChildAt(i));
         }
         return count;
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
index 50892fc..f488f09 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
@@ -20,14 +20,16 @@
 import static android.autofillservice.cts.testcore.Timeouts.LONG_PRESS_MS;
 import static android.autofillservice.cts.testcore.Timeouts.UI_TIMEOUT;
 
+import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiObject2;
+import android.util.Log;
 
 import com.android.compatibility.common.util.RequiredFeatureRule;
-import com.android.compatibility.common.util.Timeout;
 import com.android.cts.mockime.MockIme;
 
 import org.junit.rules.RuleChain;
@@ -46,12 +48,11 @@
     private static final RequiredFeatureRule REQUIRES_IME_RULE = new RequiredFeatureRule(
             PackageManager.FEATURE_INPUT_METHODS);
 
-    public InlineUiBot() {
-        this(UI_TIMEOUT);
-    }
+    private final Context mContext;
 
-    public InlineUiBot(Timeout defaultTimeout) {
-        super(defaultTimeout);
+    public InlineUiBot(Context context) {
+        super(UI_TIMEOUT);
+        mContext = context;
     }
 
     public static RuleChain annotateRule(TestRule rule) {
@@ -73,7 +74,7 @@
      * Selects the suggestion in the {@link MockIme}'s suggestion strip by the given text.
      */
     public void selectSuggestion(String name) throws Exception {
-        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        final UiObject2 strip = findSuggestionStrip();
         final UiObject2 dataset = strip.findObject(By.text(name));
         if (dataset == null) {
             throw new AssertionError("no dataset " + name + " in " + getChildrenAsText(strip));
@@ -88,7 +89,7 @@
 
     @Override
     public void longPressSuggestion(String name) throws Exception {
-        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        final UiObject2 strip = findSuggestionStrip();
         final UiObject2 dataset = strip.findObject(By.text(name));
         if (dataset == null) {
             throw new AssertionError("no dataset " + name + " in " + getChildrenAsText(strip));
@@ -97,14 +98,14 @@
     }
 
     @Override
-    public UiObject2 assertDatasets(String...names) throws Exception {
-        final UiObject2 picker = findSuggestionStrip(UI_TIMEOUT);
+    public UiObject2 assertDatasets(String... names) throws Exception {
+        final UiObject2 picker = findSuggestionStrip();
         return assertDatasets(picker, names);
     }
 
     @Override
     public void assertSuggestion(String name) throws Exception {
-        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        final UiObject2 strip = findSuggestionStrip();
         final UiObject2 dataset = strip.findObject(By.text(name));
         if (dataset == null) {
             throw new AssertionError("no dataset " + name + " in " + getChildrenAsText(strip));
@@ -113,7 +114,7 @@
 
     @Override
     public void assertNoSuggestion(String name) throws Exception {
-        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        final UiObject2 strip = findSuggestionStrip();
         final UiObject2 dataset = strip.findObject(By.text(name));
         if (dataset != null) {
             throw new AssertionError("has dataset " + name + " in " + getChildrenAsText(strip));
@@ -122,7 +123,10 @@
 
     @Override
     public void scrollSuggestionView(Direction direction, int speed) throws Exception {
-        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        final UiObject2 strip = findSuggestionStrip();
+        final int defaultWidth = strip.getVisibleBounds().width() / 4;
+        final int width = getEdgeSensitivityWidth(defaultWidth);
+        strip.setGestureMargin(width);
         strip.fling(direction, speed);
     }
 
@@ -133,7 +137,18 @@
         }
     }
 
-    private UiObject2 findSuggestionStrip(Timeout timeout) throws Exception {
-        return waitForObject(SUGGESTION_STRIP_SELECTOR, timeout);
+    private UiObject2 findSuggestionStrip() throws Exception {
+        return waitForObject(SUGGESTION_STRIP_SELECTOR, Timeouts.UI_TIMEOUT);
+    }
+
+    private int getEdgeSensitivityWidth(int defaultWidth) {
+        Resources resources = mContext.getResources();
+        int resId = resources.getIdentifier("config_backGestureInset", "dimen", "android");
+        try {
+            return resources.getDimensionPixelSize(resId) + 1;
+        } catch (Resources.NotFoundException e) {
+            Log.e(TAG, "Failed to get edge sensitivity width. Defaulting to " + defaultWidth, e);
+            return defaultWidth;
+        }
     }
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index e1f17da..f6b7830 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -994,23 +994,32 @@
             assertNotNull(
                     String.format("Can't get camera characteristics from: ID %s", cameraId), props);
 
+            Integer lensFacing = props.get(CameraCharacteristics.LENS_FACING);
+            if (lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_EXTERNAL) {
+                // Automotive device implementations may have external cameras but they are exempted
+                // from this test case.
+                continue;
+            }
+
             Integer cameraLocation = props.get(CameraCharacteristics.AUTOMOTIVE_LOCATION);
             assertNotNull(
                     String.format("Can't get a camera location from: ID %s", cameraId),
                     cameraLocation);
 
-            int[] lensFacing = props.get(CameraCharacteristics.AUTOMOTIVE_LENS_FACING);
+            int[] automotiveLensFacing = props.get(CameraCharacteristics.AUTOMOTIVE_LENS_FACING);
             assertNotNull(
                     String.format("Can't get a lens facing direction from: ID %s", cameraId),
-                    lensFacing);
+                    automotiveLensFacing);
 
             if (cameraLocation == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTERIOR_OTHER ||
                     cameraLocation == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTRA_OTHER ||
-                    lensFacing[0] == CameraCharacteristics.AUTOMOTIVE_LENS_FACING_EXTERIOR_OTHER ||
-                    lensFacing[0] == CameraCharacteristics.AUTOMOTIVE_LENS_FACING_INTERIOR_OTHER) {
+                    automotiveLensFacing[0] ==
+                            CameraCharacteristics.AUTOMOTIVE_LENS_FACING_EXTERIOR_OTHER ||
+                    automotiveLensFacing[0] ==
+                            CameraCharacteristics.AUTOMOTIVE_LENS_FACING_INTERIOR_OTHER) {
                 checkAutomotiveLensPoseCharacteristics(cameraId, props);
             } else {
-                Pair<Integer, Integer> key = new Pair<>(cameraLocation, lensFacing[0]);
+                Pair<Integer, Integer> key = new Pair<>(cameraLocation, automotiveLensFacing[0]);
                 if (cameraGroup.containsKey(key)) {
                     cameraGroup.get(key).add(cameraId);
                 } else {
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 5db96a4..8b5b33d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -3106,6 +3106,90 @@
     }
 
     /**
+     * Validate {@link CameraCharacteristics#LENS_POSE_TRANSLATION} and @{link
+     * CameraCharacteristics#LENS_POSE_ROTATION} of camera that list below characteristics in their
+     * static metadata.
+     * - CameraCharacteristics.AUTOMOTIVE_LOCATION_INTERIOR_OTHER
+     * - CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTERIOR_OTHER
+     * - CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTRA_OTHER
+     */
+    @Test
+    public void testAutomotiveCameraCharacteristics() throws Exception {
+        for (int i = 0; i < mAllCameraIds.length; i++) {
+            CameraCharacteristics c = mCharacteristics.get(i);
+
+            Integer location = c.get(CameraCharacteristics.AUTOMOTIVE_LOCATION);
+            int[] lensFacing = c.get(CameraCharacteristics.AUTOMOTIVE_LENS_FACING);
+            if (location == null || lensFacing == null) {
+                // CameraManagerTest#testCameraManagerAutomotiveCameras() guarantees
+                // CameraCharacteristics.AUTOMOTIVE_LOCATION and
+                // CameraCharacteristics.AUTOMOTIVE_LENS_FACING are listed in a static metadata of
+                // cameras on the automotive device implementations.
+                continue;
+            }
+
+            float[] translation = c.get(CameraCharacteristics.LENS_POSE_TRANSLATION);
+            float[] rotation = c.get(CameraCharacteristics.LENS_POSE_ROTATION);
+            assertTrue("android.lens.poseTranslation and android.lens.poseRotation must exist " +
+                    "together or not at all",
+                    (translation != null) == (rotation != null));
+            if (translation == null && rotation != null) {
+                // Cameras without android.lens.poseTranslation and anroid.lens.poseRotation are
+                // exempt from this test case.
+                continue;
+            }
+
+            // android.lens.poseTranslation describes the lens optical center of the camera device
+            // as a three dimensional vector (x, y, z) and in the unit of meters.  On the automotive
+            // sensor coordinate system, we expect the following:
+            // - The width of the vehicle body frame would not exceed 6 meters, which is a width of
+            //   the vehicle lane approximately.
+            // - The length of the vehicle body frame would not exceed 10 meters, which is an
+            //   average length of the city bus.  We apply approximately 20% tolerance to this value
+            //   because of a relatively higher variance of the vehicle's length.
+            // - The height of the vehicle body frame would not exceed 5 meters, which is an average
+            //   height of the double decker bus.
+            assertTrue("Lens pose translation vector is invalid",
+                    (translation[0] >= -3 && translation[0] <= 3)
+                            && (translation[1] >= -2 && translation[1] <= 10)
+                            && (translation[2] >= 0 && translation[2] <= 5));
+
+            // Convert a given quaternion to axis-angle representation
+            double theta = 2.0 * Math.acos(rotation[3]);
+            double a_x = rotation[0] / Math.sin(theta / 2.0);
+            double a_y = rotation[1] / Math.sin(theta / 2.0);
+            double a_z = rotation[2] / Math.sin(theta / 2.0);
+
+            // Calculate an angle between a translation vector and a rotation axis
+            double dot = (translation[0] * a_x) + (translation[1] * a_y) + (translation[2] * a_z);
+            double mag_a = Math.sqrt(Math.pow(translation[0], 2) + Math.pow(translation[1], 2)
+                    + Math.pow(translation[2], 2));
+            double mag_b =
+                    Math.sqrt(Math.pow(a_x, 2) + Math.pow(a_y, 2) + Math.pow(a_z, 2));
+            double angle = Math.acos(dot / (mag_a * mag_b));
+
+            if (location == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTERIOR_OTHER
+                    || location == CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTRA_OTHER) {
+                // If android.automotive.location is
+                // CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTERIOR_OTHER or
+                // CameraCharacteristics.AUTOMOTIVE_LOCATION_EXTRA_OTHER, its
+                // android.lens.poseRotation should not describe a direction toward the inside of
+                // the vehicle cabin.
+                assertTrue("Lens pose rotation should not describe a direction toward the cabin",
+                        angle >= Math.PI / 4);
+            } else {
+                // Likewise, if android.automotive.location is
+                // CameraCharacteristics.AUTOMOTIVE_LOCATION_INTERIOR_OTHER, its
+                // android.lens.poseRotation should not describe a direction toward the outside of
+                // the vehicle cabin.
+                assertTrue("Lens pose rotation should not describe a direction toward the " +
+                        "outside of the cabin",
+                        angle <= Math.PI * 3 / 4);
+            }
+        }
+    }
+
+    /**
      * Check key is present in characteristics if the hardware level is at least {@code hwLevel};
      * check that the key is present if the actual capabilities are one of {@code capabilities}.
      *
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 1535458..d65b7f6 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -295,7 +295,7 @@
             int format, Size targetSize, int numBuffers, String overridePhysicalCameraId,
             MultiResolutionStreamConfigurationMap multiResStreamConfig,
             boolean createMultiResiStreamConfig, ImageDropperListener listener, Handler handler,
-            long dynamicRangeProfile, int streamUseCase) {
+            long dynamicRangeProfile, long streamUseCase) {
         if (createMultiResiStreamConfig) {
             Collection<MultiResolutionStreamInfo> multiResolutionStreams =
                     multiResStreamConfig.getOutputInfo(format);
diff --git a/tests/cloudsearch/src/android/cloudsearch/cts/SearchRequestTest.java b/tests/cloudsearch/src/android/cloudsearch/cts/SearchRequestTest.java
index 3913da4..5966d95 100644
--- a/tests/cloudsearch/src/android/cloudsearch/cts/SearchRequestTest.java
+++ b/tests/cloudsearch/src/android/cloudsearch/cts/SearchRequestTest.java
@@ -45,11 +45,11 @@
         Bundle constraints = new Bundle();
         constraints.putBoolean(SearchRequest.CONSTRAINT_IS_PRESUBMIT_SUGGESTION,
                 true);
-        final String source = "AiAi_CALLER";
+        final String pkgName = "android.cloudsearch.cts";
 
         SearchRequest request = new SearchRequest.Builder("").setResultNumber(rn)
                 .setResultOffset(offset).setSearchConstraints(constraints).setQuery(query)
-                .setMaxLatencyMillis(maxLatency).setSource(source).build();
+                .setMaxLatencyMillis(maxLatency).setCallerPackageName(pkgName).build();
 
         /** Check the original request. */
         assertThat(request.getQuery()).isEqualTo(query);
@@ -59,7 +59,7 @@
         final Bundle sc = request.getSearchConstraints();
         assertThat(sc.getBoolean(SearchRequest.CONSTRAINT_IS_PRESUBMIT_SUGGESTION))
                 .isEqualTo(true);
-        assertThat(request.getSource()).isEqualTo(source);
+        assertThat(request.getCallerPackageName()).isEqualTo(pkgName);
 
         Parcel parcel = Parcel.obtain();
         parcel.setDataPosition(0);
@@ -74,7 +74,7 @@
         final Bundle sccopy = request.getSearchConstraints();
         assertThat(sccopy.getBoolean(SearchRequest.CONSTRAINT_IS_PRESUBMIT_SUGGESTION))
                 .isEqualTo(true);
-        assertThat(copy.getSource()).isEqualTo(source);
+        assertThat(copy.getCallerPackageName()).isEqualTo(pkgName);
 
         parcel.recycle();
     }
diff --git a/tests/cloudsearch/src/android/cloudsearch/cts/SearchResultTest.java b/tests/cloudsearch/src/android/cloudsearch/cts/SearchResultTest.java
index 042d40c..9dd83f4 100644
--- a/tests/cloudsearch/src/android/cloudsearch/cts/SearchResultTest.java
+++ b/tests/cloudsearch/src/android/cloudsearch/cts/SearchResultTest.java
@@ -15,9 +15,14 @@
  */
 package android.cloudsearch.cts;
 
+import static androidx.test.InstrumentationRegistry.getContext;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.PendingIntent;
 import android.app.cloudsearch.SearchResult;
+import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
 
@@ -41,12 +46,20 @@
         final String title = "title";
         final String snippet = "Good Snippet";
         final float score = 10;
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.android.com"));
+        PendingIntent pendingIntent = PendingIntent.getActivity(getContext(),
+                1, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
 
         Bundle extraInfos = new Bundle();
         extraInfos.putBoolean(SearchResult.EXTRAINFO_APP_CONTAINS_IAP_DISCLAIMER,
                 false);
         extraInfos.putString(SearchResult.EXTRAINFO_APP_DEVELOPER_NAME,
                 "best_app_developer");
+        extraInfos.putParcelable(SearchResult.EXTRAINFO_ACTION_INSTALL_BUTTON, pendingIntent);
+        extraInfos.putParcelable(SearchResult.EXTRAINFO_ACTION_APP_CARD, pendingIntent);
+        extraInfos.putString(SearchResult.EXTRAINFO_APP_PACKAGE_NAME,
+                "best_package_name");
+        extraInfos.putDouble(SearchResult.EXTRAINFO_APP_INSTALL_COUNT, 10);
 
         SearchResult result = new SearchResult.Builder(title, extraInfos)
                 .setSnippet(snippet).setTitle(title).setExtraInfos(extraInfos)
@@ -63,6 +76,18 @@
         assertThat(rExtraInfos
                 .getString(SearchResult.EXTRAINFO_APP_DEVELOPER_NAME))
                 .isEqualTo("best_app_developer");
+        assertThat((PendingIntent) rExtraInfos
+                .getParcelable(SearchResult.EXTRAINFO_ACTION_INSTALL_BUTTON))
+                .isEqualTo(pendingIntent);
+        assertThat((PendingIntent) rExtraInfos
+                .getParcelable(SearchResult.EXTRAINFO_ACTION_APP_CARD))
+                .isEqualTo(pendingIntent);
+        assertThat(rExtraInfos
+                .getString(SearchResult.EXTRAINFO_APP_PACKAGE_NAME))
+                .isEqualTo("best_package_name");
+        assertThat(rExtraInfos
+                .getDouble(SearchResult.EXTRAINFO_APP_INSTALL_COUNT))
+                .isEqualTo(10);
 
         Parcel parcel = Parcel.obtain();
         parcel.setDataPosition(0);
@@ -80,6 +105,18 @@
         assertThat(rExtraInfosCopy
                 .getString(SearchResult.EXTRAINFO_APP_DEVELOPER_NAME))
                 .isEqualTo("best_app_developer");
+        assertThat((PendingIntent) rExtraInfosCopy
+                .getParcelable(SearchResult.EXTRAINFO_ACTION_INSTALL_BUTTON))
+                .isEqualTo(pendingIntent);
+        assertThat((PendingIntent) rExtraInfosCopy
+                .getParcelable(SearchResult.EXTRAINFO_ACTION_APP_CARD))
+                .isEqualTo(pendingIntent);
+        assertThat(rExtraInfosCopy
+                .getString(SearchResult.EXTRAINFO_APP_PACKAGE_NAME))
+                .isEqualTo("best_package_name");
+        assertThat(rExtraInfosCopy
+                .getDouble(SearchResult.EXTRAINFO_APP_INSTALL_COUNT))
+                .isEqualTo(10);
 
         parcel.recycle();
     }
diff --git a/tests/devicepolicy/AndroidManifest.xml b/tests/devicepolicy/AndroidManifest.xml
index c8dd6c4..c8c6c0e 100644
--- a/tests/devicepolicy/AndroidManifest.xml
+++ b/tests/devicepolicy/AndroidManifest.xml
@@ -23,6 +23,9 @@
             canInteractAcrossProfiles_permissionIsSet_returnsTrue -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/>
 
+    <!-- Seemingly the INTERNET permission cannot be adopted. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+
     <!-- Add a network security config that trusts user added CAs for tests -->
     <application android:testOnly="true"
                  android:appComponentFactory="com.android.eventlib.premade.EventLibAppComponentFactory"
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ApplicationRestrictionsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ApplicationRestrictionsTest.java
index ec18186..f3adec0 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ApplicationRestrictionsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ApplicationRestrictionsTest.java
@@ -408,21 +408,21 @@
     private void assertBooleanKey(Bundle bundle, String key, boolean expectedValue) {
         boolean value = bundle.getBoolean(key);
         Log.v(TAG, "assertBooleanKey(): " + key + "=" + value);
-        assertWithMessage("bundle's '%s' key")
+        assertWithMessage("bundle's '%s' key", key)
                 .that(value).isEqualTo(expectedValue);
     }
 
     private void assertIntKey(Bundle bundle, String key, int expectedValue) {
         int value = bundle.getInt(key);
         Log.v(TAG, "assertIntKey(): " + key + "=" + value);
-        assertWithMessage("bundle's '%s' key")
+        assertWithMessage("bundle's '%s' key", key)
                 .that(value).isEqualTo(expectedValue);
     }
 
     private void assertStringKey(Bundle bundle, String key, String expectedValue) {
         String value = bundle.getString(key);
         Log.v(TAG, "assertStringKey(): " + key + "=" + value);
-        assertWithMessage("bundle's '%s' key")
+        assertWithMessage("bundle's '%s' key", key)
                 .that(value).isEqualTo(expectedValue);
     }
 
@@ -431,14 +431,14 @@
         Log.v(TAG, "assertStringsKey(): " + key + "="
                 + (value == null ? "null" : Arrays.toString(value)));
 
-        assertWithMessage("bundle's '%s' key").that(value).asList()
+        assertWithMessage("bundle's '%s' key", key).that(value).asList()
                 .containsExactlyElementsIn(expectedValue).inOrder();
     }
 
     private Bundle getBundleKey(Bundle bundle, String key) {
         Bundle value = bundle.getBundle(key);
         Log.v(TAG, "getBundleKey(): " + key + "=" + value);
-        assertWithMessage("bundle's '%s' key").that(value).isNotNull();
+        assertWithMessage("bundle's '%s' key", key).that(value).isNotNull();
         return value;
     }
 
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/BackupTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/BackupTest.java
index a086173..f63c806 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/BackupTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/BackupTest.java
@@ -24,7 +24,6 @@
 
 import static org.testng.Assert.assertThrows;
 
-import android.app.admin.DevicePolicyManager;
 import android.app.backup.BackupManager;
 import android.content.Context;
 
@@ -52,8 +51,6 @@
     public static final DeviceState sDeviceState = new DeviceState();
 
     private static final Context sContext = TestApis.context().instrumentedContext();
-    private static final DevicePolicyManager sLocalDevicePolicyManager =
-            sContext.getSystemService(DevicePolicyManager.class);
     private static final BackupManager sLocalBackupManager = new BackupManager(sContext);
 
     @PolicyAppliesTest(policy = Backup.class)
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/BlockUninstallTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/BlockUninstallTest.java
new file mode 100644
index 0000000..8b0b041
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/BlockUninstallTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.devicepolicy.cts;
+
+import static com.android.bedstead.metricsrecorder.truth.MetricQueryBuilderSubject.assertThat;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.admin.DevicePolicyManager;
+import android.stats.devicepolicy.EventId;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.BeforeClass;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.PolicyAppliesTest;
+import com.android.bedstead.harrier.annotations.enterprise.PolicyDoesNotApplyTest;
+import com.android.bedstead.harrier.policies.BlockUninstall;
+import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.testapp.TestApp;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public class BlockUninstallTest {
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final TestApp sTestApp = sDeviceState.testApps().any();
+
+    private static final String NOT_INSTALLED_PACKAGE_NAME = "not.installed.package";
+
+    private static final DevicePolicyManager sLocalDevicePolicyManager =
+            TestApis.context().instrumentedContext().getSystemService(DevicePolicyManager.class);
+
+    @BeforeClass
+    public static void setupClass() {
+        sTestApp.install();
+    }
+
+    @AfterClass
+    public static void teardownClass() {
+        sTestApp.uninstallFromAllUsers();
+    }
+
+    @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ true);
+        });
+    }
+
+    @Postsubmit(reason = "new test")
+    @PolicyAppliesTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_true_isUninstallBlockedIsTrue() {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ true
+            );
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().isUninstallBlocked(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName()
+            )).isTrue();
+            assertThat(sLocalDevicePolicyManager.isUninstallBlocked(/* admin= */ null,
+                    sTestApp.packageName())).isTrue();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ false
+            );
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @PolicyDoesNotApplyTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_true_isUninstallBlockedIsFalse() {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ true
+            );
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().isUninstallBlocked(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName()
+            )).isTrue();
+            assertThat(sLocalDevicePolicyManager.isUninstallBlocked(/* admin= */ null,
+                    sTestApp.packageName())).isFalse();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ false
+            );
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @PolicyAppliesTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_false_isUninstallBlockedIsFalse() {
+        sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                sDeviceState.dpc().componentName(),
+                sTestApp.packageName(), /* uninstallBlocked= */ false
+        );
+
+        assertThat(sDeviceState.dpc().devicePolicyManager().isUninstallBlocked(
+                sDeviceState.dpc().componentName(), sTestApp.packageName()
+        )).isFalse();
+        assertThat(sLocalDevicePolicyManager.isUninstallBlocked(/* admin= */ null,
+                sTestApp.packageName())).isFalse();
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_true_appIsNotInstalled_silentlyFails() {
+        sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                sDeviceState.dpc().componentName(),
+                NOT_INSTALLED_PACKAGE_NAME, /* uninstallBlocked= */ true
+        );
+
+        assertThat(sDeviceState.dpc().devicePolicyManager().isUninstallBlocked(
+                sDeviceState.dpc().componentName(), NOT_INSTALLED_PACKAGE_NAME
+        )).isFalse();
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = BlockUninstall.class)
+    public void setUninstallBlocked_logged() {
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ true
+            );
+
+            assertThat(metrics.query()
+                            .whereType().isEqualTo(EventId.SET_UNINSTALL_BLOCKED_VALUE)
+                            .whereAdminPackageName().isEqualTo(
+                                    sDeviceState.dpc().packageName())
+                            .whereStrings().contains(sTestApp.packageName())
+                            .whereStrings().size().isEqualTo(1)
+                            .whereBoolean().isEqualTo(sDeviceState.dpc().isDelegate())
+                            ).wasLogged();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setUninstallBlocked(
+                    sDeviceState.dpc().componentName(),
+                    sTestApp.packageName(), /* uninstallBlocked= */ false
+            );
+        }
+    }
+}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
index 6eb98c0..4998a6e 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileAppsTest.java
@@ -477,6 +477,94 @@
     @Test
     @RequireRunOnPrimaryUser
     @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
+    @EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
+    @Postsubmit(reason = "new test")
+    public void startMainActivity_byComponent_nullActivity_newTask() throws Exception {
+        int originalTaskId = ActivityContext.getWithContext(activity -> {
+            sCrossProfileApps.startMainActivity(
+                    MAIN_ACTIVITY,
+                    sDeviceState.workProfile().userHandle(),
+                    /* callingActivity */ null,
+                    /* options */ null);
+
+            return activity.getTaskId();
+        });
+
+        ActivityCreatedEvent event =
+                ActivityEvents.forActivity(MAIN_ACTIVITY, sDeviceState.workProfile())
+                        .activityCreated().waitForEvent();
+        assertThat(event.taskId()).isNotEqualTo(originalTaskId);
+    }
+
+    @Test
+    @RequireRunOnPrimaryUser
+    @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
+    @EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
+    @Postsubmit(reason = "new test")
+    public void startMainActivity_byComponent_setsActivity_sameTask() throws Exception {
+        int originalTaskId = ActivityContext.getWithContext(activity -> {
+            sCrossProfileApps.startMainActivity(
+                    MAIN_ACTIVITY,
+                    sDeviceState.workProfile().userHandle(),
+                    activity,
+                    /* options */ null);
+
+            return activity.getTaskId();
+        });
+
+        ActivityCreatedEvent event =
+                ActivityEvents.forActivity(MAIN_ACTIVITY, sDeviceState.workProfile())
+                        .activityCreated().waitForEvent();
+        assertThat(event.taskId()).isEqualTo(originalTaskId);
+    }
+
+    @Test
+    @RequireRunOnPrimaryUser
+    @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
+    @EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
+    @Postsubmit(reason = "new test")
+    public void startNonMainActivity_byComponent_nullActivity_newTask() throws Exception {
+        int originalTaskId = ActivityContext.getWithContext(activity -> {
+            sCrossProfileApps.startActivity(
+                    NOT_MAIN_ACTIVITY,
+                    sDeviceState.workProfile().userHandle(),
+                    /* callingActivity */ null,
+                    /* options */ null);
+
+            return activity.getTaskId();
+        });
+
+        ActivityCreatedEvent event =
+                ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
+                        .activityCreated().waitForEvent();
+        assertThat(event.taskId()).isNotEqualTo(originalTaskId);
+    }
+
+    @Test
+    @RequireRunOnPrimaryUser
+    @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
+    @EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
+    @Postsubmit(reason = "new test")
+    public void startNonMainActivity_byComponent_setsActivity_sameTask() throws Exception {
+        int originalTaskId = ActivityContext.getWithContext(activity -> {
+            sCrossProfileApps.startActivity(
+                    NOT_MAIN_ACTIVITY,
+                    sDeviceState.workProfile().userHandle(),
+                    activity,
+                    /* options */ null);
+
+            return activity.getTaskId();
+        });
+
+        ActivityCreatedEvent event =
+                ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
+                        .activityCreated().waitForEvent();
+        assertThat(event.taskId()).isEqualTo(originalTaskId);
+    }
+
+    @Test
+    @RequireRunOnPrimaryUser
+    @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
     @EnsureHasPermission(INTERACT_ACROSS_PROFILES)
     @Postsubmit(reason = "new test")
     public void startActivity_byIntent_logged() throws Exception {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileSharingTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileSharingTest.java
index d2dff2a..2c6fb57 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileSharingTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/CrossProfileSharingTest.java
@@ -63,8 +63,6 @@
     @Rule
     public static final DeviceState sDeviceState = new DeviceState();
 
-    private static final Context sContext = TestApis.context().instrumentedContext();
-
     private static final TestApp sTestApp = sDeviceState.testApps().query()
             .whereActivities().contains(
                     activity().intentFilters().contains(
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
index 5a45a66..79151e3 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DeviceOwnerTest.java
@@ -49,6 +49,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.time.Duration;
+
 @RunWith(BedsteadJUnit4.class)
 public final class DeviceOwnerTest {
     @ClassRule
@@ -118,11 +120,12 @@
             Poll.forValue("Active admins", dpm::getActiveAdmins)
                     .toMeet(i -> i == null || !i.contains(RemoteDpc.DPC_COMPONENT_NAME))
                     .errorOnFail("Expected active admins to not contain RemoteDPC")
+                    .timeout(Duration.ofMinutes(5))
                     .await();
         }
     }
 
-    @UserTest({UserType.PRIMARY_USER, UserType.SECONDARY_USER, UserType.WORK_PROFILE})
+    @UserTest({UserType.PRIMARY_USER, UserType.SECONDARY_USER})
     @EnsureHasDeviceOwner
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @Postsubmit(reason = "new test")
@@ -131,7 +134,7 @@
                 .isEqualTo(sDeviceState.dpc().packageName());
     }
 
-    @UserTest({UserType.PRIMARY_USER, UserType.SECONDARY_USER, UserType.WORK_PROFILE})
+    @UserTest({UserType.PRIMARY_USER, UserType.SECONDARY_USER})
     @EnsureHasDeviceOwner
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @Postsubmit(reason = "new test")
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index 4c9b3a1..657c61c 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.PROVISION_DEMO_DEVICE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
@@ -63,6 +64,7 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 
 import androidx.test.core.app.ApplicationProvider;
 
@@ -110,6 +112,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -139,8 +142,6 @@
     private static final String ACCOUNT_TYPE = "com.android.cts.test";
     private static final Account TEST_ACCOUNT = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
 
-    private static final String USER_SETUP_COMPLETE_KEY = "user_setup_complete";
-
     private static final String KEY_PRE_PROVISIONING_SYSTEM_APPS = "pre_provisioning_system_apps";
     private static final String KEY_PRE_PROVISIONING_NON_SYSTEM_APPS =
             "pre_provisioning_non_system_apps";
@@ -686,6 +687,123 @@
         }
     }
 
+    @Postsubmit(reason = "New test")
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @RequireFeature(FEATURE_DEVICE_ADMIN)
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    @Test
+    public void newlyProvisionedFullyManagedDevice_setsDeviceAsDemoDeviceWhenRequested()
+            throws Exception {
+        boolean setupComplete = TestApis.users().current().getSetupComplete();
+        TestApis.users().current().setSetupComplete(false);
+        // TODO(b/222499341): replace with annotations
+        int demoDevice = TestApis.settings().global().getInt(Settings.Global.DEVICE_DEMO_MODE, 0);
+        TestApis.settings().global().putInt(Settings.Global.DEVICE_DEMO_MODE, 0);
+        try {
+            FullyManagedDeviceProvisioningParams params =
+                    createDefaultManagedDeviceProvisioningParamsBuilder()
+                            .setDemoDevice(true)
+                            .build();
+            sDevicePolicyManager.provisionFullyManagedDevice(params);
+
+            assertThat(TestApis.settings().global().getInt(Settings.Global.DEVICE_DEMO_MODE, 0))
+                    .isEqualTo(1);
+        } finally {
+            TestApis.users().current().setSetupComplete(setupComplete);
+            TestApis.settings().global().putInt(Settings.Global.DEVICE_DEMO_MODE, demoDevice);
+        }
+    }
+
+    @Postsubmit(reason = "New test")
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @RequireFeature(FEATURE_DEVICE_ADMIN)
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    @Test
+    public void newlyProvisionedFullyManagedDevice_setsProvisioningStateWhenDemoDeviceIsRequested()
+            throws Exception {
+        boolean setupComplete = TestApis.users().current().getSetupComplete();
+        TestApis.users().current().setSetupComplete(false);
+        // TODO(b/222499341): replace with annotations
+        int demoDevice = TestApis.settings().global().getInt(Settings.Global.DEVICE_DEMO_MODE, 0);
+        try {
+            FullyManagedDeviceProvisioningParams params =
+                    createDefaultManagedDeviceProvisioningParamsBuilder()
+                            .setDemoDevice(true)
+                            .build();
+            sDevicePolicyManager.provisionFullyManagedDevice(params);
+
+            assertThat(sDevicePolicyManager.getUserProvisioningState())
+                    .isEqualTo(DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
+        } finally {
+            TestApis.users().current().setSetupComplete(setupComplete);
+            TestApis.settings().global().putInt(Settings.Global.DEVICE_DEMO_MODE, demoDevice);
+        }
+    }
+
+    @Postsubmit(reason = "New test")
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @RequireFeature(FEATURE_DEVICE_ADMIN)
+    @EnsureHasPermission(PROVISION_DEMO_DEVICE)
+    @EnsureDoesNotHavePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    @Test
+    public void newlyProvisionedFullyManagedDevice_withProvisionDemoDevicePermission_throwsSecurityException()
+            throws Exception {
+        FullyManagedDeviceProvisioningParams params =
+                createDefaultManagedDeviceProvisioningParamsBuilder()
+                        .build();
+
+        assertThrows(SecurityException.class, () ->
+                sDevicePolicyManager.provisionFullyManagedDevice(params));
+    }
+
+    @Postsubmit(reason = "New test")
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @RequireFeature(FEATURE_DEVICE_ADMIN)
+    @EnsureHasPermission(PROVISION_DEMO_DEVICE)
+    @EnsureDoesNotHavePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    @Test
+    public void newlyProvisionedFullyManagedDevice_withProvisionDemoDevicePermissionForDemoDevice_doesNotThrowException()
+            throws Exception {
+        boolean setupComplete = TestApis.users().current().getSetupComplete();
+        TestApis.users().current().setSetupComplete(false);
+        // TODO(b/222499341): replace with annotations
+        int demoDevice = TestApis.settings().global().getInt(Settings.Global.DEVICE_DEMO_MODE, 0);
+        try {
+            FullyManagedDeviceProvisioningParams params =
+                    createDefaultManagedDeviceProvisioningParamsBuilder()
+                            .setDemoDevice(true)
+                            .build();
+
+            sDevicePolicyManager.provisionFullyManagedDevice(params);
+
+        } finally {
+            TestApis.users().current().setSetupComplete(setupComplete);
+            TestApis.settings().global().putInt(Settings.Global.DEVICE_DEMO_MODE, demoDevice);
+        }
+    }
+
+    @Postsubmit(reason = "New test")
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @RequireFeature(FEATURE_DEVICE_ADMIN)
+    @EnsureDoesNotHavePermission({
+            PROVISION_DEMO_DEVICE,
+            MANAGE_PROFILE_AND_DEVICE_OWNERS})
+    @Test
+    public void newlyProvisionedFullyManagedDevice_withoutRequiredPermissionsForDemoDevice_throwsSecurityException()
+            throws Exception {
+        FullyManagedDeviceProvisioningParams params =
+                createDefaultManagedDeviceProvisioningParamsBuilder()
+                        .setDemoDevice(true)
+                        .build();
+
+        assertThrows(SecurityException.class, () ->
+                sDevicePolicyManager.provisionFullyManagedDevice(params));
+    }
 
     @RequireDoesNotHaveFeature(PackageManager.FEATURE_AUTOMOTIVE)
     @EnsureHasPermission(MANAGE_DEVICE_ADMINS)
@@ -703,13 +821,13 @@
                 (new PreferentialNetworkServiceConfig.Builder())
                         .setEnabled(true).build();
         assertThrows(SecurityException.class,
-                () -> sDevicePolicyManager.setPreferentialNetworkServiceConfig(
-                        preferentialNetworkServiceConfigEnabled));
+                () -> sDevicePolicyManager.setPreferentialNetworkServiceConfigs(
+                        List.of(preferentialNetworkServiceConfigEnabled)));
         assertThrows(SecurityException.class,
-                () -> sDevicePolicyManager.setPreferentialNetworkServiceConfig(
-                        PreferentialNetworkServiceConfig.DEFAULT));
+                () -> sDevicePolicyManager.setPreferentialNetworkServiceConfigs(
+                        List.of(PreferentialNetworkServiceConfig.DEFAULT)));
         assertThrows(SecurityException.class,
-                () -> sDevicePolicyManager.getPreferentialNetworkServiceConfig());
+                () -> sDevicePolicyManager.getPreferentialNetworkServiceConfigs());
     }
 
     @Test
@@ -718,12 +836,12 @@
         PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
                 (new PreferentialNetworkServiceConfig.Builder())
                         .setEnabled(true).build();
-        sDevicePolicyManager.setPreferentialNetworkServiceConfig(
-                preferentialNetworkServiceConfigEnabled);
-        assertTrue(sDevicePolicyManager.getPreferentialNetworkServiceConfig().isEnabled());
-        sDevicePolicyManager.setPreferentialNetworkServiceConfig(
-                PreferentialNetworkServiceConfig.DEFAULT);
-        assertFalse(sDevicePolicyManager.getPreferentialNetworkServiceConfig().isEnabled());
+        sDevicePolicyManager.setPreferentialNetworkServiceConfigs(
+                List.of(preferentialNetworkServiceConfigEnabled));
+        assertTrue(sDevicePolicyManager.getPreferentialNetworkServiceConfigs().get(0).isEnabled());
+        sDevicePolicyManager.setPreferentialNetworkServiceConfigs(
+                List.of(PreferentialNetworkServiceConfig.DEFAULT));
+        assertFalse(sDevicePolicyManager.getPreferentialNetworkServiceConfigs().get(0).isEnabled());
         sDevicePolicyManager.clearProfileOwner(DEVICE_ADMIN_COMPONENT_NAME);
         SystemUtil.runShellCommand(REMOVE_ACTIVE_ADMIN_COMMAND);
     }
@@ -1339,19 +1457,6 @@
                         TestApis.users().current().userHandle()));
     }
 
-    @Postsubmit(reason = "New test")
-    @Test
-    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
-    @EnsureHasDeviceOwner
-    public void setUserProvisioningState_unmanagedDevice_stateUserUnmanaged_doesNotThrowIllegalStateException() {
-        sDevicePolicyManager.setUserProvisioningState(
-                DevicePolicyManager.STATE_USER_PROFILE_FINALIZED,
-                TestApis.users().current().userHandle());
-
-        assertThat(sDevicePolicyManager.getUserProvisioningState())
-                .isEqualTo(DevicePolicyManager.STATE_USER_PROFILE_FINALIZED);
-    }
-
     @Test
     public void setAdminExtras_managedProfileParams_works() {
         ManagedProfileProvisioningParams params =
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/KeyManagementTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/KeyManagementTest.java
index b985584..00cffc3 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/KeyManagementTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/KeyManagementTest.java
@@ -35,6 +35,7 @@
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.Postsubmit;
 import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
 import com.android.bedstead.harrier.annotations.enterprise.PolicyAppliesTest;
 import com.android.bedstead.harrier.policies.KeyManagement;
 import com.android.bedstead.nene.TestApis;
@@ -74,7 +75,7 @@
     @ClassRule
     @Rule
     public static final DeviceState sDeviceState = new DeviceState();
-    private static final int KEYCHAIN_CALLBACK_TIMEOUT_SECONDS = 600;
+    private static final int KEYCHAIN_CALLBACK_TIMEOUT_SECONDS = 540;
     private static final String RSA = "RSA";
     private static final String RSA_ALIAS = "com.android.test.valid-rsa-key-1";
     private static final PrivateKey PRIVATE_KEY =
@@ -220,6 +221,14 @@
         }
     }
 
+
+    @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = KeyManagement.class)
+    public void hasKeyPair_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager().hasKeyPair(RSA_ALIAS));
+    }
+
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = KeyManagement.class)
     public void hasKeyPair_nonExistentAlias_false() {
@@ -345,6 +354,14 @@
     }
 
     @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = KeyManagement.class)
+    public void getKeyPairGrants_notAllowed_throwsException() {
+        Assert.assertThrows(SecurityException.class,
+                () -> sDeviceState.dpc().devicePolicyManager()
+                        .getKeyPairGrants(RSA_ALIAS));
+    }
+
+    @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = KeyManagement.class, singleTestOnly = true)
     public void getKeyPairGrants_nonExistent_throwsIllegalArgumentException() {
         Assert.assertThrows(IllegalArgumentException.class,
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LauncherAppsTests.java b/tests/devicepolicy/src/android/devicepolicy/cts/LauncherAppsTests.java
index a7dfc6f..865d80f 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LauncherAppsTests.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LauncherAppsTests.java
@@ -37,7 +37,7 @@
     private final LauncherApps sLauncherApps = sContext.getSystemService(LauncherApps.class);
 
     @Test
-    public void testResolveInvalidActivity_doesNotCrash() {
+    public void resolveActivity_invalid_doesNotCrash() {
         final Intent intent = new Intent();
         intent.setComponent(new ComponentName("invalidPackage", "invalidClass"));
 
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
index 3aa148e..23e4b35 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
@@ -1000,8 +1000,8 @@
                 activity.activity().startActivity(intent);
 
                 if (TestApis.activities().foregroundActivity() != null) {
-                    assertThat(TestApis.activities().foregroundActivity().pkg()).isNotEqualTo(
-                            emergencyDialerPackageName);
+                    assertThat(TestApis.activities().foregroundActivity().pkg().packageName())
+                            .isNotEqualTo(emergencyDialerPackageName);
                 }
             } finally {
                 activity.stopLockTask();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
index 975fa1a..f63cc59 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
@@ -94,14 +94,14 @@
 
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = LostMode.class)
-    @Ignore("b/216487148")
+    @Ignore("b/223148704")
     public void sendLostModeLocationUpdate_noTestProviders_returnFalse() throws Exception {
         sendLostModeLocationUpdate(/* expected= */ false);
     }
 
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = LostMode.class)
-    @Ignore("b/216487148")
+    @Ignore("b/223148704")
     public void sendLostModeLocationUpdate_noLocation_returnFalse() throws Exception {
         try (LocationProvider provider = TestApis.location().addLocationProvider()) {
             sendLostModeLocationUpdate(/* expected */ false);
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java
deleted file mode 100644
index d3b7087..0000000
--- a/tests/devicepolicy/src/android/devicepolicy/cts/NegativeCallAuthorizationTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.devicepolicy.cts;
-
-import static org.testng.Assert.assertThrows;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.SmallTest;
-
-import com.android.bedstead.harrier.BedsteadJUnit4;
-import com.android.bedstead.harrier.DeviceState;
-import com.android.bedstead.harrier.annotations.RequireFeature;
-
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test that certain DevicePolicyManager APIs aren't available to non-owner apps and that they throw
- * SecurityException when invoked by such apps. For most of the older APIs that accept an explicit
- * ComponentName admin argument, this is tested in android.admin.cts.DevicePolicyManagerTest by
- * passing an admin that is not owner, but for newer APIs authorization is done based on caller UID,
- * so it is critical that the app is not owner. These APIs are tested here.
- */
-@SmallTest
-@RunWith(BedsteadJUnit4.class)
-public final class NegativeCallAuthorizationTest {
-    private static final String ALIAS = "some-alias";
-    private static final Context sContext = ApplicationProvider.getApplicationContext();
-    private static final DevicePolicyManager sDpm =
-            sContext.getSystemService(DevicePolicyManager.class);
-
-    @ClassRule @Rule
-    public static final DeviceState sDeviceState = new DeviceState();
-
-    @Test
-    @RequireFeature(PackageManager.FEATURE_DEVICE_ADMIN)
-    public void testHasKeyPair_failIfNotOwner() {
-        assertThrows(SecurityException.class, () -> sDpm.hasKeyPair(ALIAS));
-    }
-
-    @Test
-    @RequireFeature(PackageManager.FEATURE_DEVICE_ADMIN)
-    public void testGetKeyPairGrants_failIfNotOwner() {
-        assertThrows(SecurityException.class, () -> sDpm.getKeyPairGrants(ALIAS));
-    }
-}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/NetworkLoggingTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/NetworkLoggingTest.java
new file mode 100644
index 0000000..0dbc45c
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/NetworkLoggingTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.devicepolicy.cts;
+
+import static com.android.bedstead.nene.permissions.CommonPermissions.INTERNET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.stats.devicepolicy.EventId;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureHasNoSecondaryUser;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.PolicyAppliesTest;
+import com.android.bedstead.harrier.policies.NetworkLogging;
+import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
+import com.android.bedstead.metricsrecorder.truth.MetricQueryBuilderSubject;
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.permissions.PermissionContext;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+// These tests currently only cover checking that the appropriate methods are callable. They should
+// be replaced with more complete tests once the other network logging tests are ready to be
+// migrated to the new infrastructure
+@RunWith(BedsteadJUnit4.class)
+public final class NetworkLoggingTest {
+
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final String[] URL_LIST = {
+            "example.edu",
+            "google.co.jp",
+            "google.fr",
+            "google.com.br",
+            "google.com.tr",
+            "google.co.uk",
+            "google.de"
+    };
+
+    @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = NetworkLogging.class)
+    public void isNetworkLoggingEnabled_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> sDeviceState.dpc().devicePolicyManager()
+                .isNetworkLoggingEnabled(sDeviceState.dpc().componentName()));
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = NetworkLogging.class)
+    @EnsureHasNoSecondaryUser
+    public void isNetworkLoggingEnabled_networkLoggingIsEnabled_returnsTrue() throws Exception {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), true);
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().isNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName())).isTrue();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), false);
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = NetworkLogging.class)
+    public void isNetworkLoggingEnabled_networkLoggingIsNotEnabled_returnsFalse() throws Exception {
+        sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                sDeviceState.dpc().componentName(), false);
+
+        assertThat(sDeviceState.dpc().devicePolicyManager().isNetworkLoggingEnabled(
+                sDeviceState.dpc().componentName())).isFalse();
+    }
+
+    @Postsubmit(reason = "new test")
+    @PolicyAppliesTest(policy = NetworkLogging.class)
+    public void setNetworkLoggingEnabled_networkLoggingIsEnabled() throws Exception {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), true);
+            for (String url : URL_LIST) {
+                connectToWebsite(url);
+            }
+
+            TestApis.devicePolicy().forceNetworkLogs();
+
+            long batchToken = waitForBatchToken();
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().retrieveNetworkLogs(
+                    sDeviceState.dpc().componentName(), batchToken)).isNotEmpty();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), false);
+        }
+    }
+
+    private long waitForBatchToken() {
+        if (sDeviceState.dpc().isDelegate()) {
+            return sDeviceState.dpc().events().delegateNetworkLogsAvailable()
+                    .waitForEvent().batchToken();
+        } else {
+            return sDeviceState.dpc().events().networkLogsAvailable().waitForEvent().batchToken();
+        }
+    }
+
+    private void connectToWebsite(String server) throws Exception {
+        try (PermissionContext p = TestApis.permissions().withPermission(INTERNET)) {
+            final URL url = new URL("http://" + server);
+            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+            try {
+                urlConnection.setConnectTimeout(2000);
+                urlConnection.setReadTimeout(2000);
+                urlConnection.getResponseCode();
+            } finally {
+                urlConnection.disconnect();
+            }
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = NetworkLogging.class)
+    public void setNetworkLoggingEnabled_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> sDeviceState.dpc().devicePolicyManager()
+                .setNetworkLoggingEnabled(sDeviceState.dpc().componentName(), true));
+    }
+
+    @Postsubmit(reason = "new test")
+    @CannotSetPolicyTest(policy = NetworkLogging.class)
+    public void retrieveNetworkLogs_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> sDeviceState.dpc().devicePolicyManager()
+                .retrieveNetworkLogs(sDeviceState.dpc().componentName(), /*batchToken= */ 0));
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = NetworkLogging.class)
+    public void setNetworkLoggingEnabled_true_logsEvent() {
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), true);
+
+            MetricQueryBuilderSubject.assertThat(metrics.query()
+                    .whereType().isEqualTo(EventId.SET_NETWORK_LOGGING_ENABLED_VALUE)
+                    .whereAdminPackageName().isEqualTo(
+                            sDeviceState.dpc().packageName())
+                            .whereBoolean().isEqualTo(sDeviceState.dpc().isDelegate())
+                            .whereInteger().isEqualTo(1) // Enabled
+                    ).wasLogged();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), false);
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = NetworkLogging.class)
+    public void setNetworkLoggingEnabled_false_logsEvent() {
+        sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                sDeviceState.dpc().componentName(), true);
+
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), false);
+
+            MetricQueryBuilderSubject.assertThat(metrics.query()
+                    .whereType().isEqualTo(EventId.SET_NETWORK_LOGGING_ENABLED_VALUE)
+                    .whereAdminPackageName().isEqualTo(
+                            sDeviceState.dpc().packageName())
+                    .whereBoolean().isEqualTo(sDeviceState.dpc().isDelegate())
+                    .whereInteger().isEqualTo(0) // Disabled
+            ).wasLogged();
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @CanSetPolicyTest(policy = NetworkLogging.class)
+    public void retrieveNetworkLogs_logsEvent() throws Exception {
+        try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), true);
+            for (String url : URL_LIST) {
+                connectToWebsite(url);
+            }
+            TestApis.devicePolicy().forceNetworkLogs();
+            long batchToken = waitForBatchToken();
+
+            sDeviceState.dpc().devicePolicyManager().retrieveNetworkLogs(
+                    sDeviceState.dpc().componentName(), batchToken);
+
+            MetricQueryBuilderSubject.assertThat(metrics.query()
+                    .whereType().isEqualTo(EventId.RETRIEVE_NETWORK_LOGS_VALUE)
+                    .whereAdminPackageName().isEqualTo(
+                            sDeviceState.dpc().packageName())
+                    .whereBoolean().isEqualTo(sDeviceState.dpc().isDelegate())
+            ).wasLogged();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setNetworkLoggingEnabled(
+                    sDeviceState.dpc().componentName(), false);
+        }
+    }
+}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PackagesTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PackagesTest.java
new file mode 100644
index 0000000..63063c8
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PackagesTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.devicepolicy.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
+import com.android.bedstead.harrier.policies.HideApplication;
+import com.android.bedstead.harrier.policies.SuspendPackage;
+import com.android.bedstead.testapp.TestApp;
+import com.android.bedstead.testapp.TestAppInstance;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public final class PackagesTest {
+
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final TestApp sTestApp = sDeviceState.testApps().any();
+    private static final TestAppInstance sTestAppInstance = sTestApp.install();
+
+    @AfterClass
+    public static void teardownClass() {
+        sTestAppInstance.uninstall();
+    }
+
+    @CanSetPolicyTest(policy = HideApplication.class)
+    @Postsubmit(reason = "new test")
+    public void isApplicationHidden_applicationIsHidden_returnsTrue() {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setApplicationHidden(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName(), true);
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().isApplicationHidden(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName())).isTrue();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setApplicationHidden(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName(), false);
+        }
+    }
+
+    @CanSetPolicyTest(policy = HideApplication.class)
+    @Postsubmit(reason = "new test")
+    public void isApplicationHidden_applicationIsNotHidden_returnsFalse() {
+        sDeviceState.dpc().devicePolicyManager().setApplicationHidden(
+                sDeviceState.dpc().componentName(), sTestApp.packageName(), false);
+
+        assertThat(sDeviceState.dpc().devicePolicyManager().isApplicationHidden(
+                sDeviceState.dpc().componentName(), sTestApp.packageName())).isFalse();
+    }
+
+    @CannotSetPolicyTest(policy = HideApplication.class)
+    @Postsubmit(reason = "new test")
+    public void isApplicationHidden_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager()
+                        .isApplicationHidden(
+                                sDeviceState.dpc().componentName(), sTestApp.packageName()));
+    }
+
+    @CannotSetPolicyTest(policy = HideApplication.class)
+    @Postsubmit(reason = "new test")
+    public void setApplicationHidden_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager()
+                        .setApplicationHidden(
+                                sDeviceState.dpc().componentName(), sTestApp.packageName(), true));
+    }
+
+    @CanSetPolicyTest(policy = SuspendPackage.class)
+    @Postsubmit(reason = "new test")
+    public void isPackageSuspended_packageIsSuspended_returnsTrue() throws Exception {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setPackagesSuspended(
+                    sDeviceState.dpc().componentName(), new String[]{sTestApp.packageName()}, true);
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().isPackageSuspended(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName())).isTrue();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setPackagesSuspended(
+                    sDeviceState.dpc().componentName(), new String[]{sTestApp.packageName()},
+                    false);
+        }
+    }
+
+    @CanSetPolicyTest(policy = SuspendPackage.class)
+    @Postsubmit(reason = "new test")
+    public void isPackageSuspended_packageIsNotSuspended_returnFalse() throws Exception {
+        sDeviceState.dpc().devicePolicyManager().setPackagesSuspended(
+                sDeviceState.dpc().componentName(), new String[]{sTestApp.packageName()}, false);
+
+        assertThat(sDeviceState.dpc().devicePolicyManager().isPackageSuspended(
+                sDeviceState.dpc().componentName(), sTestApp.packageName())).isFalse();
+    }
+
+    @CannotSetPolicyTest(policy = SuspendPackage.class)
+    @Postsubmit(reason = "new test")
+    public void isPackageSuspended_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager()
+                        .isPackageSuspended(
+                                sDeviceState.dpc().componentName(), sTestApp.packageName()));
+    }
+
+    @CannotSetPolicyTest(policy = SuspendPackage.class)
+    @Postsubmit(reason = "new test")
+    public void setPackageSuspended_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager()
+                        .setPackagesSuspended(
+                                sDeviceState.dpc().componentName(),
+                                new String[]{sTestApp.packageName()}, true));
+    }
+}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
index 522c317..6e23366 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java
@@ -29,9 +29,13 @@
 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY;
+import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_PROMPT;
 
 import static com.android.bedstead.nene.notifications.NotificationListenerQuerySubject.assertThat;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.testng.Assert.assertThrows;
@@ -39,7 +43,7 @@
 import com.android.bedstead.harrier.BedsteadJUnit4;
 import com.android.bedstead.harrier.DeviceState;
 import com.android.bedstead.harrier.annotations.AfterClass;
-import com.android.bedstead.harrier.annotations.BeforeClass;
+import com.android.bedstead.harrier.annotations.IntTestParameter;
 import com.android.bedstead.harrier.annotations.NotificationsTest;
 import com.android.bedstead.harrier.annotations.StringTestParameter;
 import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
@@ -51,7 +55,9 @@
 import com.android.bedstead.harrier.policies.SetSmsPermissionGranted;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.notifications.NotificationListener;
+import com.android.bedstead.nene.utils.Poll;
 import com.android.bedstead.testapp.TestApp;
+import com.android.bedstead.testapp.TestAppActivity;
 import com.android.bedstead.testapp.TestAppInstance;
 
 import org.junit.ClassRule;
@@ -131,12 +137,11 @@
             ).wherePermissions().doesNotContain(
                     NOT_DECLARED_PERMISSION
             ).get();
-    private static TestAppInstance sTestAppInstance;
-
-    @BeforeClass
-    public static void setupClass() {
-        sTestAppInstance = sTestApp.install(TestApis.users().instrumented());
-    }
+    private static final TestApp sNotInstalledTestApp = sDeviceState.testApps().query()
+            .wherePermissions().contains(GRANTABLE_PERMISSION)
+            .whereActivities().isNotEmpty().get();
+    private static TestAppInstance sTestAppInstance =
+            sTestApp.install(TestApis.users().instrumented());
 
     @AfterClass
     public static void teardownClass() {
@@ -331,6 +336,14 @@
         }
     }
 
+    @CannotSetPolicyTest(policy = SetPermissionGrantState.class)
+    public void grantPermission_cannotBeSet_throwsException(
+            @DeniablePermissionTestParameter String permission) {
+        assertThrows(SecurityException.class, () -> sDeviceState.dpc().devicePolicyManager()
+                .setPermissionGrantState(sDeviceState.dpc().componentName(), sTestApp.packageName(),
+                        permission, PERMISSION_GRANT_STATE_GRANTED));
+    }
+
     // TODO(b/204041462): Add test that the user can manually grant sensor permissions
 
     @CanSetPolicyTest(policy = SetPermissionGrantState.class)
@@ -503,6 +516,8 @@
         int existingGrantState = sDeviceState.dpc().devicePolicyManager()
                 .getPermissionGrantState(sDeviceState.dpc().componentName(),
                         sTestApp.packageName(), READ_SMS);
+        sTestApp.pkg().denyPermission(READ_SMS);
+
         try {
             sDeviceState.dpc().devicePolicyManager().setPermissionGrantState(
                     sDeviceState.dpc().componentName(), sTestApp.packageName(),
@@ -597,6 +612,81 @@
         }
     }
 
+    @CannotSetPolicyTest(policy = SetPermissionGrantState.class)
+    public void getPermissionGrantState_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> {
+            sDeviceState.dpc().devicePolicyManager().getPermissionGrantState(
+                    sDeviceState.dpc().componentName(), sTestApp.packageName(),
+                    GRANTABLE_PERMISSION);
+        });
+    }
+
+    @CannotSetPolicyTest(policy = SetPermissionGrantState.class)
+    public void setPermissionPolicy_notAllowed_throwsException() {
+        assertThrows(SecurityException.class, () -> {
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_AUTO_GRANT);
+        });
+    }
+
+    @CanSetPolicyTest(policy = SetPermissionGrantState.class)
+    public void setPermissionPolicy_setsPolicy(@IntTestParameter(
+            {PERMISSION_POLICY_AUTO_GRANT, PERMISSION_POLICY_AUTO_DENY}) int policy) {
+        try {
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), policy);
+
+            assertThat(sDeviceState.dpc().devicePolicyManager().getPermissionPolicy(
+                    sDeviceState.dpc().componentName())).isEqualTo(policy);
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_PROMPT);
+        }
+    }
+
+    @PolicyAppliesTest(policy = SetPermissionGrantState.class)
+    public void setPermissionPolicy_grant_automaticallyGrantsPermissions() {
+        try (TestAppInstance testApp = sNotInstalledTestApp.install()) {
+            // We install fresh so the permissions are not granted
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_AUTO_GRANT);
+
+            TestAppActivity activity = testApp.activities().any().start().activity();
+            activity.requestPermissions(new String[]{GRANTABLE_PERMISSION}, /* requestCode= */ 0);
+
+            Poll.forValue("Permission granted",
+                    () -> sNotInstalledTestApp.pkg().hasPermission(GRANTABLE_PERMISSION))
+                    .toBeEqualTo(true)
+                    .errorOnFail()
+                    .await();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_PROMPT);
+        }
+    }
+
+    @PolicyAppliesTest(policy = SetPermissionGrantState.class)
+    public void setPermissionPolicy_deny_automaticallyDeniesPermissions() {
+        try (TestAppInstance testApp = sNotInstalledTestApp.install()) {
+            // We install fresh so the permissions are not granted
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_AUTO_DENY);
+
+            TestAppActivity activity = testApp.activities().any().start().activity();
+            activity.requestPermissions(new String[]{GRANTABLE_PERMISSION}, /* requestCode= */ 0);
+
+            Poll.forValue("Permission granted",
+                    () -> sNotInstalledTestApp.pkg().hasPermission(GRANTABLE_PERMISSION))
+                    .toBeEqualTo(false)
+                    .errorOnFail()
+                    .await();
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setPermissionPolicy(
+                    sDeviceState.dpc().componentName(), PERMISSION_POLICY_PROMPT);
+        }
+    }
+
+
     @PolicyAppliesTest(policy = SetSensorPermissionGranted.class)
     @NotificationsTest
     @Ignore("TODO(198280344): Re-enable when we can set sensor permissions using device owner")
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
index 1a0dc01..38c110e 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PermitInputMethodsTest.java
@@ -106,9 +106,6 @@
                 SYSTEM_INPUT_METHODS_PACKAGES.isEmpty());
 
         List<String> enabledNonSystemImes = List.of(INPUT_METHOD_PACKAGE_NAME);
-        Set<String> permittedPlusSystem = new HashSet<>();
-        permittedPlusSystem.addAll(SYSTEM_INPUT_METHODS_PACKAGES);
-        permittedPlusSystem.addAll(enabledNonSystemImes);
 
         assertThat(sDeviceState.dpc().devicePolicyManager().setPermittedInputMethods(
                 sDeviceState.dpc().componentName(), /* packageNames= */ enabledNonSystemImes)
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
index 44abc72..a3847f1 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
@@ -55,7 +55,6 @@
 
 import org.junit.ClassRule;
 import org.junit.Rule;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 
 // TODO(b/191640667): Parameterize the length limit tests with multiple limits
@@ -92,7 +91,6 @@
     @Rule
     public static final DeviceState sDeviceState = new DeviceState();
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void setResetPasswordToken_validToken_passwordTokenSet() {
@@ -107,7 +105,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void resetPasswordWithToken_validPasswordAndToken_success() {
@@ -120,7 +117,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void resetPasswordWithToken_badToken_failure() {
@@ -129,7 +125,6 @@
                 DPC_COMPONENT_NAME, VALID_PASSWORD, BAD_TOKEN, /* flags = */ 0)).isFalse();
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void resetPasswordWithToken_noPassword_deviceIsNotSecure() {
@@ -141,7 +136,6 @@
         assertThat(sLocalKeyguardManager.isDeviceSecure()).isFalse();
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void resetPasswordWithToken_password_deviceIsSecure() {
@@ -157,7 +151,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -185,7 +178,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -214,7 +206,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void resetPasswordWithToken_validPasswordAndToken_logged() {
@@ -232,7 +223,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -262,7 +252,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -292,7 +281,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -324,7 +312,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -342,7 +329,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -364,7 +350,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -385,7 +370,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -405,7 +389,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -425,7 +408,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -452,7 +434,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     // setPasswordMinimumLength is unsupported on automotive
@@ -471,7 +452,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -498,7 +478,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     // setPasswordMinimumUpperCase is unsupported on automotive
     @RequireDoesNotHaveFeature(FEATURE_AUTOMOTIVE)
@@ -517,7 +496,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -544,7 +522,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     // setPasswordMinimumLowerCase is unsupported on automotive
     @RequireDoesNotHaveFeature(FEATURE_AUTOMOTIVE)
@@ -563,7 +540,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -590,7 +566,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void setPasswordMinimumLetters_success() {
@@ -607,7 +582,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -634,7 +608,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void setPasswordMinimumNumeric_success() {
@@ -651,7 +624,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -678,7 +650,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void setPasswordMinimumSymbols_success() {
@@ -695,7 +666,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -723,7 +693,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     // setPasswordMinimumNonLetter is unsupported on automotive
     @RequireDoesNotHaveFeature(FEATURE_AUTOMOTIVE)
@@ -742,7 +711,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -770,7 +738,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -792,7 +759,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     // setPasswordQuality is unsupported on automotive
@@ -814,7 +780,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @CanSetPolicyTest(policy = ResetPasswordWithToken.class)
     public void setRequiredPasswordComplexity_success() {
@@ -830,7 +795,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void setRequiredPasswordComplexity_low_passwordThatMeetsLowPasswordBandRequired() {
@@ -847,7 +811,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void setRequiredPasswordComplexity_medium_passwordThatMeetsMediumPasswordBandRequired() {
@@ -865,7 +828,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void setRequiredPasswordComplexity_high_passwordThatMeetsHighPasswordBandRequired() {
@@ -883,7 +845,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void getPasswordComplexity_passwordThatMeetsLowPasswordBand_lowPasswordComplexity() {
@@ -899,7 +860,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void getPasswordComplexity_passwordThatMeetsMediumPasswordBand_mediumPasswordComplexity() {
@@ -915,7 +875,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void getPasswordComplexity_passwordThatMeetsHighPasswordBand_highPasswordComplexity() {
@@ -931,7 +890,6 @@
         }
     }
 
-    @Test
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     public void clearResetPasswordToken_passwordTokenIsResetAndUnableToSetNewPassword() {
@@ -948,11 +906,10 @@
         }
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumLength_featureUnsupported_ignored() {
+    public void passwordMinimumLength_featureUnsupported_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumLength(
                 DPC_COMPONENT_NAME);
 
@@ -964,11 +921,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumNumeric_ignored() {
+    public void passwordMinimumNumeric_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumNumeric(
                 DPC_COMPONENT_NAME);
 
@@ -980,11 +936,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumLowerCase_ignored() {
+    public void passwordMinimumLowerCase_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumLowerCase(
                 DPC_COMPONENT_NAME);
 
@@ -997,11 +952,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumUpperCase_ignored() {
+    public void passwordMinimumUpperCase_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumUpperCase(
                 DPC_COMPONENT_NAME);
 
@@ -1014,11 +968,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumLetters_ignored() {
+    public void passwordMinimumLetters_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumLetters(
                 DPC_COMPONENT_NAME);
 
@@ -1030,11 +983,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumSymbols_ignored() {
+    public void passwordMinimumSymbols_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumSymbols(
                 DPC_COMPONENT_NAME);
 
@@ -1046,11 +998,10 @@
                 .isEqualTo(valueBefore);
     }
 
-    @Test
     @RequireFeature(FEATURE_AUTOMOTIVE)
     @PolicyAppliesTest(policy = ResetPasswordWithToken.class)
     @Postsubmit(reason = "new test")
-    public void testPasswordMinimumNonLetter_ignored() {
+    public void passwordMinimumNonLetter_ignored() {
         int valueBefore = sDeviceState.dpc().devicePolicyManager().getPasswordMinimumNonLetter(
                 DPC_COMPONENT_NAME);
 
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/RingtoneTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/RingtoneTest.java
index 1fb1685..a8ad777 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/RingtoneTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/RingtoneTest.java
@@ -48,8 +48,8 @@
         NOTIFICATION(Settings.System.NOTIFICATION_SOUND, RingtoneManager.TYPE_NOTIFICATION),
         ALARM(Settings.System.ALARM_ALERT, RingtoneManager.TYPE_ALARM);
 
-        String mRingtoneName;
-        int mType;
+        final String mRingtoneName;
+        final int mType;
 
         RingtoneConfig(String ringtoneName, int type) {
             this.mRingtoneName = ringtoneName;
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/SupportMessageTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/SupportMessageTest.java
index 42ebd7f..17f90a4 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/SupportMessageTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/SupportMessageTest.java
@@ -82,7 +82,7 @@
     public void setShortSupportMessage_validText_works() {
         mDevicePolicyManager.setShortSupportMessage(mAdmin, VALID_SUPPORT_MESSAGE);
 
-        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin).toString())
                 .isEqualTo(VALID_SUPPORT_MESSAGE);
     }
 
@@ -91,7 +91,7 @@
     public void setLongSupportMessage_validText_works() {
         mDevicePolicyManager.setLongSupportMessage(mAdmin, VALID_SUPPORT_MESSAGE);
 
-        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin).toString())
                 .isEqualTo(VALID_SUPPORT_MESSAGE);
     }
 
@@ -100,7 +100,7 @@
     public void setShortSupportMessage_emptyText_works() {
         mDevicePolicyManager.setShortSupportMessage(mAdmin, EMPTY_SUPPORT_MESSAGE);
 
-        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin).toString())
                 .isEqualTo(EMPTY_SUPPORT_MESSAGE);
     }
 
@@ -110,7 +110,7 @@
         mDevicePolicyManager.setLongSupportMessage(mAdmin, VALID_SUPPORT_MESSAGE);
         mDevicePolicyManager.setLongSupportMessage(mAdmin, /* charSequence= */ null);
 
-        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin)).isEqualTo("null");
+        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin).toString()).isEqualTo("null");
     }
 
     @PolicyAppliesTest(policy = SupportMessage.class)
@@ -119,7 +119,8 @@
         mDevicePolicyManager.setShortSupportMessage(mAdmin, VALID_SUPPORT_MESSAGE);
         mDevicePolicyManager.setShortSupportMessage(mAdmin, /* charSequence= */ null);
 
-        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin)).isEqualTo("null");
+        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin).toString())
+                .isEqualTo("null");
     }
 
     @PolicyAppliesTest(policy = SupportMessage.class)
@@ -127,7 +128,7 @@
     public void setLongSupportMessage_emptyText_works() {
         mDevicePolicyManager.setLongSupportMessage(mAdmin, EMPTY_SUPPORT_MESSAGE);
 
-        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getLongSupportMessage(mAdmin).toString())
                 .isEqualTo(EMPTY_SUPPORT_MESSAGE);
     }
 
@@ -136,7 +137,7 @@
     public void setShortSupportMessage_tooLongText_isTruncated() {
         mDevicePolicyManager.setShortSupportMessage(mAdmin, SHORT_SUPPORT_MESSAGE_TOO_LONG);
 
-        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin).toString())
                 .isEqualTo(SHORT_SUPPORT_MESSAGE_TOO_LONG_TRUNCATED);
     }
 
@@ -145,7 +146,7 @@
     public void setLongSupportMessage_longText_notTruncated() {
         mDevicePolicyManager.setShortSupportMessage(mAdmin, LONG_SUPPORT_MESSAGE_REASONABLY_LONG);
 
-        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin))
+        assertThat(mDevicePolicyManager.getShortSupportMessage(mAdmin).toString())
                 .isEqualTo(LONG_SUPPORT_MESSAGE_REASONABLY_LONG);
     }
 
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/SystemAppTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/SystemAppTest.java
new file mode 100644
index 0000000..3b9ecc0
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/SystemAppTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.devicepolicy.cts;
+
+import static org.testng.Assert.assertThrows;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.AfterClass;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.CanSetPolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.CannotSetPolicyTest;
+import com.android.bedstead.harrier.policies.EnableSystemApp;
+import com.android.bedstead.testapp.TestApp;
+import com.android.bedstead.testapp.TestAppInstance;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public final class SystemAppTest {
+
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final TestApp sTestApp = sDeviceState.testApps().any();
+    private static final TestAppInstance sTestAppInstance = sTestApp.install();
+
+    @AfterClass
+    public static void teardownClass() {
+        sTestAppInstance.uninstall();
+    }
+
+    @CanSetPolicyTest(policy = EnableSystemApp.class)
+    @Postsubmit(reason = "new test")
+    public void enableSystemApp_nonSystemApp_throwsException() {
+        assertThrows(IllegalArgumentException.class,
+                () -> sDeviceState.dpc().devicePolicyManager().enableSystemApp(
+                        sDeviceState.dpc().componentName(), sTestApp.packageName()));
+    }
+
+    @CannotSetPolicyTest(policy = EnableSystemApp.class)
+    @Postsubmit(reason = "new test")
+    public void enableSystemApp_notAllowed_throwsException() {
+        assertThrows(SecurityException.class,
+                () -> sDeviceState.dpc().devicePolicyManager().enableSystemApp(
+                        sDeviceState.dpc().componentName(), sTestApp.packageName()));
+    }
+}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index 716db8d..d07c3ce 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -174,15 +174,31 @@
         // Third case above. Since the deprecated API is intended to allow credential in addition
         // to biometrics, we should be receiving BIOMETRIC_ERROR_NO_BIOMETRICS.
         final boolean noSensors = mSensorProperties.isEmpty();
+        int expectedError;
+        if (noSensors) {
+            expectedError = BiometricPrompt.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL;
+        } else if (hasOnlyConvenienceSensors()) {
+            expectedError = BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT;
+        } else {
+            expectedError = BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS;
+        }
         callback = mock(BiometricPrompt.AuthenticationCallback.class);
         showDeviceCredentialAllowedBiometricPrompt(callback, new CancellationSignal(),
                 false /* shouldShow */);
         verify(callback).onAuthenticationError(
-                eq(noSensors ? BiometricPrompt.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL
-                        : BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS),
+                eq(expectedError),
                 any());
     }
 
+    private boolean hasOnlyConvenienceSensors() {
+        for (SensorProperties sensor : mSensorProperties) {
+            if (sensor.getSensorStrength() != SensorProperties.STRENGTH_CONVENIENCE) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * When device credential is enrolled, check the behavior for
      * 1) BiometricManager#canAuthenticate(DEVICE_CREDENTIAL)
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 9eb7bac..91be9196 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -538,6 +538,10 @@
                   android:exported="true"/>
         <activity android:name="android.server.wm.PinnedStackTests$TestActivity"
                   android:exported="true"/>
+        <activity android:name="android.server.wm.TaskFragmentTrustedModeTest$TranslucentActivity"
+                  android:exported="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"
+                  android:theme="@android:style/Theme.Translucent.NoTitleBar" />
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
index d8c804f..59194c6 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
@@ -18,50 +18,33 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.server.wm.jetpack.utils.ExtensionUtil.MINIMUM_EXTENSION_VERSION;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assertEqualWindowLayoutInfo;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeHasDisplayFeatures;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutComponent;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getExtensionWindowLayoutInfo;
-import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
-import static android.server.wm.jetpack.utils.ExtensionUtil.isExtensionVersionValid;
 import static android.server.wm.jetpack.utils.SidecarUtil.assumeSidecarSupportedDevice;
 import static android.server.wm.jetpack.utils.SidecarUtil.getSidecarInterface;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.areExtensionAndSidecarDeviceStateEqual;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.assertNotBothDimensionsZero;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.assertHasNonNegativeDimensions;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.doesDisplayRotateForOrientation;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityWindowToken;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.setActivityOrientationActivityDoesNotHandleOrientationChanges;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.setActivityOrientationActivityHandlesOrientationChanges;
+
+import static androidx.window.extensions.layout.FoldingFeature.STATE_FLAT;
+import static androidx.window.extensions.layout.FoldingFeature.STATE_HALF_OPENED;
+import static androidx.window.extensions.layout.FoldingFeature.TYPE_FOLD;
+import static androidx.window.extensions.layout.FoldingFeature.TYPE_HINGE;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeNotNull;
-import static org.junit.Assume.assumeTrue;
 
-import static androidx.window.extensions.layout.FoldingFeature.TYPE_FOLD;
-import static androidx.window.extensions.layout.FoldingFeature.TYPE_HINGE;
-import static androidx.window.extensions.layout.FoldingFeature.STATE_FLAT;
-import static androidx.window.extensions.layout.FoldingFeature.STATE_HALF_OPENED;
-
-import android.app.Activity;
 import android.graphics.Rect;
-import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
+import android.platform.test.annotations.Presubmit;
 import android.server.wm.jetpack.utils.TestActivity;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 import android.server.wm.jetpack.utils.TestValueCountConsumer;
-import android.platform.test.annotations.Presubmit;
+import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
 
-import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 import androidx.window.extensions.layout.DisplayFeature;
@@ -78,7 +61,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Collections;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
@@ -111,6 +93,41 @@
         assumeNotNull(mWindowLayoutComponent);
     }
 
+    /**
+     * Test adding and removing a window layout change listener.
+     */
+    @Test
+    public void testWindowLayoutComponent_onWindowLayoutChangeListener() throws Exception {
+        // Set activity to portrait
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+                ORIENTATION_PORTRAIT);
+
+        // Create the callback, onWindowLayoutChanged should only be called twice in this
+        // test, not the third time when the orientation will change because the listener will be
+        // removed.
+        TestValueCountConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
+                new TestValueCountConsumer<>();
+        windowLayoutInfoConsumer.setCount(2);
+
+        // Add window layout listener for mWindowToken - onWindowLayoutChanged should be called
+        mWindowLayoutComponent.addWindowLayoutInfoListener(mActivity, windowLayoutInfoConsumer);
+
+        // Change the activity orientation - onWindowLayoutChanged should be called
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+                ORIENTATION_LANDSCAPE);
+
+        // Remove the listener
+        mWindowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
+
+        // Change the activity orientation - onWindowLayoutChanged should NOT be called
+        setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+                ORIENTATION_PORTRAIT);
+
+        // Check that the countdown is zero
+        WindowLayoutInfo lastValue = windowLayoutInfoConsumer.waitAndGet();
+        assertNotNull(lastValue);
+    }
+
     @Test
     public void testWindowLayoutComponent_WindowLayoutInfoListener() {
         TestValueCountConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index 3cd15d8..0fda662 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -38,6 +38,7 @@
 import android.server.wm.cts.R;
 import android.view.Gravity;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.RelativeLayout;
@@ -45,6 +46,8 @@
 
 import androidx.test.filters.FlakyTest;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -56,6 +59,7 @@
 @Presubmit
 @FlakyTest(detail = "Promote once confirmed non-flaky")
 public class KeepClearRectsTests extends WindowManagerTestBase {
+    private static final long FOCUS_VIEW_CHECK_TIMEOUT = 3000;
     private static final List<Rect> TEST_KEEP_CLEAR_RECTS =
             Arrays.asList(new Rect(0, 0, 25, 25),
                           new Rect(30, 0, 50, 25),
@@ -319,6 +323,38 @@
     }
 
     @Test
+    public void testFocusedViewDeclaredAsKeepClearArea() throws Exception {
+        int preferKeepClearForFocusDelay = ViewConfiguration.get(
+                mContext).getPreferKeepClearForFocusDelay();
+
+        assumeTrue(preferKeepClearForFocusDelay >= 0);
+
+        mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
+        final TestActivity activity = mTestSession.getActivity();
+
+        final Rect viewBounds = new Rect(0, 0, 60, 60);
+        final View v = createTestViewInActivity(activity, viewBounds);
+        assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+
+        mTestSession.runOnMainSyncAndWait(() -> {
+            v.setFocusable(true);
+            v.requestFocus();
+        });
+
+        PollingCheck.check("Expected focused view bounds as keep clear area",
+                preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+                () -> hasSameElements(
+                        getRectsInScreenSpace(Arrays.asList(viewBounds),
+                                activity.getComponentName()),
+                        getKeepClearRectsForActivity(activity)));
+
+        mTestSession.runOnMainSyncAndWait(() -> v.setFocusable(false));
+        PollingCheck.check("Expected no keep clear areas after clearing focus, but found some",
+                preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+                () -> hasSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity)));
+    }
+
+    @Test
     public void testKeepClearRectsGetTranslatedToWindowSpace() {
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
         final TestActivity activity = mTestSession.getActivity();
@@ -353,12 +389,14 @@
             v.setPreferKeepClear(false);
             v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
         });
-        assertSameElements(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName),
+        List<Rect> expectedRectsInScreenSpace =
+                getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName);
+        assertSameElements(expectedRectsInScreenSpace,
                            getKeepClearRectsForActivity(activity));
 
         activity.finishAndRemoveTask();
         assertTrue(Collections.disjoint(
-                getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName),
+                expectedRectsInScreenSpace,
                 getKeepClearRectsOnDefaultDisplay()));
     }
 
@@ -374,7 +412,7 @@
         assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds), componentName),
                            getKeepClearRectsForActivity(activity));
 
-        final String title = "KeepCleasrRectsTestWindow";
+        final String title = "KeepClearRectsTestWindow";
         mTestSession.runOnMainSyncAndWait(() -> {
             final View testView = new View(activity);
             testView.setPreferKeepClear(true);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index ca205fd..defe2de 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -334,13 +334,13 @@
                 extraString(EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(2)),
                 extraString(EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(1)),
                 extraString(EXTRA_EXPANDED_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(1)),
-                extraString(EXTRA_EXPANDED_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(5)));
+                extraString(EXTRA_EXPANDED_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(4)));
         // Wait for animation complete since we are comparing aspect ratio
         waitForEnterPipAnimationComplete(PIP_ACTIVITY);
         assertPinnedStackExists();
         // Assert that we have entered PIP and that the aspect ratio is correct
         final Rect bounds = getPinnedStackBounds();
-        assertFloatEquals((float) bounds.width() / bounds.height(), (float) 1.0f / 5.0f);
+        assertFloatEquals((float) bounds.width() / bounds.height(), (float) 1.0f / 4.0f);
     }
 
     @Test
@@ -515,16 +515,16 @@
     }
 
     @Test
-    public void testPreferDockBigOverlaysWithExpandedPip() {
-        testPreferDockBigOverlaysWithExpandedPip(true);
+    public void testShouldDockBigOverlaysWithExpandedPip() {
+        testShouldDockBigOverlaysWithExpandedPip(true);
     }
 
     @Test
-    public void testNotPreferDockBigOverlaysWithExpandedPip() {
-        testPreferDockBigOverlaysWithExpandedPip(false);
+    public void testShouldNotDockBigOverlaysWithExpandedPip() {
+        testShouldDockBigOverlaysWithExpandedPip(false);
     }
 
-    private void testPreferDockBigOverlaysWithExpandedPip(boolean preferDock) {
+    private void testShouldDockBigOverlaysWithExpandedPip(boolean shouldDock) {
         assumeTrue(supportsExpandedPip());
         TestActivitySession<TestActivity> testSession = createManagedTestActivitySession();
         final Intent intent = new Intent(mContext, TestActivity.class);
@@ -541,7 +541,7 @@
         waitForEnterPipAnimationComplete(PIP_ACTIVITY);
         assertPinnedStackExists();
 
-        testSession.runOnMainSyncAndWait(() -> activity.setPreferDockBigOverlays(preferDock));
+        testSession.runOnMainSyncAndWait(() -> activity.setShouldDockBigOverlays(shouldDock));
 
         mWmState.assertResumedActivity("Activity must be resumed", activity.getComponentName());
         assertPinnedStackExists();
@@ -549,8 +549,15 @@
             final Task task = mWmState.getTaskByActivity(activity.getComponentName());
             final TaskInfo info = mTaskOrganizer.getTaskInfo(task.getTaskId());
 
-            assertEquals(preferDock, info.getPreferDockBigOverlays());
+            assertEquals(shouldDock, info.shouldDockBigOverlays());
         });
+
+        final boolean[] actual = new boolean[] {!shouldDock};
+        testSession.runOnMainSyncAndWait(() -> {
+            actual[0] = activity.shouldDockBigOverlays();
+        });
+
+        assertEquals(shouldDock, actual[0]);
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index 4cf56b9..35beba0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -23,13 +23,11 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.Intent.ACTION_MAIN;
-import static android.content.Intent.CATEGORY_HOME;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.CliIntentExtra.extraBool;
 import static android.server.wm.CliIntentExtra.extraString;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.app.Components.HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY;
-import static android.server.wm.app.Components.HOME_ACTIVITY;
 import static android.server.wm.app.Components.SPLASHSCREEN_ACTIVITY;
 import static android.server.wm.app.Components.SPLASH_SCREEN_REPLACE_ICON_ACTIVITY;
 import static android.server.wm.app.Components.SPLASH_SCREEN_REPLACE_THEME_ACTIVITY;
@@ -128,21 +126,15 @@
         mWmState.setSanityCheckWithFocusedWindow(true);
     }
 
-    private CommandSession.ActivitySession prepareTestLauncher() {
-        createManagedHomeActivitySession(HOME_ACTIVITY);
+    /**
+     * @return The starter activity session to start the test activity
+     */
+    private CommandSession.ActivitySession prepareTestStarter() {
         return createManagedActivityClientSession()
-                .startActivity(new Intent(ACTION_MAIN)
-                        .addCategory(CATEGORY_HOME)
-                        .addFlags(FLAG_ACTIVITY_NEW_TASK)
-                        .setComponent(HOME_ACTIVITY));
+                .startActivity(getLaunchActivityBuilder().setUseInstrumentation());
     }
 
-    private void startActivityFromTestLauncher(CommandSession.ActivitySession homeActivity,
-            ComponentName componentName, Consumer<Intent> fillExtra) {
-        startActivityFromTestLauncher(homeActivity, componentName, fillExtra, null /* options */);
-    }
-
-    private void startActivitiesFromTestLauncher(CommandSession.ActivitySession homeActivity,
+    private void startActivitiesFromStarter(CommandSession.ActivitySession starter,
             Intent[] intents, ActivityOptions options) {
 
         final Bundle data = new Bundle();
@@ -150,10 +142,10 @@
         if (options != null) {
             data.putParcelable(EXTRA_OPTION, options.toBundle());
         }
-        homeActivity.sendCommand(COMMAND_START_ACTIVITIES, data);
+        starter.sendCommand(COMMAND_START_ACTIVITIES, data);
     }
 
-    private void startActivityFromTestLauncher(CommandSession.ActivitySession homeActivity,
+    private void startActivityFromStarter(CommandSession.ActivitySession starter,
             ComponentName componentName, Consumer<Intent> fillExtra, ActivityOptions options) {
 
         final Bundle data = new Bundle();
@@ -165,7 +157,7 @@
         if (options != null) {
             data.putParcelable(EXTRA_OPTION, options.toBundle());
         }
-        homeActivity.sendCommand(COMMAND_START_ACTIVITY, data);
+        starter.sendCommand(COMMAND_START_ACTIVITY, data);
     }
 
     @Test
@@ -174,7 +166,14 @@
         // applied insets by system bars in AAOS.
         assumeFalse(isCar());
 
-        launchActivityNoWait(SPLASHSCREEN_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
+        final CommandSession.ActivitySession starter = prepareTestStarter();
+        final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
+        noIconOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        // launch from app with no-icon options
+        startActivityFromStarter(starter, SPLASHSCREEN_ACTIVITY,
+                intent -> {}, noIconOptions);
         // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
         testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
     }
@@ -186,7 +185,13 @@
         assumeFalse(isCar());
         assumeTrue(supportsFreeform());
 
-        launchActivityNoWait(SPLASHSCREEN_ACTIVITY, WINDOWING_MODE_FREEFORM);
+        final CommandSession.ActivitySession starter = prepareTestStarter();
+        final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
+        noIconOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+        // launch from app with no-icon options
+        startActivityFromStarter(starter, SPLASHSCREEN_ACTIVITY,
+                intent -> {}, noIconOptions);
         // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
         testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
     }
@@ -373,12 +378,11 @@
     private void launchRuntimeHandleExitAnimationActivity(boolean extraOnCreate,
             boolean extraOnResume, boolean extraCancel, boolean expectResult) throws Exception {
         TestJournalProvider.TestJournalContainer.start();
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
-        startActivityFromTestLauncher(homeActivity, HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY, intent -> {
-            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, extraOnCreate);
-            intent.putExtra(REQUEST_HANDLE_EXIT_ON_RESUME, extraOnResume);
-            intent.putExtra(CANCEL_HANDLE_EXIT, extraCancel);
-        });
+
+        launchActivityNoWait(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY,
+                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, extraOnCreate),
+                extraBool(REQUEST_HANDLE_EXIT_ON_RESUME, extraOnResume),
+                extraBool(CANCEL_HANDLE_EXIT, extraCancel));
 
         mWmState.computeState(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY);
         mWmState.assertVisibility(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY, true);
@@ -420,8 +424,15 @@
         // applied insets by system bars in AAOS.
         assumeFalse(isCar());
 
-        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
-                extraBool(DELAY_RESUME, true));
+        final CommandSession.ActivitySession starter = prepareTestStarter();
+        final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
+        noIconOptions.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        // launch from app with no-icon options
+        startActivityFromStarter(starter, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
+                intent -> intent.putExtra(DELAY_RESUME, true), noIconOptions);
+
         testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
@@ -432,20 +443,25 @@
         assumeFalse(isCar());
         assumeTrue(supportsFreeform());
 
-        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, WINDOWING_MODE_FREEFORM,
-                extraBool(DELAY_RESUME, true));
+        final CommandSession.ActivitySession starter = prepareTestStarter();
+        final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
+        noIconOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+
+        // launch from app with no-icon options
+        startActivityFromStarter(starter, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
+                intent -> intent.putExtra(DELAY_RESUME, true), noIconOptions);
+
         testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
     @Test
     public void testHandleExitIconAnimatingActivity() throws Exception {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
-        TestJournalProvider.TestJournalContainer.start();
 
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent -> {
-            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true);
-        });
+        TestJournalProvider.TestJournalContainer.start();
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
+                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, true));
         mWmState.computeState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY);
         mWmState.assertVisibility(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, true);
 
@@ -456,12 +472,12 @@
     @Test
     public void testCancelHandleExitIconAnimatingActivity() {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+
         TestJournalProvider.TestJournalContainer.start();
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent -> {
-            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true);
-            intent.putExtra(CANCEL_HANDLE_EXIT, true);
-        });
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
+                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, true),
+                extraBool(CANCEL_HANDLE_EXIT, true));
+
         mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, STATE_RESUMED);
         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
 
@@ -511,13 +527,13 @@
     }
 
     @Test
-    public void testLaunchFromLauncherWithSolidColorOptions() throws Exception {
+    public void testLaunchWithSolidColorOptions() throws Exception {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+        final CommandSession.ActivitySession starter = prepareTestStarter();
         TestJournalProvider.TestJournalContainer.start();
         final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
                 .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent ->
+        startActivityFromStarter(starter, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent ->
                 intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true), noIconOptions);
         mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, STATE_RESUMED);
         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
@@ -544,13 +560,13 @@
                 true /* containsBranding */, false /* iconAnimatable */);
     }
 
-    private void launchActivitiesFromLauncherWithOptions(Intent[] intents,
+    private void launchActivitiesFromStarterWithOptions(Intent[] intents,
             ActivityOptions options, ComponentName waitResumeComponent) {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+        final CommandSession.ActivitySession starter = prepareTestStarter();
         TestJournalProvider.TestJournalContainer.start();
 
-        startActivitiesFromTestLauncher(homeActivity, intents, options);
+        startActivitiesFromStarter(starter, intents, options);
 
         mWmState.waitForActivityState(waitResumeComponent, STATE_RESUMED);
         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
@@ -566,7 +582,7 @@
                 new Intent().setComponent(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY)
                         .putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true)
         };
-        launchActivitiesFromLauncherWithOptions(intents, options,
+        launchActivitiesFromStarterWithOptions(intents, options,
                 SPLASH_SCREEN_REPLACE_ICON_ACTIVITY);
         assertHandleExit(REPLACE_ICON_EXIT, true /* containsIcon */, false /* containsBranding */,
                 true /* iconAnimatable */);
@@ -584,7 +600,7 @@
                 new Intent().setComponent(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY)
                         .putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true)
         };
-        launchActivitiesFromLauncherWithOptions(intents, options,
+        launchActivitiesFromStarterWithOptions(intents, options,
                 SPLASH_SCREEN_REPLACE_ICON_ACTIVITY);
         assertHandleExit(REPLACE_ICON_EXIT, false /* containsIcon */, false /* containsBranding */,
                 false /* iconAnimatable */);
@@ -621,28 +637,31 @@
     @Test
     public void testOverrideSplashscreenTheme() {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
-
         // Pre-launch the activity to ensure status is cleared on the device
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
-                intent -> {});
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_RESUMED);
+        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
         waitAndAssertOverrideThemeColor(0 /* ignore */);
 
         // Launch the activity a first time, check that the splashscreen use the default theme,
         // and override the theme for the next launch
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
-                intent -> intent.putExtra(OVERRIDE_THEME_ENABLED, true));
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
+                extraBool(OVERRIDE_THEME_ENABLED, true));
+        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_RESUMED);
+        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
         waitAndAssertOverrideThemeColor(Color.BLUE);
 
         // Launch the activity a second time, check that the theme has been overridden and reset
         // to the default theme
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
-                intent -> {});
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_RESUMED);
+        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
         waitAndAssertOverrideThemeColor(Color.RED);
 
         // Launch the activity a third time just to check that the theme has indeed been reset.
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
-                intent -> {});
+        launchActivityNoWait(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_RESUMED);
+        mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
         waitAndAssertOverrideThemeColor(Color.BLUE);
     }
 
@@ -671,23 +690,25 @@
     @Test
     public void testDefineSplashScreenStyleFromTheme() {
         assumeFalse(isLeanBack());
-        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+        final CommandSession.ActivitySession starter = prepareTestStarter();
         final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
                 .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
 
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
+        // launch from app with sold color options
+        startActivityFromStarter(starter, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
                 intent -> {}, noIconOptions);
         waitAndAssertStyleThemeIcon(false);
 
-        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
-                intent -> {});
+        // launch from app with icon options
+        final ActivityOptions iconOptions = ActivityOptions.makeBasic()
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+        startActivityFromStarter(starter, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
+                intent -> {}, iconOptions);
         waitAndAssertStyleThemeIcon(true);
 
-        // launch from app
-        final Intent intent = new Intent(Intent.ACTION_VIEW)
-                .setComponent(SPLASH_SCREEN_STYLE_THEME_ACTIVITY)
-                .setFlags(FLAG_ACTIVITY_NEW_TASK);
-        mContext.startActivity(intent);
+        // launch from app without activity options
+        startActivityFromStarter(starter, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
+                intent -> {}, null /* options */);
         waitAndAssertStyleThemeIcon(true);
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
index 2fa3ec8..ffd7d95 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitActivityLifecycleTest.java
@@ -44,7 +44,6 @@
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
-import org.junit.Ignore;
 import org.junit.Test;
 
 /**
@@ -60,8 +59,6 @@
  */
 @Presubmit
 public class SplitActivityLifecycleTest extends TaskFragmentOrganizerTestBase {
-    private Activity mOwnerActivity;
-    private IBinder mOwnerToken;
     private final Rect mPrimaryBounds = new Rect();
     private final Rect mSideBounds = new Rect();
     private TaskFragmentRecord mTaskFragA;
@@ -72,13 +69,11 @@
     private final Intent mIntent = new Intent().setComponent(mActivityC);
 
     @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    Activity setUpOwnerActivity() {
         // Launch activities in fullscreen, otherwise, some tests fail on devices which use freeform
         // as the default windowing mode, because tests' prerequisite are that activity A, B, and C
         // need to overlay completely, but they can be partially overlay as freeform windows.
-        mOwnerActivity = startActivityInWindowingModeFullScreen(ActivityA.class);
-        mOwnerToken = getActivityToken(mOwnerActivity);
+        return startActivityInWindowingModeFullScreen(ActivityA.class);
     }
 
     /** Launch two Activities in two adjacent TaskFragments side-by-side. */
@@ -393,32 +388,6 @@
         testActivityLaunchInExpandedTaskFragmentInternal();
     }
 
-    /**
-     * Verifies the behavior to launch Activity in expanded TaskFragment and occludes the embedded
-     * Task.
-     * <p>
-     * For example, given that Activity A and B are showed side-by-side, which Activity B is in
-     * embedded Task, this test verifies the behavior to launch Activity C in the TaskFragment which
-     * fills the Task bounds of owner Activity:
-     * <pre class="prettyprint">
-     *     - Fullscreen -
-     *     TaskFragmentC
-     *       - ActivityC <---- new started Activity
-     * - Left -      - Right -
-     * TaskFragmentA TaskFragmentB
-     *   - ActivityA   - Embedded Task
-     *                   - ActivityB
-     * </pre></p>
-     */
-    @Test
-    @Ignore("b/197364677")
-    public void testActivityLaunchInExpandedTaskFragment_AboveEmbeddedTask() {
-        // Initialize test environment by launching Activity A and B side-by-side.
-        initializeSplitActivities(true /* verifyEmbeddedTask */);
-
-        testActivityLaunchInExpandedTaskFragmentInternal();
-    }
-
     private void testActivityLaunchInExpandedTaskFragmentInternal() {
 
         final TaskFragmentCreationParams fullScreenParamsC = mTaskFragmentOrganizer
@@ -444,91 +413,6 @@
     }
 
     /**
-     * Verifies the behavior to launch Activity above the embedded Task in TaskFragment.
-     * <p>
-     * For example, given that Activity A and B are showed side-by-side, which Activity B is in
-     * embedded Task, this test verifies the behavior to launch Activity C on top of the embedded
-     * Task in the same TaskFragment as Activity B:
-     * <pre class="prettyprint">
-     * - Left -      - Right -
-     * TaskFragmentA TaskFragmentB
-     *   - ActivityA   - ActivityC <---- new started Activity
-     *                 - Embedded Task
-     *                   - ActivityB
-     * </pre></p>
-     */
-    @Test
-    @Ignore("b/197364677")
-    public void testActivityLaunchAboveEmbeddedTaskInTaskFragment() {
-        // Initialize test environment by launching Activity A and B side-by-side.
-        initializeSplitActivities(true /* verifyEmbeddedTask */);
-
-        final IBinder taskFragTokenB = mTaskFragB.getTaskFragToken();
-
-        WindowContainerTransaction wct = new WindowContainerTransaction()
-                .startActivityInTaskFragment(taskFragTokenB, mOwnerToken, mIntent,
-                        null /* activityOptions */);
-
-        mTaskFragmentOrganizer.applyTransaction(wct);
-
-        mTaskFragmentOrganizer.waitForTaskFragmentInfoChanged();
-
-        final TaskFragmentInfo infoB = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragTokenB);
-
-        assertNotEmptyTaskFragment(infoB, taskFragTokenB);
-
-        waitAndAssertResumedActivity(mActivityC, "Activity C must be resumed.");
-        waitAndAssertResumedActivity(mActivityA, "Activity A must be resumed.");
-        waitAndAssertActivityState(mActivityB, WindowManagerState.STATE_STOPPED,
-                "Activity B is occluded by Activity C, so it must be stopped.");
-
-        final TaskFragment taskFragmentB = mWmState.getTaskFragmentByActivity(mActivityB);
-        assertWithMessage("TaskFragmentB must contain Activity C")
-                .that(taskFragmentB.mActivities).containsExactly(mWmState.getActivity(mActivityC));
-    }
-
-    /**
-     * Verifies the behavior to launch Activity to the embedded Task in TaskFragment.
-     * <p>
-     * For example, given that Activity A and B are showed side-by-side, which Activity B is in
-     * embedded Task, this test verifies the behavior to launch Activity C to the embedded Task
-     * and on top of Activity B:
-     * <pre class="prettyprint">
-     * - Left -      - Right -
-     * TaskFragmentA TaskFragmentB
-     *   - ActivityA   - Embedded Task
-     *                   - ActivityC <---- new started Activity
-     *                   - ActivityB
-     * </pre></p>
-     */
-    @Test
-    @Ignore("b/197364677")
-    public void testActivityLaunchToEmbeddedTaskInTaskFragment() {
-        // Initialize test environment by launching Activity A and B side-by-side.
-        initializeSplitActivities(true /* verifyEmbeddedTask */);
-
-        final IBinder taskFragTokenB = mTaskFragB.getTaskFragToken();
-        // Make Activity C launch to the embedded Task.
-        final Intent intent = new Intent(mIntent).addFlags(FLAG_ACTIVITY_NEW_TASK);
-
-        WindowContainerTransaction wct = new WindowContainerTransaction()
-                .startActivityInTaskFragment(taskFragTokenB, mOwnerToken, intent,
-                        null /* activityOptions */);
-
-        mTaskFragmentOrganizer.applyTransaction(wct);
-
-        waitAndAssertResumedActivity(mActivityC, "Activity C must be resumed.");
-        waitAndAssertResumedActivity(mActivityA, "Activity A must be resumed.");
-        waitAndAssertActivityState(mActivityB, STATE_STOPPED,
-                "Activity B is occluded by Activity C, so it must be stopped.");
-
-        final Task embeddedTask = mWmState.getTaskByActivity(mActivityB);
-        assertWithMessage("Embedded Task must contain Activity B and Activity C")
-                .that(embeddedTask.mActivities).containsExactly(mWmState.getActivity(mActivityB),
-                mWmState.getActivity(mActivityC));
-    }
-
-    /**
      * Verifies the show-when-locked behavior while launch embedded activities. Don't show the
      * embedded activities even if one of Activity has showWhenLocked flag.
      */
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java
index b1975db..d6728f41 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java
@@ -24,6 +24,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -78,6 +79,25 @@
 
     @Test
     public void startActivityValidUser() throws Throwable {
+        verifyStartActivityAsValidUser(false /* withOptions */);
+    }
+
+    @Test
+    public void startActivityInvalidUser() {
+        verifyStartActivityAsInvalidUser(false /* withOptions */);
+    }
+
+    @Test
+    public void startActivityAsValidUserWithOptions() throws Throwable {
+        verifyStartActivityAsValidUser(true /* withOptions */);
+    }
+
+    @Test
+    public void startActivityAsInvalidUserWithOptions() {
+        verifyStartActivityAsInvalidUser(true /* withOptions */);
+    }
+
+    private void verifyStartActivityAsValidUser(boolean withOptions) throws Throwable {
         int[] secondUser= {-1};
         CountDownLatch latch = new CountDownLatch(1);
         RemoteCallback cb = new RemoteCallback((Bundle result) -> {
@@ -102,7 +122,12 @@
 
         try {
             runWithShellPermissionIdentity(() -> {
-                mContext.startActivityAsUser(intent, secondUserHandle);
+                if (withOptions) {
+                    mContext.startActivityAsUser(intent, ActivityOptions.makeBasic().toBundle(),
+                            secondUserHandle);
+                } else {
+                    mContext.startActivityAsUser(intent, secondUserHandle);
+                }
                 mAm.switchUser(secondUserHandle);
                 try {
                     latch.await(5, TimeUnit.SECONDS);
@@ -120,8 +145,7 @@
         returnToOriginalUserLatch.await(20, TimeUnit.SECONDS);
     }
 
-    @Test
-    public void startActivityInvalidUser() {
+    private void verifyStartActivityAsInvalidUser(boolean withOptions) {
         UserHandle secondUserHandle = UserHandle.of(mSecondUserId * 100);
         int[] stackId = {-1};
 
@@ -129,7 +153,12 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         runWithShellPermissionIdentity(() -> {
-            mContext.startActivityAsUser(intent, secondUserHandle);
+            if (withOptions) {
+                mContext.startActivityAsUser(intent, ActivityOptions.makeBasic().toBundle(),
+                        secondUserHandle);
+            } else {
+                mContext.startActivityAsUser(intent, secondUserHandle);
+            }
             WindowManagerState amState = mAmWmState;
             amState.computeState();
             ComponentName componentName = ComponentName.createRelative(PACKAGE, CLASS);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
index 9f8d6e0..318e6f7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerPolicyTest.java
@@ -19,7 +19,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.TaskFragmentOrganizerTestBase.assertEmptyTaskFragment;
-import static android.server.wm.TaskFragmentOrganizerTestBase.assertNotEmptyTaskFragment;
 import static android.server.wm.TaskFragmentOrganizerTestBase.getActivityToken;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
@@ -53,7 +52,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -177,16 +175,10 @@
     }
 
     /**
-     * Verifies the behavior to start Activity from another process in a new created Task under
-     * TaskFragment with {@link android.permission#ACTIVITY_EMBEDDING}.
-     * <p>
-     * If the application to start Activity holds the permission, the activity is allowed to start
-     * on the Task. Otherwise, the TaskFragment should remain empty.
-     * </p>
+     * Verifies the behavior to start Activity in a new created Task in TaskFragment is forbidden.
      */
     @Test
-    @Ignore("b/197364677")
-    public void testStartActivityFromAnotherProcessInEmbeddedTask() {
+    public void testStartActivityFromAnotherProcessInNewTask_ThrowException() {
         final Activity activity = startNewActivity();
         final IBinder ownerToken = getActivityToken(activity);
         final TaskFragmentCreationParams params = mTaskFragmentOrganizer.generateTaskFragParams(
@@ -209,29 +201,13 @@
 
         TaskFragmentInfo info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
 
-        // TaskFragment must remain empty because we don't hold EMBEDDING_ACTIVITY permission to
-        // launch Activity in the embedded Task.
+        // TaskFragment must remain empty because embedding activities in a new task is not allowed.
         assertEmptyTaskFragment(info, taskFragToken);
 
         mTaskFragmentOrganizer.waitForTaskFragmentError();
 
         assertThat(mTaskFragmentOrganizer.getThrowable()).isInstanceOf(SecurityException.class);
         assertThat(mTaskFragmentOrganizer.getErrorCallbackToken()).isEqualTo(errorCallbackToken);
-
-        final WindowContainerTransaction wctWithPermission = new WindowContainerTransaction()
-                .startActivityInTaskFragment(taskFragToken, ownerToken, intent,
-                        null /* activityOptions */);
-
-        NestedShellPermission.run(() -> mTaskFragmentOrganizer.applyTransaction(wctWithPermission),
-                "android.permission.ACTIVITY_EMBEDDING");
-
-        mTaskFragmentOrganizer.waitForTaskFragmentInfoChanged();
-
-        info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
-
-        // The new started Activity must be launched in the new created Task under the TaskFragment
-        // with token taskFragToken.
-        assertNotEmptyTaskFragment(info, taskFragToken);
     }
 
     /**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
index ced35b8..7d4d4f0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java
@@ -17,8 +17,9 @@
 package android.server.wm;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
+import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBEDDING_ACTIVITY;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -33,10 +34,8 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
-import android.server.wm.WindowContextTests.TestActivity;
 import android.server.wm.WindowManagerState.Task;
 import android.server.wm.WindowManagerState.TaskFragment;
-import android.server.wm.jetpack.second.Components;
 import android.view.SurfaceControl;
 import android.window.TaskFragmentCreationParams;
 import android.window.TaskFragmentInfo;
@@ -45,10 +44,7 @@
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 
-import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -62,23 +58,9 @@
  */
 @Presubmit
 public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase {
-    private Activity mOwnerActivity;
-    private IBinder mOwnerToken;
-    private ComponentName mOwnerActivityName;
-    private int mOwnerTaskId;
     private final ComponentName mLaunchingActivity = new ComponentName(mContext,
             WindowMetricsActivityTests.MetricsActivity.class);
 
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mOwnerActivity = startActivity(TestActivity.class);
-        mOwnerToken = getActivityToken(mOwnerActivity);
-        mOwnerActivityName = mOwnerActivity.getComponentName();
-        mOwnerTaskId = mOwnerActivity.getTaskId();
-    }
-
     /**
      * Verifies the behavior of
      * {@link WindowContainerTransaction#createTaskFragment(TaskFragmentCreationParams)} to create
@@ -140,7 +122,7 @@
         assertNotEmptyTaskFragment(mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken),
                 taskFragToken, mOwnerToken);
 
-        mWmState.waitForActivityState(mOwnerActivityName, WindowManagerState.STATE_RESUMED);
+        mWmState.waitForActivityState(mOwnerActivityName, STATE_RESUMED);
 
         final Task parentTask = mWmState.getTaskByActivity(mOwnerActivityName);
         final TaskFragment taskFragment = mWmState.getTaskFragmentByActivity(mOwnerActivityName);
@@ -158,7 +140,6 @@
      * Bundle)} to start Activity in TaskFragment without creating new Task.
      */
     @Test
-    @Ignore("b/197364677")
     public void testStartActivityInTaskFragment_reuseTask() {
         final TaskFragmentCreationParams params = generateTaskFragCreationParams();
         final IBinder taskFragToken = params.getFragmentToken();
@@ -173,7 +154,7 @@
         TaskFragmentInfo info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
         assertNotEmptyTaskFragment(info, taskFragToken);
 
-        mWmState.waitForActivityState(mLaunchingActivity, WindowManagerState.STATE_RESUMED);
+        mWmState.waitForActivityState(mLaunchingActivity, STATE_RESUMED);
 
         Task parentTask = mWmState.getRootTask(mOwnerActivity.getTaskId());
         TaskFragment taskFragment = mWmState.getTaskFragmentByActivity(mLaunchingActivity);
@@ -192,47 +173,6 @@
 
     /**
      * Verifies the behavior of
-     * {@link WindowContainerTransaction#startActivityInTaskFragment(IBinder, IBinder, Intent,
-     * Bundle)} to start Activity on new created Task.
-     */
-    @Test
-    @Ignore("b/197364677")
-    public void testStartActivityInTaskFragment_createNewTask() {
-        final TaskFragmentCreationParams params = generateTaskFragCreationParams();
-        final IBinder taskFragToken = params.getFragmentToken();
-        final Intent intent = new Intent()
-                .setComponent(mLaunchingActivity)
-                .addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK);
-        final WindowContainerTransaction wct = new WindowContainerTransaction()
-                .createTaskFragment(params)
-                .startActivityInTaskFragment(taskFragToken, mOwnerToken, intent,
-                        null /* activityOptions */);
-        mTaskFragmentOrganizer.applyTransaction(wct);
-
-        mTaskFragmentOrganizer.waitForTaskFragmentCreated();
-
-        TaskFragmentInfo info = mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
-        assertNotEmptyTaskFragment(info, taskFragToken);
-
-        mWmState.waitForActivityState(mLaunchingActivity, WindowManagerState.STATE_RESUMED);
-
-        Task parentTask = mWmState.getRootTask(mOwnerActivity.getTaskId());
-        TaskFragment taskFragment = mWmState.getTaskFragmentByActivity(mLaunchingActivity);
-        Task childTask = mWmState.getTaskByActivity(mLaunchingActivity);
-
-        // Assert window hierarchy must be as follows
-        // - owner Activity's Task (parentTask)
-        //   - taskFragment
-        //     - new created Task
-        //       - LAUNCHING_ACTIVITY
-        //   - owner Activity
-        assertWindowHierarchy(parentTask, taskFragment, childTask,
-                mWmState.getActivity(mLaunchingActivity));
-        assertWindowHierarchy(parentTask, mWmState.getActivity(mOwnerActivityName));
-    }
-
-    /**
-     * Verifies the behavior of
      * {@link WindowContainerTransaction#deleteTaskFragment(WindowContainerToken)} to remove
      * the organized TaskFragment.
      */
@@ -279,7 +219,7 @@
         mTaskFragmentOrganizer.applyTransaction(wct);
         mTaskFragmentOrganizer.waitForTaskFragmentCreated();
         // The activity below must be occluded and stopped.
-        waitAndAssertActivityState(mOwnerActivityName, WindowManagerState.STATE_STOPPED,
+        waitAndAssertActivityState(mOwnerActivityName, STATE_STOPPED,
                 "Activity must be stopped");
 
         // Finishing the top activity and remain the TaskFragment on top. The next top activity
@@ -310,7 +250,7 @@
     @Test
     public void testTaskFragmentConfigChange_disallowedUntrustedMode() {
         final TaskFragmentInfo taskFragmentInfo = createTaskFragment(
-                Components.SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
 
         List<WindowContainerTransaction> transactions = createConfigChangingTransactions(
                 taskFragmentInfo);
@@ -325,30 +265,6 @@
         }
     }
 
-    /**
-     * Builds, runs and waits for completion of task fragment creation transaction.
-     * @param componentName name of the activity to launch in the TF, or {@code null} if none.
-     * @return token of the created task fragment.
-     */
-    private TaskFragmentInfo createTaskFragment(@Nullable ComponentName componentName) {
-        final TaskFragmentCreationParams params = generateTaskFragCreationParams();
-        final IBinder taskFragToken = params.getFragmentToken();
-        final WindowContainerTransaction wct = new WindowContainerTransaction()
-                .createTaskFragment(params);
-        if (componentName != null) {
-            wct.startActivityInTaskFragment(taskFragToken, mOwnerToken,
-                    new Intent().setComponent(componentName), null /* activityOptions */);
-        }
-        mTaskFragmentOrganizer.applyTransaction(wct);
-        mTaskFragmentOrganizer.waitForTaskFragmentCreated();
-
-        if (componentName != null) {
-            mWmState.waitForActivityState(componentName, WindowManagerState.STATE_RESUMED);
-        }
-
-        return mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
-    }
-
     private List<WindowContainerTransaction> createConfigChangingTransactions(
             @NonNull TaskFragmentInfo taskFragmentInfo) {
         final WindowContainerToken wct = taskFragmentInfo.getToken();
@@ -367,9 +283,4 @@
 
         return transactionList;
     }
-
-    @NonNull
-    private TaskFragmentCreationParams generateTaskFragCreationParams() {
-        return mTaskFragmentOrganizer.generateTaskFragParams(mOwnerToken);
-    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTestBase.java
index 34a16a5..6edbc9a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTestBase.java
@@ -17,6 +17,7 @@
 package android.server.wm;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -24,10 +25,13 @@
 import static org.junit.Assert.fail;
 
 import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.IBinder;
+import android.server.wm.WindowContextTests.TestActivity;
 import android.server.wm.WindowManagerState.WindowContainer;
 import android.util.ArrayMap;
 import android.window.TaskFragmentCreationParams;
@@ -48,6 +52,10 @@
 
 public class TaskFragmentOrganizerTestBase extends WindowManagerTestBase {
     public BasicTaskFragmentOrganizer mTaskFragmentOrganizer;
+    Activity mOwnerActivity;
+    IBinder mOwnerToken;
+    ComponentName mOwnerActivityName;
+    int mOwnerTaskId;
 
     @Before
     @Override
@@ -55,6 +63,17 @@
         super.setUp();
         mTaskFragmentOrganizer = new BasicTaskFragmentOrganizer();
         mTaskFragmentOrganizer.registerOrganizer();
+        mOwnerActivity = setUpOwnerActivity();
+        mOwnerToken = getActivityToken(mOwnerActivity);
+        mOwnerActivityName = mOwnerActivity.getComponentName();
+        mOwnerTaskId = mOwnerActivity.getTaskId();
+    }
+
+    /** Setups the owner activity of the organized TaskFragment. */
+    Activity setUpOwnerActivity() {
+        // Launch activities in fullscreen in case the device may use freeform as the default
+        // windowing mode.
+        return startActivityInWindowingModeFullScreen(TestActivity.class);
     }
 
     @After
@@ -121,6 +140,50 @@
         }
     }
 
+    /**
+     * Builds, runs and waits for completion of task fragment creation transaction.
+     * @param componentName name of the activity to launch in the TF, or {@code null} if none.
+     * @return token of the created task fragment.
+     */
+    TaskFragmentInfo createTaskFragment(@Nullable ComponentName componentName) {
+        return createTaskFragment(componentName, new Rect());
+    }
+
+    /**
+     * Same as {@link #createTaskFragment(ComponentName)}, but allows to specify the bounds for the
+     * new task fragment.
+     */
+    TaskFragmentInfo createTaskFragment(@Nullable ComponentName componentName,
+            @NonNull Rect bounds) {
+        final TaskFragmentCreationParams params = generateTaskFragCreationParams(bounds);
+        final IBinder taskFragToken = params.getFragmentToken();
+        final WindowContainerTransaction wct = new WindowContainerTransaction()
+                .createTaskFragment(params);
+        if (componentName != null) {
+            wct.startActivityInTaskFragment(taskFragToken, mOwnerToken,
+                    new Intent().setComponent(componentName), null /* activityOptions */);
+        }
+        mTaskFragmentOrganizer.applyTransaction(wct);
+        mTaskFragmentOrganizer.waitForTaskFragmentCreated();
+
+        if (componentName != null) {
+            mWmState.waitForActivityState(componentName, STATE_RESUMED);
+        }
+
+        return mTaskFragmentOrganizer.getTaskFragmentInfo(taskFragToken);
+    }
+
+    @NonNull
+    TaskFragmentCreationParams generateTaskFragCreationParams() {
+        return mTaskFragmentOrganizer.generateTaskFragParams(mOwnerToken);
+    }
+
+    @NonNull
+    TaskFragmentCreationParams generateTaskFragCreationParams(@NonNull Rect bounds) {
+        return mTaskFragmentOrganizer.generateTaskFragParams(mOwnerToken, bounds,
+                WINDOWING_MODE_UNDEFINED);
+    }
+
     public static class BasicTaskFragmentOrganizer extends TaskFragmentOrganizer {
         private final static int WAIT_TIMEOUT_IN_SECOND = 10;
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
new file mode 100644
index 0000000..d133cec
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm;
+
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
+import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBEDDING_ACTIVITY;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Test;
+
+/**
+ * Tests that verifies the behaviors of embedding activities in different trusted modes.
+ *
+ * Build/Install/Run:
+ *     atest CtsWindowManagerDeviceTestCases:TaskFragmentTrustedModeTest
+ */
+public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
+
+    private final ComponentName mTranslucentActivity = new ComponentName(mContext,
+            TranslucentActivity.class);
+
+    /**
+     * Verifies the visibility of a task fragment that has overlays on top of activities embedded
+     * in untrusted mode when there is an overlay over the task fragment.
+     */
+    @Test
+    public void testUntrustedModeTaskFragmentVisibility_overlayTaskFragment() {
+        // Create a task fragment with activity in untrusted mode.
+        final TaskFragmentInfo tf = createTaskFragment(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+
+        // Start a translucent activity over the TaskFragment.
+        createTaskFragment(mTranslucentActivity, partialOverlayBounds(tf));
+        mWmState.waitForActivityState(mTranslucentActivity, STATE_RESUMED);
+
+        // The task fragment must be made invisible when there is an overlay activity in it.
+        mWmState.waitForActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY, STATE_STOPPED);
+        final String overlayMessage = "Activities embedded in untrusted mode should be made "
+                + "invisible in a task fragment with overlay";
+        assertTrue(overlayMessage, mWmState.hasActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY,
+                STATE_STOPPED));
+        assertFalse(overlayMessage, mWmState.isActivityVisible(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
+        assertFalse(overlayMessage, mWmState.getTaskFragmentByActivity(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY).isVisible());
+        // The activity that appeared on top would stay resumed
+        assertTrue(overlayMessage, mWmState.hasActivityState(mTranslucentActivity, STATE_RESUMED));
+        assertTrue(overlayMessage, mWmState.isActivityVisible(mTranslucentActivity));
+        assertTrue(overlayMessage, mWmState.getTaskFragmentByActivity(
+                mTranslucentActivity).isVisible());
+    }
+
+    /**
+     * Verifies the visibility of a task fragment that has overlays on top of activities embedded
+     * in untrusted mode when an activity from another process is started on top.
+     */
+    @Test
+    public void testUntrustedModeTaskFragmentVisibility_startActivityInTaskFragment() {
+        // Create a task fragment with activity in untrusted mode.
+        final TaskFragmentInfo taskFragmentInfo = createTaskFragment(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+
+        // Start an activity with a different UID in the TaskFragment.
+        final WindowContainerTransaction wct = new WindowContainerTransaction()
+                .startActivityInTaskFragment(taskFragmentInfo.getFragmentToken(), mOwnerToken,
+                        new Intent().setComponent(mTranslucentActivity),
+                        null /* activityOptions */);
+        mTaskFragmentOrganizer.applyTransaction(wct);
+        mWmState.waitForActivityState(mTranslucentActivity, STATE_RESUMED);
+
+        // Some activities in the task fragment must be made invisible when there is an overlay.
+        mWmState.waitForActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY, STATE_STOPPED);
+        final String overlayMessage = "Activities embedded in untrusted mode should be made "
+                + "invisible in a task fragment with overlay";
+        assertTrue(overlayMessage, mWmState.hasActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY,
+                STATE_STOPPED));
+        assertFalse(overlayMessage, mWmState.isActivityVisible(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
+        // The activity that appeared on top would stay resumed, and the task fragment is still
+        // visible.
+        assertTrue(overlayMessage, mWmState.hasActivityState(mTranslucentActivity, STATE_RESUMED));
+        assertTrue(overlayMessage, mWmState.isActivityVisible(mTranslucentActivity));
+        assertTrue(overlayMessage, mWmState.getTaskFragmentByActivity(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY).isVisible());
+    }
+
+    /**
+     * Verifies the visibility of a task fragment that has overlays on top of activities embedded
+     * in untrusted mode when an activity from another process is reparented on top.
+     */
+    @Test
+    public void testUntrustedModeTaskFragmentVisibility_reparentActivityInTaskFragment() {
+        final Activity translucentActivity = startActivity(TranslucentActivity.class);
+
+        // Create a task fragment with activity in untrusted mode.
+        final TaskFragmentInfo taskFragmentInfo = createTaskFragment(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+
+        // Reparent a translucent activity with a different UID to the TaskFragment.
+        final IBinder embeddedActivityToken = getActivityToken(translucentActivity);
+        final WindowContainerTransaction wct = new WindowContainerTransaction()
+                .reparentActivityToTaskFragment(taskFragmentInfo.getFragmentToken(),
+                        embeddedActivityToken);
+        mTaskFragmentOrganizer.applyTransaction(wct);
+        mWmState.waitForActivityState(mTranslucentActivity, STATE_RESUMED);
+
+        // Some activities in the task fragment must be made invisible when there is an overlay.
+        mWmState.waitForActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY, STATE_STOPPED);
+        final String overlayMessage = "Activities embedded in untrusted mode should be made "
+                + "invisible in a task fragment with overlay";
+        assertTrue(overlayMessage, mWmState.hasActivityState(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY,
+                STATE_STOPPED));
+        assertFalse(overlayMessage, mWmState.isActivityVisible(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
+        // The activity that appeared on top would stay resumed, and the task fragment is still
+        // visible
+        assertTrue(overlayMessage, mWmState.hasActivityState(mTranslucentActivity, STATE_RESUMED));
+        assertTrue(overlayMessage, mWmState.isActivityVisible(mTranslucentActivity));
+        assertTrue(overlayMessage, mWmState.getTaskFragmentByActivity(
+                SECOND_UNTRUSTED_EMBEDDING_ACTIVITY).isVisible());
+
+        // Finishing the overlay activity must make TaskFragment visible again.
+        translucentActivity.finish();
+        waitAndAssertResumedActivity(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY,
+                "Activity must be resumed without overlays");
+        assertTrue("Activity must be visible without overlays",
+                mWmState.isActivityVisible(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
+    }
+
+    /**
+     * Creates bounds for a container that would appear on top and partially occlude the provided
+     * one.
+     */
+    @NonNull
+    private Rect partialOverlayBounds(@NonNull TaskFragmentInfo info) {
+        final Rect baseBounds = info.getConfiguration().windowConfiguration.getBounds();
+        final Rect result = new Rect(baseBounds);
+        result.inset(50 /* left */, 50 /* top */, 50 /* right */, 50 /* bottom */);
+        return result;
+    }
+
+    public static class TranslucentActivity extends FocusableActivity {}
+}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index df00ed5..1046f871 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -236,7 +236,7 @@
     private static final int UI_MODE_TYPE_VR_HEADSET = 0x07;
 
     static final boolean ENABLE_SHELL_TRANSITIONS =
-            SystemProperties.getBoolean("persist.debug.shell_transit", false);
+            SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
 
     private static Boolean sHasHomeScreen = null;
     private static Boolean sSupportsSystemDecorsOnSecondaryDisplays = null;
diff --git a/tests/input/OWNERS b/tests/input/OWNERS
index 8ed76d2..824b5ac 100644
--- a/tests/input/OWNERS
+++ b/tests/input/OWNERS
@@ -1,5 +1,2 @@
-# Bug component: 136048
+include platform/frameworks/base:/INPUT_OWNERS
 arthurhung@google.com
-lzye@google.com
-michaelwr@google.com
-svv@google.com
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index d03bf4b..329d29d 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -514,17 +514,15 @@
                         return decorView != null && decorView.isAttachedToWindow()
                                 && decorView.getVisibility() == View.VISIBLE;
                     }
-                    case "setStylusHandwritingWindowTouchListener": {
-                        View decorView = getStylusHandwritingWindow().getDecorView();
-                        if (decorView != null && decorView.getVisibility() == View.VISIBLE) {
-                            mEvents = new ArrayList<>();
-                            decorView.setOnTouchListener((view, event) ->
-                                    mEvents.add(MotionEvent.obtain(event)));
-                            return true;
-                        }
-                        return false;
+                    case "setStylusHandwritingInkView": {
+                        View inkView = new View(attrContext);
+                        getStylusHandwritingWindow().setContentView(inkView);
+                        mEvents = new ArrayList<>();
+                        inkView.setOnTouchListener((view, event) ->
+                                mEvents.add(MotionEvent.obtain(event)));
+                        return true;
                     }
-                    case "getStylusHandwritingWindowEvents": {
+                    case "getStylusHandwritingEvents": {
                         return mEvents;
                     }
                     case "finishStylusHandwriting": {
@@ -964,11 +962,24 @@
 
     @Override
     public boolean onStartStylusHandwriting() {
+        if (mEvents != null) {
+            mEvents.clear();
+        }
         getTracer().onStartStylusHandwriting(() -> super.onStartStylusHandwriting());
         return true;
     }
 
     @Override
+    public void onStylusHandwritingMotionEvent(@NonNull MotionEvent motionEvent) {
+        if (mEvents == null) {
+            mEvents = new ArrayList<>();
+        }
+        mEvents.add(MotionEvent.obtain(motionEvent));
+        getTracer().onStylusHandwritingMotionEvent(()
+                -> super.onStylusHandwritingMotionEvent(motionEvent));
+    }
+
+    @Override
     public void onFinishStylusHandwriting() {
         getTracer().onFinishStylusHandwriting(() -> super.onFinishStylusHandwriting());
     }
@@ -1358,6 +1369,10 @@
             recordEventInternal("onStartStylusHandwriting", runnable, arguments);
         }
 
+        void onStylusHandwritingMotionEvent(@NonNull Runnable runnable) {
+            recordEventInternal("onStylusMotionEvent", runnable);
+        }
+
         void onFinishStylusHandwriting(@NonNull Runnable runnable) {
             final Bundle arguments = new Bundle();
             arguments.putParcelable("editorInfo", mIme.getCurrentInputEditorInfo());
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index a779410..87cd773 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -1450,13 +1450,13 @@
     }
 
     @NonNull
-    public ImeCommand callSetStylusHandwritingWindowTouchListener() {
-        return callCommandInternal("setStylusHandwritingWindowTouchListener", new Bundle());
+    public ImeCommand callSetStylusHandwritingInkView() {
+        return callCommandInternal("setStylusHandwritingInkView", new Bundle());
     }
 
     @NonNull
-    public ImeCommand callGetStylusHandwritingWindowEvents() {
-        return callCommandInternal("getStylusHandwritingWindowEvents", new Bundle());
+    public ImeCommand callGetStylusHandwritingEvents() {
+        return callCommandInternal("getStylusHandwritingEvents", new Bundle());
     }
 
     @NonNull
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index 265940f2..1398785 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -30,6 +30,7 @@
 
 import android.Manifest;
 import android.content.Context;
+import android.inputmethodservice.InputMethodService;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Pair;
@@ -154,12 +155,28 @@
 
     /**
      * Call {@link InputMethodManager#startStylusHandwriting(View)} and inject Stylus touch events
-     * on screen. Make sure InkWindow receives those events via Spy window surface.
+     * on screen. Make sure {@link InputMethodService#onStylusHandwritingMotionEvent(MotionEvent)}
+     * receives those events via Spy window surface.
      * @throws Exception
      */
     @Test
-    public void testHandwritingStylusEvents() throws Exception {
-        final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+    public void testHandwritingStylusEvents_onStylusHandwritingMotionEvent() throws Exception {
+        testHandwritingStylusEvents(false /* verifyOnInkView */);
+    }
+
+    /**
+     * Call {@link InputMethodManager#startStylusHandwriting(View)} and inject Stylus touch events
+     * on screen. Make sure Inking view receives those events via Spy window surface.
+     * @throws Exception
+     */
+    @Test
+    public void testHandwritingStylusEvents_dispatchToInkView() throws Exception {
+        testHandwritingStylusEvents(false /* verifyOnInkView */);
+    }
+
+    private void testHandwritingStylusEvents(boolean verifyOnInkView) throws Exception {
+        final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
+                .getTargetContext().getSystemService(InputMethodManager.class);
         try (MockImeSession imeSession = MockImeSession.create(
                 InstrumentationRegistry.getInstrumentation().getContext(),
                 InstrumentationRegistry.getInstrumentation().getUiAutomation(),
@@ -187,19 +204,25 @@
                     stream, imeSession.callGetStylusHandwritingWindowVisibility(), TIMEOUT)
                     .getReturnBooleanValue());
 
-            // Verify IME stylus window receives the motion Event.
-            assertTrue(expectCommand(
-                    stream, imeSession.callSetStylusHandwritingWindowTouchListener(), TIMEOUT)
-                    .getReturnBooleanValue());
+            if (verifyOnInkView) {
+                // Verify IME stylus Ink view receives the motion Event.
+                assertTrue(expectCommand(
+                        stream,
+                        imeSession.callSetStylusHandwritingInkView(),
+                        TIMEOUT).getReturnBooleanValue());
+            }
 
             // inject Stylus touch events to screen
             List<MotionEvent> injectedEvents =
                     TestUtils.getStylusMoveEventsOnDisplay(0 /* displayId */);
             TestUtils.injectAll(injectedEvents);
 
-            // get Stylus events from InkWindow.
-            ArrayList<MotionEvent> capturedEvents =  expectCommand(
-                    stream, imeSession.callGetStylusHandwritingWindowEvents(), TIMEOUT)
+            expectEvent(
+                    stream, event -> "onStylusMotionEvent".equals(event.getEventName()), TIMEOUT);
+
+            // get Stylus events from Ink view.
+            ArrayList<MotionEvent> capturedEvents = expectCommand(
+                    stream, imeSession.callGetStylusHandwritingEvents(), TIMEOUT)
                     .getReturnParcelableArrayListValue();
             assertNotNull(capturedEvents);
 
diff --git a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementCorrectionsInjectionTest.java b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementCorrectionsInjectionTest.java
index ee7b466..21f3d2b 100644
--- a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementCorrectionsInjectionTest.java
+++ b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementCorrectionsInjectionTest.java
@@ -25,6 +25,7 @@
 import android.location.cts.common.TestGnssStatusCallback;
 import android.location.cts.common.TestLocationListener;
 import android.location.cts.common.TestLocationManager;
+import android.location.cts.common.TestMeasurementUtil;
 import android.util.Log;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -40,6 +41,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.junit.Assume.assumeTrue;
+
 /**
  * Tests for {@link GnssMeasurementCorrections} injection.
  *
@@ -62,6 +65,7 @@
         InstrumentationRegistry.getInstrumentation()
                 .getUiAutomation()
                 .adoptShellPermissionIdentity(Manifest.permission.LOCATION_HARDWARE);
+        assumeTrue(TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager, TAG));
     }
 
     @After
diff --git a/tests/media/jni/NativeCodecDecoderTest.cpp b/tests/media/jni/NativeCodecDecoderTest.cpp
index d005322..8ea1136 100644
--- a/tests/media/jni/NativeCodecDecoderTest.cpp
+++ b/tests/media/jni/NativeCodecDecoderTest.cpp
@@ -44,7 +44,7 @@
 
     void setUpAudioReference(const char* refFile);
     void deleteReference();
-    bool setUpExtractor(const char* srcFile);
+    bool setUpExtractor(const char* srcFile, int colorFormat);
     void deleteExtractor();
     bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame,
                         bool isEncoder) override;
@@ -60,10 +60,10 @@
     ~CodecDecoderTest();
 
     bool testSimpleDecode(const char* decoder, const char* testFile, const char* refFile,
-                          float rmsError, uLong checksum);
-    bool testFlush(const char* decoder, const char* testFile);
-    bool testOnlyEos(const char* decoder, const char* testFile);
-    bool testSimpleDecodeQueueCSD(const char* decoder, const char* testFile);
+                          int colorFormat, float rmsError, uLong checksum);
+    bool testFlush(const char* decoder, const char* testFile, int colorFormat);
+    bool testOnlyEos(const char* decoder, const char* testFile, int colorFormat);
+    bool testSimpleDecodeQueueCSD(const char* decoder, const char* testFile, int colorFormat);
 };
 
 CodecDecoderTest::CodecDecoderTest(const char* mime, ANativeWindow* window)
@@ -103,7 +103,7 @@
     mRefLength = 0;
 }
 
-bool CodecDecoderTest::setUpExtractor(const char* srcFile) {
+bool CodecDecoderTest::setUpExtractor(const char* srcFile, int colorFormat) {
     FILE* fp = fopen(srcFile, "rbe");
     struct stat buf {};
     if (fp && !fstat(fileno(fp), &buf)) {
@@ -114,6 +114,7 @@
         if (res != AMEDIA_OK) {
             deleteExtractor();
         } else {
+            mBytesPerSample = (colorFormat == COLOR_FormatYUVP010) ? 2 : 1;
             for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(mExtractor);
                  trackID++) {
                 AMediaFormat* currFormat = AMediaExtractor_getTrackFormat(mExtractor, trackID);
@@ -123,7 +124,7 @@
                     AMediaExtractor_selectTrack(mExtractor, trackID);
                     if (!mIsAudio) {
                         AMediaFormat_setInt32(currFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
-                                              COLOR_FormatYUV420Flexible);
+                                              colorFormat);
                     }
                     mInpDecFormat = currFormat;
                     // TODO: determine this from the extractor format when it becomes exposed.
@@ -239,7 +240,7 @@
                 AMediaFormat_getInt32(format, "width", &width);
                 AMediaFormat_getInt32(format, "height", &height);
                 AMediaFormat_getInt32(format, "stride", &stride);
-                mOutputBuff->updateChecksum(buf, info, width, height, stride);
+                mOutputBuff->updateChecksum(buf, info, width, height, stride, mBytesPerSample);
             }
         }
         mOutputBuff->saveOutPTS(info->presentationTimeUs);
@@ -300,9 +301,10 @@
 }
 
 bool CodecDecoderTest::testSimpleDecode(const char* decoder, const char* testFile,
-                                        const char* refFile, float rmsError, uLong checksum) {
+                                        const char* refFile, int colorFormat, float rmsError,
+                                        uLong checksum) {
     bool isPass = true;
-    if (!setUpExtractor(testFile)) return false;
+    if (!setUpExtractor(testFile, colorFormat)) return false;
     mSaveToMem = (mWindow == nullptr);
     auto ref = &mRefBuff;
     auto test = &mTestBuff;
@@ -400,9 +402,9 @@
     return isPass;
 }
 
-bool CodecDecoderTest::testFlush(const char* decoder, const char* testFile) {
+bool CodecDecoderTest::testFlush(const char* decoder, const char* testFile, int colorFormat) {
     bool isPass = true;
-    if (!setUpExtractor(testFile)) return false;
+    if (!setUpExtractor(testFile, colorFormat)) return false;
     mCsdBuffers.clear();
     for (int i = 0;; i++) {
         char csdName[16];
@@ -527,9 +529,9 @@
     return isPass;
 }
 
-bool CodecDecoderTest::testOnlyEos(const char* decoder, const char* testFile) {
+bool CodecDecoderTest::testOnlyEos(const char* decoder, const char* testFile, int colorFormat) {
     bool isPass = true;
-    if (!setUpExtractor(testFile)) return false;
+    if (!setUpExtractor(testFile, colorFormat)) return false;
     mSaveToMem = (mWindow == nullptr);
     auto ref = &mRefBuff;
     auto test = &mTestBuff;
@@ -568,9 +570,10 @@
     return isPass;
 }
 
-bool CodecDecoderTest::testSimpleDecodeQueueCSD(const char* decoder, const char* testFile) {
+bool CodecDecoderTest::testSimpleDecodeQueueCSD(const char* decoder, const char* testFile,
+                                                int colorFormat) {
     bool isPass = true;
-    if (!setUpExtractor(testFile)) return false;
+    if (!setUpExtractor(testFile, colorFormat)) return false;
     std::vector<AMediaFormat*> formats;
     formats.push_back(mInpDecFormat);
     mInpDecDupFormat = AMediaFormat_new();
@@ -664,7 +667,7 @@
 
 static jboolean nativeTestSimpleDecode(JNIEnv* env, jobject, jstring jDecoder, jobject surface,
                                        jstring jMime, jstring jtestFile, jstring jrefFile,
-                                       jfloat jrmsError, jlong jChecksum) {
+                                       jint jColorFormat, jfloat jrmsError, jlong jChecksum) {
     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
     const char* cMime = env->GetStringUTFChars(jMime, nullptr);
     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
@@ -673,8 +676,8 @@
     uLong cChecksum = jChecksum;
     ANativeWindow* window = surface ? ANativeWindow_fromSurface(env, surface) : nullptr;
     auto* codecDecoderTest = new CodecDecoderTest(cMime, window);
-    bool isPass =
-            codecDecoderTest->testSimpleDecode(cDecoder, cTestFile, cRefFile, cRmsError, cChecksum);
+    bool isPass = codecDecoderTest->testSimpleDecode(cDecoder, cTestFile, cRefFile, jColorFormat,
+                                                     cRmsError, cChecksum);
     delete codecDecoderTest;
     if (window) {
         ANativeWindow_release(window);
@@ -688,12 +691,12 @@
 }
 
 static jboolean nativeTestOnlyEos(JNIEnv* env, jobject, jstring jDecoder, jstring jMime,
-                                  jstring jtestFile) {
+                                  jstring jtestFile, jint jColorFormat) {
     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
     const char* cMime = env->GetStringUTFChars(jMime, nullptr);
     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
     auto* codecDecoderTest = new CodecDecoderTest(cMime, nullptr);
-    bool isPass = codecDecoderTest->testOnlyEos(cDecoder, cTestFile);
+    bool isPass = codecDecoderTest->testOnlyEos(cDecoder, cTestFile, jColorFormat);
     delete codecDecoderTest;
     env->ReleaseStringUTFChars(jDecoder, cDecoder);
     env->ReleaseStringUTFChars(jMime, cMime);
@@ -702,13 +705,13 @@
 }
 
 static jboolean nativeTestFlush(JNIEnv* env, jobject, jstring jDecoder, jobject surface,
-                                jstring jMime, jstring jtestFile) {
+                                jstring jMime, jstring jtestFile, jint jColorFormat) {
     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
     const char* cMime = env->GetStringUTFChars(jMime, nullptr);
     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
     ANativeWindow* window = surface ? ANativeWindow_fromSurface(env, surface) : nullptr;
     auto* codecDecoderTest = new CodecDecoderTest(cMime, window);
-    bool isPass = codecDecoderTest->testFlush(cDecoder, cTestFile);
+    bool isPass = codecDecoderTest->testFlush(cDecoder, cTestFile, jColorFormat);
     delete codecDecoderTest;
     if (window) {
         ANativeWindow_release(window);
@@ -721,12 +724,13 @@
 }
 
 static jboolean nativeTestSimpleDecodeQueueCSD(JNIEnv* env, jobject, jstring jDecoder,
-                                               jstring jMime, jstring jtestFile) {
+                                               jstring jMime, jstring jtestFile,
+                                               jint jColorFormat) {
     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
     const char* cMime = env->GetStringUTFChars(jMime, nullptr);
     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
     auto codecDecoderTest = new CodecDecoderTest(cMime, nullptr);
-    bool isPass = codecDecoderTest->testSimpleDecodeQueueCSD(cDecoder, cTestFile);
+    bool isPass = codecDecoderTest->testSimpleDecodeQueueCSD(cDecoder, cTestFile, jColorFormat);
     delete codecDecoderTest;
     env->ReleaseStringUTFChars(jDecoder, cDecoder);
     env->ReleaseStringUTFChars(jMime, cMime);
@@ -738,15 +742,15 @@
     const JNINativeMethod methodTable[] = {
             {"nativeTestSimpleDecode",
              "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;Ljava/"
-             "lang/String;FJ)Z",
+             "lang/String;IFJ)Z",
              (void*)nativeTestSimpleDecode},
-            {"nativeTestOnlyEos", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+            {"nativeTestOnlyEos", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z",
              (void*)nativeTestOnlyEos},
             {"nativeTestFlush",
-             "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;)Z",
+             "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;I)Z",
              (void*)nativeTestFlush},
             {"nativeTestSimpleDecodeQueueCSD",
-             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z",
              (void*)nativeTestSimpleDecodeQueueCSD},
     };
     jclass c = env->FindClass("android/mediav2/cts/CodecDecoderTest");
@@ -757,10 +761,10 @@
     const JNINativeMethod methodTable[] = {
             {"nativeTestSimpleDecode",
              "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;Ljava/"
-             "lang/String;FJ)Z",
+             "lang/String;IFJ)Z",
              (void*)nativeTestSimpleDecode},
             {"nativeTestFlush",
-             "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;)Z",
+             "(Ljava/lang/String;Landroid/view/Surface;Ljava/lang/String;Ljava/lang/String;I)Z",
              (void*)nativeTestFlush},
     };
     jclass c = env->FindClass("android/mediav2/cts/CodecDecoderSurfaceTest");
diff --git a/tests/media/jni/NativeCodecTestBase.cpp b/tests/media/jni/NativeCodecTestBase.cpp
index 1516185..391ef1e 100644
--- a/tests/media/jni/NativeCodecTestBase.cpp
+++ b/tests/media/jni/NativeCodecTestBase.cpp
@@ -207,8 +207,8 @@
     return result;
 }
 
-void OutputManager::updateChecksum(
-        uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height, int stride) {
+void OutputManager::updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height,
+                                   int stride, int bytesPerSample) {
     uint8_t flattenInfo[16];
     int pos = 0;
     if (width <= 0 || height <= 0 || stride <= 0) {
@@ -218,15 +218,15 @@
                           info->flags & ~AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
     flattenField<int64_t>(flattenInfo, &pos, info->presentationTimeUs);
     crc32value = crc32(crc32value, flattenInfo, pos);
-    if (width > 0 && height > 0 && stride > 0) {
+    if (width > 0 && height > 0 && stride > 0 && bytesPerSample > 0) {
         // Only checksum Y plane
-        std::vector<uint8_t> tmp(width * height, 0u);
+        std::vector<uint8_t> tmp(width * height * bytesPerSample, 0u);
         size_t offset = 0;
         for (int i = 0; i < height; ++i) {
-            memcpy(tmp.data() + (i * width), buf + offset, width);
+            memcpy(tmp.data() + (i * width * bytesPerSample), buf + offset, width * bytesPerSample);
             offset += stride;
         }
-        crc32value = crc32(crc32value, tmp.data(), width * height);
+        crc32value = crc32(crc32value, tmp.data(), width * height * bytesPerSample);
     } else {
         crc32value = crc32(crc32value, buf, info->size);
     }
@@ -342,6 +342,7 @@
     mSaveToMem = false;
     mOutputBuff = nullptr;
     mCodec = nullptr;
+    mBytesPerSample = mIsAudio ? 2 : 1;
 }
 
 CodecTestBase::~CodecTestBase() {
diff --git a/tests/media/jni/NativeCodecTestBase.h b/tests/media/jni/NativeCodecTestBase.h
index d67933a..9a22108 100644
--- a/tests/media/jni/NativeCodecTestBase.h
+++ b/tests/media/jni/NativeCodecTestBase.h
@@ -106,10 +106,11 @@
         memory.insert(memory.end(), buf, buf + info->size);
     }
     void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info) {
-        updateChecksum(buf, info, 0, 0, 0);
+        updateChecksum(buf, info, 0, 0, 0, 0);
     }
-    void updateChecksum(
-            uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height, int stride);
+
+    void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height,
+                        int stride, int bytesPerSample);
     uLong getChecksum() { return crc32value; }
     void reset() {
         inpPtsArray.clear();
@@ -136,6 +137,7 @@
     int64_t mPrevOutputPts;
     bool mSignalledOutFormatChanged;
     AMediaFormat* mOutFormat;
+    int mBytesPerSample;
 
     bool mSaveToMem;
     OutputManager* mOutputBuff;
diff --git a/tests/media/jni/NativeMediaCommon.h b/tests/media/jni/NativeMediaCommon.h
index c597923..fd8aba1 100644
--- a/tests/media/jni/NativeMediaCommon.h
+++ b/tests/media/jni/NativeMediaCommon.h
@@ -56,6 +56,7 @@
 constexpr int COLOR_FormatYUV420SemiPlanar = 21;
 constexpr int COLOR_FormatYUV420Flexible = 0x7F420888;
 constexpr int COLOR_FormatSurface = 0x7f000789;
+constexpr int COLOR_FormatYUVP010 = 54;
 
 // constants not defined in NDK
 extern const char* TBD_AMEDIACODEC_PARAMETER_KEY_REQUEST_SYNC_FRAME;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index 0dc1e95..b0da46f 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -443,7 +443,7 @@
     }
 
     private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mime,
-            String testFile, String refFile, float rmsError, long checksum);
+            String testFile, String refFile, int colorFormat, float rmsError, long checksum);
 
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
@@ -452,11 +452,12 @@
         mExtractor.release();
         mActivity.setScreenParams(getWidth(format), getHeight(format), false);
         assertTrue(nativeTestSimpleDecode(mCodecName, mSurface, mMime, mInpPrefix + mTestFile,
-                mInpPrefix + mReconfigFile, -1.0f, 0L));
+                mInpPrefix + mReconfigFile, format.getInteger(MediaFormat.KEY_COLOR_FORMAT), -1.0f,
+                0L));
     }
 
     private native boolean nativeTestFlush(String decoder, Surface surface, String mime,
-            String testFile);
+            String testFile, int colorFormat);
 
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
@@ -464,6 +465,7 @@
         MediaFormat format = setUpSource(mTestFile);
         mExtractor.release();
         mActivity.setScreenParams(getWidth(format), getHeight(format), true);
-        assertTrue(nativeTestFlush(mCodecName, mSurface, mMime, mInpPrefix + mTestFile));
+        assertTrue(nativeTestFlush(mCodecName, mSurface, mMime, mInpPrefix + mTestFile,
+                format.getInteger(MediaFormat.KEY_COLOR_FORMAT)));
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index ff5ca6d..5cc2861 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -190,7 +190,7 @@
     }
 
     private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mime,
-            String testFile, String refFile, float rmsError, long checksum);
+            String testFile, String refFile, int colorFormat, float rmsError, long checksum);
 
     static void verify(OutputManager outBuff, String refFile, float rmsError, int audioFormat,
             long refCRC) throws IOException {
@@ -328,15 +328,17 @@
                 }
             }
             mCodec.release();
+            mExtractor.release();
+            int colorFormat = mIsAudio ? 0 : format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+            assertTrue(nativeTestSimpleDecode(mCodecName, null, mMime, mInpPrefix + mTestFile,
+                    mInpPrefix + mRefFile, colorFormat, mRmsError, ref.getCheckSumBuffer()));
             if (mSaveToMem) {
                 int audioEncoding = mIsAudio ? format.getInteger(MediaFormat.KEY_PCM_ENCODING,
                         AudioFormat.ENCODING_PCM_16BIT) : AudioFormat.ENCODING_INVALID;
+                Assume.assumeFalse("skip checksum due to tone mapping", mSkipChecksumVerification);
                 verify(mOutputBuff, mRefFile, mRmsError, audioEncoding, mRefCRC);
             }
-            assertTrue(nativeTestSimpleDecode(mCodecName, null, mMime, mInpPrefix + mTestFile,
-                    mInpPrefix + mRefFile, mRmsError, ref.getCheckSumBuffer()));
         }
-        mExtractor.release();
     }
 
     /**
@@ -453,15 +455,19 @@
     }
 
     private native boolean nativeTestFlush(String decoder, Surface surface, String mime,
-            String testFile);
+            String testFile, int colorFormat);
 
     @Ignore("TODO(b/147576107)")
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    public void testFlushNative() {
-        {
-            assertTrue(nativeTestFlush(mCodecName, null, mMime, mInpPrefix + mTestFile));
+    public void testFlushNative() throws IOException {
+        int colorFormat = 0;
+        if (!mIsAudio) {
+            MediaFormat format = setUpSource(mTestFile);
+            mExtractor.release();
+            colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
         }
+        assertTrue(nativeTestFlush(mCodecName, null, mMime, mInpPrefix + mTestFile, colorFormat));
     }
 
     /**
@@ -677,14 +683,19 @@
         mExtractor.release();
     }
 
-    private native boolean nativeTestOnlyEos(String decoder, String mime, String testFile);
+    private native boolean nativeTestOnlyEos(String decoder, String mime, String testFile,
+            int colorFormat);
 
     @SmallTest
     @Test
-    public void testOnlyEosNative() {
-        {
-            assertTrue(nativeTestOnlyEos(mCodecName, mMime, mInpPrefix + mTestFile));
+    public void testOnlyEosNative() throws IOException {
+        int colorFormat = 0;
+        if (!mIsAudio) {
+            MediaFormat format = setUpSource(mTestFile);
+            mExtractor.release();
+            colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
         }
+        assertTrue(nativeTestOnlyEos(mCodecName, mMime, mInpPrefix + mTestFile, colorFormat));
     }
 
     /**
@@ -778,7 +789,7 @@
     }
 
     private native boolean nativeTestSimpleDecodeQueueCSD(String decoder, String mime,
-            String testFile);
+            String testFile, int colorFormat);
 
     @LargeTest
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
@@ -788,10 +799,10 @@
             mExtractor.release();
             return;
         }
-        {
-            assertTrue(nativeTestSimpleDecodeQueueCSD(mCodecName, mMime, mInpPrefix + mTestFile));
-        }
         mExtractor.release();
+        int colorFormat = mIsAudio ? 0 : format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+        assertTrue(nativeTestSimpleDecodeQueueCSD(mCodecName, mMime, mInpPrefix + mTestFile,
+                colorFormat));
     }
 
     /**
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 1938b8f..9729cc6 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -23,6 +23,7 @@
 
 import androidx.test.filters.LargeTest;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -639,6 +640,7 @@
                 assertEquals("width mismatch", mWidth, getWidth(mOutFormat));
                 assertEquals("height mismatch", mHeight, getHeight(mOutFormat));
             }
+            Assume.assumeFalse("skip checksum due to tonemapping", mSkipChecksumVerification);
             CodecDecoderTest.verify(ref, mRefFile, mRmsError, audioEncoding, mRefCRC);
         }
     }
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index d07a1df..fd68507 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -66,6 +66,7 @@
 
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
 import static android.media.MediaCodecInfo.CodecProfileLevel.*;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -293,36 +294,37 @@
     }
 
     void checksum(ByteBuffer buf, int size) {
-        checksum(buf, size, 0, 0, 0);
+        checksum(buf, size, 0, 0, 0, 0);
     }
 
-    void checksum(ByteBuffer buf, int size, int width, int height, int stride) {
+    void checksum(ByteBuffer buf, int size, int width, int height, int stride, int bytesPerSample) {
         int cap = buf.capacity();
         assertTrue("checksum() params are invalid: size = " + size + " cap = " + cap,
                 size > 0 && size <= cap);
         if (buf.hasArray()) {
-            if (width > 0 && height > 0 && stride > 0) {
+            if (width > 0 && height > 0 && stride > 0 && bytesPerSample > 0) {
                 int offset = buf.position() + buf.arrayOffset();
-                byte[] bb = new byte[width * height];
+                byte[] bb = new byte[width * height * bytesPerSample];
                 for (int i = 0; i < height; ++i) {
-                    System.arraycopy(buf.array(), offset, bb, i * width, width);
+                    System.arraycopy(buf.array(), offset, bb, i * width * bytesPerSample,
+                            width * bytesPerSample);
                     offset += stride;
                 }
-                mCrc32UsingBuffer.update(bb, 0, width * height);
+                mCrc32UsingBuffer.update(bb, 0, width * height * bytesPerSample);
             } else {
                 mCrc32UsingBuffer.update(buf.array(), buf.position() + buf.arrayOffset(), size);
             }
-        } else if (width > 0 && height > 0 && stride > 0) {
+        } else if (width > 0 && height > 0 && stride > 0 && bytesPerSample > 0) {
             // Checksum only the Y plane
             int pos = buf.position();
             int offset = pos;
-            byte[] bb = new byte[width * height];
+            byte[] bb = new byte[width * height * bytesPerSample];
             for (int i = 0; i < height; ++i) {
                 buf.position(offset);
-                buf.get(bb, i * width, width);
+                buf.get(bb, i * width * bytesPerSample, width * bytesPerSample);
                 offset += stride;
             }
-            mCrc32UsingBuffer.update(bb, 0, width * height);
+            mCrc32UsingBuffer.update(bb, 0, width * height * bytesPerSample);
             buf.position(pos);
         } else {
             int pos = buf.position();
@@ -340,7 +342,9 @@
 
     void checksum(Image image) {
         int format = image.getFormat();
-        assertEquals("unexpected image format", ImageFormat.YUV_420_888, format);
+        assertTrue("unexpected image format",
+                format == ImageFormat.YUV_420_888 || format == ImageFormat.YCBCR_P010);
+        int bytesPerSample = (ImageFormat.getBitsPerPixel(format) * 2) / (8 * 3);  // YUV420
 
         Rect cropRect = image.getCropRect();
         int imageWidth = cropRect.width();
@@ -356,6 +360,7 @@
             rowStride = planes[i].getRowStride();
             pixelStride = planes[i].getPixelStride();
             if (i == 0) {
+                assertEquals(bytesPerSample, pixelStride);
                 width = imageWidth;
                 height = imageHeight;
                 left = imageLeft;
@@ -368,30 +373,35 @@
             }
             int cropOffset = (left * pixelStride) + top * rowStride;
             // local contiguous pixel buffer
-            byte[] bb = new byte[width * height];
+            byte[] bb = new byte[width * height * bytesPerSample];
+
             if (buf.hasArray()) {
                 byte[] b = buf.array();
                 int offs = buf.arrayOffset() + cropOffset;
-                if (pixelStride == 1) {
+                if (pixelStride == bytesPerSample) {
                     for (y = 0; y < height; ++y) {
-                        System.arraycopy(b, offs + y * rowStride, bb, y * width, width);
+                        System.arraycopy(b, offs + y * rowStride, bb, y * width * bytesPerSample,
+                                width * bytesPerSample);
                     }
                 } else {
                     // do it pixel-by-pixel
                     for (y = 0; y < height; ++y) {
                         int lineOffset = offs + y * rowStride;
                         for (x = 0; x < width; ++x) {
-                            bb[y * width + x] = b[lineOffset + x * pixelStride];
+                            for (int bytePos = 0; bytePos < bytesPerSample; ++bytePos) {
+                                bb[y * width * bytesPerSample + x * bytesPerSample + bytePos] =
+                                        b[lineOffset + x * pixelStride + bytePos];
+                            }
                         }
                     }
                 }
             } else { // almost always ends up here due to direct buffers
                 int base = buf.position();
                 int pos = base + cropOffset;
-                if (pixelStride == 1) {
+                if (pixelStride == bytesPerSample) {
                     for (y = 0; y < height; ++y) {
                         buf.position(pos + y * rowStride);
-                        buf.get(bb, y * width, width);
+                        buf.get(bb, y * width * bytesPerSample, width * bytesPerSample);
                     }
                 } else {
                     // local line buffer
@@ -399,16 +409,20 @@
                     // do it pixel-by-pixel
                     for (y = 0; y < height; ++y) {
                         buf.position(pos + y * rowStride);
-                        // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
-                        buf.get(lb, 0, pixelStride * (width - 1) + 1);
+                        // we're only guaranteed to have pixelStride * (width - 1) +
+                        // bytesPerSample bytes
+                        buf.get(lb, 0, pixelStride * (width - 1) + bytesPerSample);
                         for (x = 0; x < width; ++x) {
-                            bb[y * width + x] = lb[x * pixelStride];
+                            for (int bytePos = 0; bytePos < bytesPerSample; ++bytePos) {
+                                bb[y * width * bytesPerSample + x * bytesPerSample + bytePos] =
+                                        lb[x * pixelStride + bytePos];
+                            }
                         }
                     }
                 }
                 buf.position(base);
             }
-            mCrc32UsingImage.update(bb, 0, width * height);
+            mCrc32UsingImage.update(bb, 0, width * height * bytesPerSample);
         }
     }
 
@@ -683,6 +697,35 @@
         return isSupported;
     }
 
+    static boolean doesAnyFormatHaveHBDProfile(String mime, ArrayList<MediaFormat> formats) {
+        // check for HLG profiles
+        for (MediaFormat format : formats) {
+            assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
+            switch (mime) {
+                case MediaFormat.MIMETYPE_VIDEO_VP9: {
+                    int profile = format.getInteger(MediaFormat.KEY_PROFILE, VP9Profile0);
+                    if (profile == VP9Profile2 || profile == VP9Profile3) {
+                        return true;
+                    }
+                }
+                case MediaFormat.MIMETYPE_VIDEO_HEVC: {
+                    int profile = format.getInteger(MediaFormat.KEY_PROFILE, HEVCProfileMain);
+                    if (profile == HEVCProfileMain10) {
+                        return true;
+                    }
+                }
+                case MediaFormat.MIMETYPE_VIDEO_AV1: {
+                    int profile = format.getInteger(MediaFormat.KEY_PROFILE, AV1ProfileMain8);
+                    if (profile == AV1ProfileMain10) {
+                        return true;
+                    }
+                }
+            }
+        }
+        // check for HDR profiles (if necessary)
+        return doesAnyFormatHaveHDRProfile(mime, formats);
+    }
+
     static boolean doesAnyFormatHaveHDRProfile(String mime, ArrayList<MediaFormat> formats) {
         for (MediaFormat format : formats) {
             assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
@@ -1225,6 +1268,7 @@
     String mMime;
     String mTestFile;
     boolean mIsInterlaced;
+    boolean mSkipChecksumVerification;
 
     ArrayList<ByteBuffer> mCsdBuffers;
     private int mCurrCsdIdx;
@@ -1248,6 +1292,7 @@
     }
 
     MediaFormat setUpSource(String prefix, String srcFile) throws IOException {
+        Preconditions.assertTestFileExists(prefix + srcFile);
         mExtractor = new MediaExtractor();
         mExtractor.setDataSource(prefix + srcFile);
         for (int trackID = 0; trackID < mExtractor.getTrackCount(); trackID++) {
@@ -1265,11 +1310,15 @@
                         }
                     }
                 } else {
-                    if (mSurface == null) {
-                        // COLOR_FormatYUV420Flexible must be supported by all components
-                        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
-                    } else {
-                        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
+                    ArrayList<MediaFormat> formatList = new ArrayList<>();
+                    formatList.add(format);
+                    boolean selectHBD = doesAnyFormatHaveHBDProfile(mMime, formatList) ||
+                            srcFile.contains("10bit");
+                    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                            getColorFormat(mCodecName, mMime, mSurface != null, selectHBD));
+                    if (selectHBD && (format.getInteger(MediaFormat.KEY_COLOR_FORMAT) !=
+                            COLOR_FormatYUVP010)) {
+                        mSkipChecksumVerification = true;
                     }
                 }
                 // TODO: determine this from the extractor format when it becomes exposed.
@@ -1281,6 +1330,23 @@
         return null;
     }
 
+    int getColorFormat(String name, String mediaType, boolean surfaceMode, boolean hbdMode)
+            throws IOException {
+        if (surfaceMode) return COLOR_FormatSurface;
+        if (hbdMode) {
+            MediaCodec codec = MediaCodec.createByCodecName(name);
+            MediaCodecInfo.CodecCapabilities cap =
+                    codec.getCodecInfo().getCapabilitiesForType(mediaType);
+            codec.release();
+            for (int c : cap.colorFormats) {
+                if (c == COLOR_FormatYUVP010) {
+                    return c;
+                }
+            }
+        }
+        return COLOR_FormatYUV420Flexible;
+    }
+
     boolean hasCSD(MediaFormat format) {
         return format.containsKey("csd-0");
     }
@@ -1371,15 +1437,18 @@
             } else {
                 // tests both getOutputImage and getOutputBuffer. Can do time division
                 // multiplexing but lets allow it for now
-                MediaFormat format = mCodec.getOutputFormat();
-                int width = format.getInteger(MediaFormat.KEY_WIDTH);
-                int height = format.getInteger(MediaFormat.KEY_HEIGHT);
-                int stride = format.getInteger(MediaFormat.KEY_STRIDE);
-                mOutputBuff.checksum(buf, info.size, width, height, stride);
-
                 Image img = mCodec.getOutputImage(bufferIndex);
                 assertTrue(img != null);
                 mOutputBuff.checksum(img);
+                int imgFormat = img.getFormat();
+                int bytesPerSample = (ImageFormat.getBitsPerPixel(imgFormat) * 2) / (8 * 3);
+
+                MediaFormat format = mCodec.getOutputFormat();
+                buf = mCodec.getOutputBuffer(bufferIndex);
+                int width = format.getInteger(MediaFormat.KEY_WIDTH);
+                int height = format.getInteger(MediaFormat.KEY_HEIGHT);
+                int stride = format.getInteger(MediaFormat.KEY_STRIDE);
+                mOutputBuff.checksum(buf, info.size, width, height, stride, bytesPerSample);
             }
         }
         if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
diff --git a/tests/media/src/android/mediav2/cts/ExtractorTest.java b/tests/media/src/android/mediav2/cts/ExtractorTest.java
index b7840db..502a5ba 100644
--- a/tests/media/src/android/mediav2/cts/ExtractorTest.java
+++ b/tests/media/src/android/mediav2/cts/ExtractorTest.java
@@ -1612,26 +1612,38 @@
                     }
                 }
                 extractor.release();
-                assertTrue(format != null);
+                assertTrue("missing track format from file " +  file, format != null);
                 if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-                    assertTrue(format.containsKey(MediaFormat.KEY_AAC_PROFILE) ||
+                    assertTrue("neither KEY_AAC_PROFILE nor KEY_PROFILE found in file " + file,
+                            format.containsKey(MediaFormat.KEY_AAC_PROFILE) ||
                             format.containsKey(MediaFormat.KEY_PROFILE));
                     if (format.containsKey(MediaFormat.KEY_AAC_PROFILE)) {
-                        assertEquals(mProfile, format.getInteger(MediaFormat.KEY_AAC_PROFILE));
+                        int profile = format.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
+                        assertEquals("mismatched KEY_AAC_PROFILE in file " + file,
+                                     mProfile, profile);
                     }
                     if (format.containsKey(MediaFormat.KEY_PROFILE)) {
-                        assertEquals(mProfile, format.getInteger(MediaFormat.KEY_PROFILE));
+                        int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
+                        assertEquals("mismatched KEY_PROFILE in file " + file, mProfile, profile);
                     }
                 } else {
-                    assertEquals(mProfile, format.getInteger(MediaFormat.KEY_PROFILE));
-                    assertEquals(mLevel, format.getInteger(MediaFormat.KEY_LEVEL));
+                    int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
+                    assertEquals("mismatched KEY_PROFILE in file " + file, mProfile, profile);
+                    int level = format.getInteger(MediaFormat.KEY_LEVEL, -1);
+                    assertEquals("mismatched KEY_LEVEL in file " + file, mLevel, level);
                 }
                 if (mMime.startsWith("audio/")) {
-                    assertEquals(mWR, format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
-                    assertEquals(mHCh, format.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
+                    int sample_rate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE, -1);
+                    assertEquals("mismatched KEY_SAMPLE_RATE in file " + file,
+                                 mWR, sample_rate);
+                    int channel_count = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT, -1);
+                    assertEquals("mismatched KEY_CHANNEL_COUNT in file " + file,
+                                 mHCh, channel_count);
                 } else if (mMime.startsWith("video/")) {
-                    assertEquals(mWR, format.getInteger(MediaFormat.KEY_WIDTH));
-                    assertEquals(mHCh, format.getInteger(MediaFormat.KEY_HEIGHT));
+                    int width = format.getInteger(MediaFormat.KEY_WIDTH, -1);
+                    assertEquals("mismatched KEY_WIDTH in file " + file, mWR, width);
+                    int height = format.getInteger(MediaFormat.KEY_HEIGHT, -1);
+                    assertEquals("mismatched KEY_HEIGHT in file " + file, mHCh, height);
                 }
             }
         }
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
index 904368d..dcc8995 100644
--- a/tests/mediapc/AndroidTest.xml
+++ b/tests/mediapc/AndroidTest.xml
@@ -26,7 +26,7 @@
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-1.1" />
+        <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-1.2" />
         <option name="dynamic-config-module" value="CtsMediaPerformanceClassTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/mediapc/DynamicConfig.xml b/tests/mediapc/DynamicConfig.xml
index 973305e..d7ba901 100644
--- a/tests/mediapc/DynamicConfig.xml
+++ b/tests/mediapc/DynamicConfig.xml
@@ -1,6 +1,6 @@
 <dynamicConfig>
     <entry key="media_files_url">
-      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.1.zip</value>
+      <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.2.zip</value>
     </entry>
 </dynamicConfig>
 
diff --git a/tests/mediapc/README.md b/tests/mediapc/README.md
index 1cb0ec5..f21aeb9 100644
--- a/tests/mediapc/README.md
+++ b/tests/mediapc/README.md
@@ -1,7 +1,7 @@
 ## Media Performance Class CTS Tests
 Current folder comprises of files necessary for testing media performance class.
 
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.1.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-1.2.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
 
 ### Commands
 ```sh
diff --git a/tests/mediapc/copy_media.sh b/tests/mediapc/copy_media.sh
index 20437d1..054fe76 100644
--- a/tests/mediapc/copy_media.sh
+++ b/tests/mediapc/copy_media.sh
@@ -17,7 +17,7 @@
 ## script to install media performance class test files manually
 
 adbOptions=" "
-resLabel=CtsMediaPerformanceClassTestCases-1.1
+resLabel=CtsMediaPerformanceClassTestCases-1.2
 srcDir="/tmp/$resLabel"
 tgtDir="/sdcard/test"
 usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
index ecc8c3a..c6a0c60 100644
--- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java
@@ -16,6 +16,11 @@
 
 package android.mediapc.cts;
 
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.graphics.ImageFormat;
 import android.media.Image;
 import android.media.MediaCodec;
@@ -43,11 +48,6 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 class CodecAsyncHandler extends MediaCodec.Callback {
     private static final String LOG_TAG = CodecAsyncHandler.class.getSimpleName();
     private final Lock mLock = new ReentrantLock();
@@ -729,28 +729,33 @@
 
 /**
  * The following class encodes a YUV video file to a given mimeType using encoder created by the
- * given encoderName and configuring to 720p 30fps format.
+ * given encoderName and configuring to 30fps format.
  */
 class Encode extends CodecEncoderTestBase implements Callable<Double> {
     private static final String LOG_TAG = Encode.class.getSimpleName();
 
     private final String mEncoderName;
     private final boolean mIsAsync;
+    private final int mBitrate;
 
-    Encode(String mime, String encoderName, boolean isAsync) {
+    Encode(String mime, String encoderName, boolean isAsync, int height, int width, int frameRate,
+            int bitrate) {
         super(mime);
         mEncoderName = encoderName;
         mIsAsync = isAsync;
         mSurface = MediaCodec.createPersistentInputSurface();
-        mFrameRate = 30;
+        mFrameRate = frameRate;
+        mBitrate = bitrate;
+        mHeight = height;
+        mWidth = width;
     }
 
     private MediaFormat setUpFormat() {
         MediaFormat format = new MediaFormat();
         format.setString(MediaFormat.KEY_MIME, mMime);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, 4000000);
-        format.setInteger(MediaFormat.KEY_WIDTH, 1280);
-        format.setInteger(MediaFormat.KEY_HEIGHT, 720);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
+        format.setInteger(MediaFormat.KEY_WIDTH, mWidth);
+        format.setInteger(MediaFormat.KEY_HEIGHT, mHeight);
         format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
         format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, 0);
         format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
index 6a2372f..9168e24 100644
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
@@ -16,6 +16,13 @@
 
 package android.mediapc.cts;
 
+import static android.mediapc.cts.CodecTestBase.selectCodecs;
+import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -34,9 +41,6 @@
 import androidx.test.rule.ActivityTestRule;
 
 import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.ReportLog;
-import com.android.compatibility.common.util.ReportLog.Metric;
-
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
@@ -55,13 +59,6 @@
 import java.util.Collection;
 import java.util.List;
 
-import static android.mediapc.cts.CodecTestBase.selectCodecs;
-import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
 /**
  * The following test class validates the codec initialization latency (time for codec create +
  * configure) for the audio encoders and hardware video encoders available in the device, under the
@@ -75,6 +72,8 @@
     private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS = 65;
     private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS = 40;
     private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS = 50;
+    private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS = 30;
+    private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS = 40;
 
     private static final int MAX_AUDIOENC_INITIALIZATION_LATENCY_MS;
     private static final int MAX_VIDEOENC_INITIALIZATION_LATENCY_MS;
@@ -88,10 +87,13 @@
         if (Utils.isRPerfClass()) {
             MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS;
             MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS;
-        } else {
-            // Performance class Build.VERSION_CODES.S and beyond
+        } else if (Utils.isSPerfClass()) {
             MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS;
             MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS;
+        } else {
+            // Performance class Build.VERSION_CODES.TIRAMISU and beyond
+            MAX_AUDIOENC_INITIALIZATION_LATENCY_MS = MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS;
+            MAX_VIDEOENC_INITIALIZATION_LATENCY_MS = MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS;
         }
     }
 
@@ -109,7 +111,7 @@
     public void setUp() throws Exception {
         Utils.assumeDeviceMeetsPerformanceClassPreconditions();
 
-        ArrayList<String>  listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
+        ArrayList<String> listOfAvcHwDecoders = selectHardwareCodecs(AVC, null, null, false);
         assumeFalse("Test requires h/w avc decoder", listOfAvcHwDecoders.isEmpty());
         AVC_DECODER_NAME = listOfAvcHwDecoders.get(0);
 
@@ -196,14 +198,15 @@
                 listOfEncoders = selectHardwareCodecs(mime, null, null, true);
             }
             for (String encoder : listOfEncoders) {
-                argsList.add(new Object[] {mime, encoder});
+                argsList.add(new Object[]{mime, encoder});
             }
         }
         return argsList;
     }
 
     private MediaRecorder createMediaRecorderLoad(Surface surface) throws Exception {
-        MediaRecorder mediaRecorder = new MediaRecorder();
+        MediaRecorder mediaRecorder = new MediaRecorder(InstrumentationRegistry.getInstrumentation()
+                .getContext());
         mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
         mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
         mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
@@ -259,7 +262,7 @@
             mMediaRecorderLoad.stop();
             mMediaRecorderLoad.release();
             mMediaRecorderLoad = null;
-            if(mTempRecordedFile != null && mTempRecordedFile.exists()) {
+            if (mTempRecordedFile != null && mTempRecordedFile.exists()) {
                 mTempRecordedFile.delete();
                 mTempRecordedFile = null;
             }
@@ -290,7 +293,7 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-7,H-1-8")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-7,H-1-8")
     public void testInitializationLatency() throws Exception {
         final int NUM_MEASUREMENTS = 5;
         // Test gathers initialization latency for a number of iterations and
@@ -328,17 +331,21 @@
                     expectedMaxCodecInitializationLatencyMs);
             assertTrue(errorLog, initializationLatency <= expectedMaxCodecInitializationLatencyMs);
         } else {
-            int pc = 0;
+            int pc;
             if (mMime.startsWith("audio/")) {
-                pc = initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS
-                        ? Build.VERSION_CODES.S
-                        : initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS
-                                ? Build.VERSION_CODES.R : 0;
+                pc = initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_T_MS ?
+                        Build.VERSION_CODES.TIRAMISU :
+                        initializationLatency < MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_S_MS ?
+                                Build.VERSION_CODES.S : initializationLatency <
+                                MAX_AUDIOENC_INITIALIZATION_LATENCY_PC_R_MS ?
+                                Build.VERSION_CODES.R : 0;
             } else {
-                pc = initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS
-                        ? Build.VERSION_CODES.S
-                        : initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS
-                                ? Build.VERSION_CODES.R : 0;
+                pc = initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_T_MS ?
+                        Build.VERSION_CODES.TIRAMISU :
+                        initializationLatency < MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_S_MS ?
+                                Build.VERSION_CODES.S : initializationLatency <
+                                MAX_VIDEOENC_INITIALIZATION_LATENCY_PC_R_MS ?
+                                Build.VERSION_CODES.R : 0;
             }
             DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",
                     "InitializationLatency_" + mEncoderName);
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index 07ee73a..a140c30 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -16,12 +16,16 @@
 
 package android.mediapc.cts;
 
+import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint;
 import android.media.MediaFormat;
-import android.util.Pair;
 import android.util.Log;
+import android.util.Pair;
+
 import org.junit.Before;
 
 import java.io.IOException;
@@ -31,10 +35,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
 public class MultiCodecPerfTestBase {
     private static final String LOG_TAG = MultiCodecPerfTestBase.class.getSimpleName();
     static final boolean[] boolStates = {true, false};
@@ -44,22 +44,24 @@
     // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as
     // passing the test
     static final double FPS_TOLERANCE_FACTOR = 0.95;
-    static ArrayList<String> mMimeList = new ArrayList<String>();
+    static ArrayList<String> mMimeList = new ArrayList<>();
     static Map<String, String> mTestFiles = new HashMap<>();
+    static Map<String, String> m720pTestFiles = new HashMap<>();
+
     static {
         mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
         mMimeList.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
 
-        mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4");
-        mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4");
+        m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4");
+        m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4");
 
         // Test VP9 and AV1 as well for Build.VERSION_CODES.S
         if (Utils.isSPerfClass()) {
             mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9);
             mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
 
-            mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
-            mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
+            m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm");
+            m720pTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4");
         }
     }
 
@@ -80,18 +82,14 @@
         mIsAsync = isAsync;
     }
 
-    // Returns the list of hardware codecs supporting the 720p 30fps format.
-    public static ArrayList<String> getHardwareCodecsFor720p(String mime, boolean isEncoder) {
-        MediaFormat fmt = MediaFormat.createVideoFormat(mime, 1280, 720);
-        fmt.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
-        ArrayList<MediaFormat> formatsList = new ArrayList<>();
-        formatsList.add(fmt);
-        return selectHardwareCodecs(mime, formatsList, null, isEncoder);
+    // Returns the list of hardware codecs for given mime
+    public static ArrayList<String> getHardwareCodecsForMime(String mime, boolean isEncoder) {
+        return selectHardwareCodecs(mime, null, null, isEncoder);
     }
 
-    // Returns the max number of 720p 30 fps instances that the given list of mimeCodecPairs
-    // supports. It also checks that the each codec supports 720p 180 fps PerformancePoint.
-    public int checkAndGetMaxSupportedInstancesFor720p(
+    // Returns the max number of 30 fps instances that the given list of mimeCodecPairs
+    // supports. It also checks that the each codec supports 180 fps PerformancePoint.
+    public int checkAndGetMaxSupportedInstancesForCodecCombinations(int height, int width,
             ArrayList<Pair<String, String>> mimeCodecPairs) throws IOException {
         int[] maxInstances = new int[mimeCodecPairs.size()];
         int[] maxFrameRates = new int[mimeCodecPairs.size()];
@@ -104,20 +102,17 @@
             List<PerformancePoint> pps = cap.getVideoCapabilities().getSupportedPerformancePoints();
             assertTrue(pps.size() > 0);
 
-            int requiredFrameRate = 180;
-            // VP9 requires 60 fps at 720p and minimum of 2 instances
-            if (mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-                requiredFrameRate = 60;
-            }
+            boolean hasVP9 = mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+            int requiredFrameRate = getRequiredMinConcurrentInstances(hasVP9) * 30;
 
             maxInstances[loopCount] = cap.getMaxSupportedInstances();
-            PerformancePoint PP720p = new PerformancePoint(1280, 720, requiredFrameRate);
+            PerformancePoint PPRes = new PerformancePoint(width, height, requiredFrameRate);
 
             maxMacroBlockRates[loopCount] = 0;
-            boolean supports720pPerformance = false;
+            boolean supportsResolutionPerformance = false;
             for (PerformancePoint pp : pps) {
-                if (pp.covers(PP720p)) {
-                    supports720pPerformance = true;
+                if (pp.covers(PPRes)) {
+                    supportsResolutionPerformance = true;
                     if (pp.getMaxMacroBlockRate() > maxMacroBlockRates[loopCount]) {
                         maxMacroBlockRates[loopCount] = (int) pp.getMaxMacroBlockRate();
                         maxFrameRates[loopCount] = pp.getMaxFrameRate();
@@ -125,9 +120,10 @@
                 }
             }
             codec.release();
-            if (!supports720pPerformance) {
-                Log.e(LOG_TAG, "Codec " + mimeCodecPair.second + " doesn't support 720p " +
-                        requiredFrameRate + " performance point");
+            if (!supportsResolutionPerformance) {
+                Log.e(LOG_TAG,
+                        "Codec " + mimeCodecPair.second + " doesn't support " + height + "p/" +
+                                requiredFrameRate + " performance point");
                 return 0;
             }
             loopCount++;
@@ -142,9 +138,17 @@
         // Allow a tolerance in expected frame rate
         mMaxFrameRate = minOfMaxFrameRates * FPS_TOLERANCE_FACTOR;
 
-        // Calculate how many 720p 30fps max instances it can support from it's mMaxFrameRate
-        // amd maxMacroBlockRate. (720p is 3,600 macro blocks assuming 16x16 macroblocks)
+        // Calculate how many 30fps max instances it can support from it's mMaxFrameRate
+        // amd maxMacroBlockRate. (assuming 16x16 macroblocks)
         return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0),
-                (int) (minOfMaxMacroBlockRates / 3600.0 / 30)));
+                (int) (minOfMaxMacroBlockRates / ((width / 16) * (height / 16)) / 30.0)));
+    }
+
+    public int getRequiredMinConcurrentInstances(boolean hasVP9) {
+        // Below T, VP9 requires 60 fps at 720p and minimum of 2 instances
+        if (!Utils.isTPerfClass() && hasVP9) {
+            return REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
+        }
+        return REQUIRED_MIN_CONCURRENT_INSTANCES;
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index bff0793..4899f83 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -16,6 +16,8 @@
 
 package android.mediapc.cts;
 
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaFormat;
 import android.os.Build;
 import android.util.Pair;
@@ -28,6 +30,7 @@
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -35,12 +38,11 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class calculates the maximum number of concurrent decode sessions that it can
  * support by the two hardware (mime - decoder) pair calculated via the
@@ -71,7 +73,7 @@
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
-            ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
+            ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false);
             for (String decoder : listOfDecoders) {
                 mimeTypeDecoderPairs.add(Pair.create(mime, decoder));
             }
@@ -96,17 +98,24 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-1,H-1-2")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
     public void test720p() throws Exception {
+        Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+
+        boolean hasVP9 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) ||
+                mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+        int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9);
+        testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
+    }
+
+    private void testCodec(Map<String, String> testFiles, int height, int width,
+            int requiredMinInstances) throws Exception {
+        mTestFiles = testFiles;
         ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>();
         mimeDecoderPairs.add(mFirstPair);
         mimeDecoderPairs.add(mSecondPair);
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeDecoderPairs);
-        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
-        if (mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
-                || mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
-        }
+        int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
+                mimeDecoderPairs);
         double achievedFrameRate = 0.0;
         if (maxInstances >= requiredMinInstances) {
             int secondPairInstances = maxInstances / 2;
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index 3e3881b..cbdd391 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -15,6 +15,9 @@
  */
 
 package android.mediapc.cts;
+
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaFormat;
 import android.os.Build;
 import android.util.Pair;
@@ -27,6 +30,7 @@
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -34,12 +38,11 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class validates the maximum number of concurrent decode sessions that it can
  * support by the hardware decoders calculated via the CodecCapabilities.getMaxSupportedInstances()
@@ -52,23 +55,22 @@
 
     private final String mDecoderName;
 
-    public MultiDecoderPerfTest(String mimeType, String testFile, String decoderName,
-            boolean isAsync) {
-        super(mimeType, testFile, isAsync);
+    public MultiDecoderPerfTest(String mimeType, String decoderName, boolean isAsync) {
+        super(mimeType, null, isAsync);
         mDecoderName = decoderName;
     }
 
-    // Returns the params list with the mime, testFile and their hardware decoders in
+    // Returns the params list with the mime and corresponding hardware decoders in
     // both sync and async modes.
-    // Parameters {0}_{2}_{3} -- Mime_DecoderName_isAsync
-    @Parameterized.Parameters(name = "{index}({0}_{2}_{3})")
+    // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{2})")
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
-            ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
+            ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false);
             for (String decoder : listOfDecoders) {
                 for (boolean isAsync : boolStates) {
-                    argsList.add(new Object[]{mime, mTestFiles.get(mime), decoder, isAsync});
+                    argsList.add(new Object[]{mime, decoder, isAsync});
                 }
             }
         }
@@ -82,15 +84,23 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-1,H-1-2")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2")
     public void test720p() throws Exception {
+        Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+
+        boolean hasVP9 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+        int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9);
+        testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
+    }
+
+    private void testCodec(Map<String, String> testFiles, int height, int width,
+            int requiredMinInstances) throws Exception {
+        mTestFile = testFiles.get(mMime);
         ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>();
         mimeDecoderPairs.add(Pair.create(mMime, mDecoderName));
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeDecoderPairs);
-        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
-        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
-        }
+        int maxInstances =
+                checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
+                        mimeDecoderPairs);
         double achievedFrameRate = 0.0;
         if (maxInstances >= requiredMinInstances) {
             ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
@@ -124,6 +134,5 @@
                     ResultUnit.NONE);
             log.submit(InstrumentationRegistry.getInstrumentation());
         }
-
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index 4cd2a0c..b9cc45d 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -16,8 +16,11 @@
 
 package android.mediapc.cts;
 
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaFormat;
 import android.os.Build;
+import android.util.Log;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -27,6 +30,8 @@
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
+
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -38,7 +43,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import static org.junit.Assert.assertTrue;
 /**
  * The following test class calculates the maximum number of concurrent encode sessions that it can
  * support by the two hardware (mime - encoder) pair calculated via the
@@ -69,7 +73,7 @@
         final List<Object[]> argsList = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
-            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
+            ArrayList<String> listOfEncoders = getHardwareCodecsForMime(mime, true);
             for (String encoder : listOfEncoders) {
                 mimeTypeEncoderPairs.add(Pair.create(mime, encoder));
             }
@@ -94,39 +98,50 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-3,H-1-4")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-3,H-1-4")
     public void test720p() throws Exception {
+        Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+
+        boolean hasVP9 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) ||
+                mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+        int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9);
+        testCodec(720, 1280, 4000000, requiredMinInstances);
+    }
+
+    private void testCodec(int height, int width, int bitrate, int requiredMinInstances)
+            throws Exception {
         ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
         mimeEncoderPairs.add(mFirstPair);
         mimeEncoderPairs.add(mSecondPair);
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeEncoderPairs);
-        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
-        if (mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
-                || mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
-        }
+        int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
+                mimeEncoderPairs);
+        double achievedFrameRate = 0.0;
         if (maxInstances >= requiredMinInstances) {
             int secondPairInstances = maxInstances / 2;
             int firstPairInstances = maxInstances - secondPairInstances;
             ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
             List<Encode> testList = new ArrayList<>();
             for (int i = 0; i < firstPairInstances; i++) {
-                testList.add(new Encode(mFirstPair.first, mFirstPair.second, mIsAsync));
+                testList.add(
+                        new Encode(mFirstPair.first, mFirstPair.second, mIsAsync, height, width, 30,
+                                bitrate));
             }
             for (int i = 0; i < secondPairInstances; i++) {
-                testList.add(new Encode(mSecondPair.first, mSecondPair.second, mIsAsync));
+                testList.add(
+                        new Encode(mSecondPair.first, mSecondPair.second, mIsAsync, height, width,
+                                30, bitrate));
             }
             List<Future<Double>> resultList = pool.invokeAll(testList);
-            double achievedFrameRate = 0.0;
             for (Future<Double> result : resultList) {
                 achievedFrameRate += result.get();
             }
         }
-        // Achieved frame rate is not compared as this test runs in byte buffer mode.
         if (Utils.isPerfClass()) {
             assertTrue("Encoder pair " + mFirstPair.second + " and " + mSecondPair.second
                     + " unable to support minimum concurrent instances. act/exp: " + maxInstances
                     + "/" + requiredMinInstances, maxInstances >= requiredMinInstances);
+            Log.v(LOG_TAG, "Achieved fps: " + achievedFrameRate +
+                    "\nAchieved frame rate is not compared as this test runs in byte buffer mode");
         } else {
             int pc = maxInstances >= requiredMinInstances ? Build.VERSION_CODES.R : 0;
             DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index f45c411..79a684e 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -15,8 +15,12 @@
  */
 
 package android.mediapc.cts;
+
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaFormat;
 import android.os.Build;
+import android.util.Log;
 import android.util.Pair;
 
 import androidx.test.filters.LargeTest;
@@ -27,6 +31,7 @@
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -38,8 +43,6 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class validates the maximum number of concurrent encode sessions that it can
  * support by the hardware encoders calculated via the CodecCapabilities.getMaxSupportedInstances()
@@ -65,7 +68,7 @@
     public static Collection<Object[]> inputParams() {
         final List<Object[]> argsList = new ArrayList<>();
         for (String mime : mMimeList) {
-            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
+            ArrayList<String> listOfEncoders = getHardwareCodecsForMime(mime, true);
             for (String encoder : listOfEncoders) {
                 for (boolean isAsync : boolStates) {
                     argsList.add(new Object[]{mime, encoder, isAsync});
@@ -81,23 +84,29 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-3,H-1-4")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-3,H-1-4")
     public void test720p() throws Exception {
+        Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+
+        boolean hasVP9 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+        int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9);
+        testCodec(720, 1280, 4000000, requiredMinInstances);
+    }
+
+    private void testCodec(int height, int width, int bitrate, int requiredMinInstances)
+            throws Exception {
         ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>();
         mimeEncoderPairs.add(Pair.create(mMime, mEncoderName));
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeEncoderPairs);
-        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES;
-        if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9;
-        }
+        int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width,
+                mimeEncoderPairs);
+        double achievedFrameRate = 0.0;
         if (maxInstances >= requiredMinInstances) {
             ExecutorService pool = Executors.newFixedThreadPool(maxInstances);
             List<Encode> testList = new ArrayList<>();
             for (int i = 0; i < maxInstances; i++) {
-                testList.add(new Encode(mMime, mEncoderName, mIsAsync));
+                testList.add(new Encode(mMime, mEncoderName, mIsAsync, height, width, 30, bitrate));
             }
             List<Future<Double>> resultList = pool.invokeAll(testList);
-            double achievedFrameRate = 0.0;
             for (Future<Double> result : resultList) {
                 achievedFrameRate += result.get();
             }
@@ -107,6 +116,8 @@
             assertTrue("Encoder " + mEncoderName + " unable to support minimum concurrent " +
                             "instances. act/exp: " + maxInstances + "/" + requiredMinInstances,
                     maxInstances >= requiredMinInstances);
+            Log.v(LOG_TAG, "Achieved fps: " + achievedFrameRate +
+                    "\nAchieved frame rate is not compared as this test runs in byte buffer mode");
         } else {
             int pc = maxInstances >= requiredMinInstances ? Build.VERSION_CODES.R : 0;
             DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index 29c8dcb..98c3183 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -15,20 +15,24 @@
  */
 
 package android.mediapc.cts;
+
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaFormat;
 import android.os.Build;
 import android.util.Pair;
 import android.view.Surface;
 
 import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
 
 import com.android.compatibility.common.util.CddTest;
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
 
+import org.junit.Assume;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,12 +41,11 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class validates the maximum number of concurrent Transcode sessions that
  * it can support by the (mime, decoder - mime, encoder) pair calculated via the
@@ -77,11 +80,11 @@
         ArrayList<Pair<String, String>> mimeTypeDecoderPairs = new ArrayList<>();
         ArrayList<Pair<String, String>> mimeTypeEncoderPairs = new ArrayList<>();
         for (String mime : mMimeList) {
-            ArrayList<String> listOfDecoders = getHardwareCodecsFor720p(mime, false);
+            ArrayList<String> listOfDecoders = getHardwareCodecsForMime(mime, false);
             for (String decoder : listOfDecoders) {
                 mimeTypeDecoderPairs.add(Pair.create(mime, decoder));
             }
-            ArrayList<String> listOfEncoders = getHardwareCodecsFor720p(mime, true);
+            ArrayList<String> listOfEncoders = getHardwareCodecsForMime(mime, true);
             for (String encoder : listOfEncoders) {
                 mimeTypeEncoderPairs.add(Pair.create(mime, encoder));
             }
@@ -97,7 +100,7 @@
     }
 
     /**
-     * This test calculates the validates number of concurrent Transcode sessions that
+     * This test calculates the validates number of concurrent 720p Transcode sessions that
      * it can support by the (mime, decoder - mime, encoder) pairs. Creates maxInstances / 2
      * Transcode sessions. If maximum instances is odd, creates one additional decoder which decodes
      * to surface and render. And ensures that all the supported sessions succeed in
@@ -105,25 +108,32 @@
      */
     @LargeTest
     @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
-    @CddTest(requirement="2.2.7.1/5.1/H-1-5,H-1-6")
+    @CddTest(requirement = "2.2.7.1/5.1/H-1-5,H-1-6")
     public void test720p() throws Exception {
+        Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass());
+
+        boolean hasVP9 = mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
+                || mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9);
+        int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9) / 2;
+        testCodec(m720pTestFiles, 720, 1280, requiredMinInstances);
+    }
+
+    private void testCodec(Map<String, String> testFiles, int height, int width,
+            int requiredMinInstances) throws Exception {
+        mTestFiles = testFiles;
         ArrayList<Pair<String, String>> mimeCodecPairs = new ArrayList<>();
         mimeCodecPairs.add(mDecoderPair);
         mimeCodecPairs.add(mEncoderPair);
-        int maxInstances = checkAndGetMaxSupportedInstancesFor720p(mimeCodecPairs);
-        int requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES / 2;
-        if (mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)
-                || mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-            requiredMinInstances = REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 / 2;
-        }
+        int maxInstances =
+                checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, mimeCodecPairs);
         double achievedFrameRate = 0.0;
         if (maxInstances >= requiredMinInstances) {
-            ExecutorService pool = Executors.newFixedThreadPool(
-                    maxInstances / 2 + maxInstances % 2);
+            ExecutorService pool =
+                    Executors.newFixedThreadPool(maxInstances / 2 + maxInstances % 2);
             List<Transcode> transcodeList = new ArrayList<>();
             for (int i = 0; i < maxInstances / 2; i++) {
-                transcodeList.add(
-                        new Transcode(mEncoderPair.first, mTestFiles.get(mDecoderPair.first),
+                transcodeList
+                        .add(new Transcode(mEncoderPair.first, mTestFiles.get(mDecoderPair.first),
                                 mDecoderPair.second, mEncoderPair.second, mIsAsync));
             }
             List<Future<Double>> decodeResultList = null;
@@ -133,7 +143,7 @@
                 Surface surface = mActivityRule.getActivity().getSurface();
                 assertTrue("Surface created is null.", surface != null);
                 assertTrue("Surface created is invalid.", surface.isValid());
-                mActivityRule.getActivity().setScreenParams(1280, 720, true);
+                mActivityRule.getActivity().setScreenParams(width, height, true);
                 decodeList.add(new DecodeToSurface(mDecoderPair.first,
                         mTestFiles.get(mDecoderPair.first), mDecoderPair.second, surface,
                         mIsAsync));
@@ -173,6 +183,5 @@
                     ResultUnit.NONE);
             log.submit(InstrumentationRegistry.getInstrumentation());
         }
-
     }
 }
diff --git a/tests/mediapc/src/android/mediapc/cts/WorkDir.java b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
index d45c14b..cd5ad7e 100644
--- a/tests/mediapc/src/android/mediapc/cts/WorkDir.java
+++ b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
@@ -40,7 +40,7 @@
             // user has specified the mediaDirString via instrumentation-arg
             return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
         } else {
-            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-1.1/");
+            return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-1.2/");
         }
     }
 }
diff --git a/tests/sensor/src/android/hardware/cts/SensorTest.java b/tests/sensor/src/android/hardware/cts/SensorTest.java
index e4f4613..c73f581 100644
--- a/tests/sensor/src/android/hardware/cts/SensorTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorTest.java
@@ -242,15 +242,23 @@
         sensor =  mSensorManager.getDefaultSensor(Sensor.TYPE_HEADING);
         boolean hasHeadingSensor = getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_SENSOR_HEADING);
-        if (hasHeadingSensor) {
+        boolean isAutomotive = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE);
+        if (isAutomotive && hasHeadingSensor) {
             assertNotNull(sensor);
             assertEquals(Sensor.TYPE_HEADING, sensor.getType());
             assertSensorValues(sensor);
             assertTrue("Max range must not be greater or equal to 360. Range="
                     + sensor.getMaximumRange() + " " + sensor.getName(),
                     sensor.getMaximumRange() < 360);
-        } else {
+        } else if (isAutomotive) {
             assertNull(sensor);
+        } else {
+            // There isn't good test coverage for heading, particularly for non-automotive devices.
+            // So if a non-automotive device wants to implement this, requirements for the sensor
+            // and how to test for those requirements should be re-discussed.
+            assertNull("If the heading sensor is being implemented on a non-automotive device, "
+                    + "the team would love to hear from you. Please reach out!", sensor);
         }
     }
 
@@ -268,41 +276,6 @@
         }
     }
 
-    public void testLimitedAxesImuConfiguration() {
-        boolean hasAccelerometer = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_ACCELEROMETER);
-        boolean hasLimitedAxesAccelerometer = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES);
-        boolean hasLimitedAxesAccelerometerUncalibrated =
-                getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED);
-
-        // Only the 3-axis accelerometer or the limited axes accelerometer should be implemented
-        // by the system at the same time. The composite sensors for limited axes accelerometer can
-        // still be present when a 3-axis accelerometer is supported.
-        if (hasAccelerometer) {
-            assertFalse(hasLimitedAxesAccelerometer);
-            assertFalse(hasLimitedAxesAccelerometerUncalibrated);
-        }
-
-        boolean hasGyroscope = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_GYROSCOPE);
-        boolean hasLimitedAxesGyroscope = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES);
-        boolean hasLimitedAxesGyroscopeUncalibrated =
-                getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_SENSOR_GYROSCOPE_LIMITED_AXES_UNCALIBRATED);
-
-
-        // Only the 3-axis gyroscope or the limited axes gyroscope should be implemented by the
-        // system at the same time. The composite sensors for limited axes gyroscope can still be
-        // present when a 3-axis gyroscope is supported.
-        if (hasGyroscope) {
-            assertFalse(hasLimitedAxesGyroscope);
-            assertFalse(hasLimitedAxesGyroscopeUncalibrated);
-        }
-    }
-
     @AppModeFull(reason = "Instant apps cannot access body sensors")
     public void testBodySensorOperations() {
         Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE);
diff --git a/tests/sensor/src/android/hardware/cts/SingleSensorTests.java b/tests/sensor/src/android/hardware/cts/SingleSensorTests.java
index 4d4768a..a782eb6 100644
--- a/tests/sensor/src/android/hardware/cts/SingleSensorTests.java
+++ b/tests/sensor/src/android/hardware/cts/SingleSensorTests.java
@@ -181,7 +181,7 @@
     }
 
     public void testAccelerometer_automotive() throws Throwable {
-        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_25HZ, true);
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_100HZ, true);
     }
 
     public void testAccelUncalibrated_fastest() throws Throwable {
@@ -220,6 +220,10 @@
         runSensorTest(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED, RATE_1HZ);
     }
 
+    public void testAccelUncalibrated_automotive() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED, RATE_100HZ, true);
+    }
+
     public void testMagneticField_fastest() throws Throwable {
         runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST);
     }
@@ -625,7 +629,7 @@
     }
 
     public void testAccelerometerLimitedAxes_automotive() throws Throwable {
-        runSensorTest(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES, RATE_25HZ, true);
+        runSensorTest(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES, RATE_100HZ, true);
     }
 
     public void testAccelerometerLimitedAxesUncalibrated_fastest() throws Throwable {
@@ -666,7 +670,7 @@
     }
 
     public void testAccelerometerLimitedAxesUncalibrated_automotive() throws Throwable {
-        runSensorTest(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED, RATE_25HZ, true);
+        runSensorTest(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED, RATE_100HZ, true);
     }
 
     public void testGyroscopeLimitedAxes_fastest() throws Throwable {
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
index 489bbcc..c66d2c3 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
@@ -307,6 +307,21 @@
                         new float[]{0.0f, 0.0f, SensorManager.STANDARD_GRAVITY},
                         new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */,
                         new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */));
+        defaults.put(Sensor.TYPE_ACCELEROMETER_UNCALIBRATED,
+                new ExpectedValuesAndThresholds(
+                        new float[]{0.0f, 0.0f, SensorManager.STANDARD_GRAVITY, 0.0f, 0.0f, 0.0f},
+                        new float[]{1.95f,
+                                    1.95f,
+                                    1.95f,
+                                    Float.MAX_VALUE,
+                                    Float.MAX_VALUE,
+                                    Float.MAX_VALUE},
+                        new float[]{1.95f,
+                                    1.95f,
+                                    1.95f,
+                                    Float.MAX_VALUE,
+                                    Float.MAX_VALUE,
+                                    Float.MAX_VALUE}));
 
         defaults.put(Sensor.TYPE_ACCELEROMETER_LIMITED_AXES,
                 new ExpectedValuesAndThresholds(
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index 14b822b..259e002 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -776,6 +776,56 @@
         });
     }
 
+    @Test
+    public void testRegisterAndUnregisterDurationScaleListener() {
+        ValueAnimator.DurationScaleChangeListener listener = scale -> {
+            return;
+        };
+        assertTrue("Listener not registered",
+                ValueAnimator.registerDurationScaleChangeListener(listener));
+        assertFalse("Listener was registered again",
+                ValueAnimator.registerDurationScaleChangeListener(listener));
+        assertTrue("Listener not unregistered",
+                ValueAnimator.unregisterDurationScaleChangeListener(listener));
+        assertFalse("Listener was unregistered again",
+                ValueAnimator.unregisterDurationScaleChangeListener(listener));
+    }
+
+    @Test
+    public void testGetDurationScale() {
+        float currentDurationScale = ValueAnimator.getDurationScale();
+        try {
+            ValueAnimator.setDurationScale(0f);
+            assertEquals(0f, ValueAnimator.getDurationScale(), 0.0f);
+        } finally {
+            // restore scale value to avoid messing up future tests
+            ValueAnimator.setDurationScale(currentDurationScale);
+        }
+
+    }
+
+    @Test
+    public void testDurationScaleListenerOnChange() throws InterruptedException {
+        float currentDurationScale = ValueAnimator.getDurationScale();
+
+        ValueAnimator.setDurationScale(1f);
+        final CountDownLatch durationScaleUpdateLatch = new CountDownLatch(1);
+        ValueAnimator.DurationScaleChangeListener listener = scale -> {
+            assertEquals(0f, ValueAnimator.getDurationScale(), 0.0f);
+            durationScaleUpdateLatch.countDown();
+        };
+
+        try {
+            ValueAnimator.registerDurationScaleChangeListener(listener);
+            ValueAnimator.setDurationScale(0f);
+            assertTrue(durationScaleUpdateLatch.await(100, TimeUnit.MILLISECONDS));
+        } finally {
+            ValueAnimator.unregisterDurationScaleChangeListener(listener);
+            // restore scale value to avoid messing up future tests
+            ValueAnimator.setDurationScale(currentDurationScale);
+        }
+    }
+
     private ValueAnimator getAnimator() {
         Object object = mActivity.view.newBall;
         String property = "y";
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
index 4b12120..04060fa 100644
--- a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
@@ -16,6 +16,7 @@
 package android.app.cts;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
@@ -62,4 +63,36 @@
         assertNull(params.getActions());
         assertNull(params.getSourceRectHint());
     }
+
+    @Test
+    public void testBuilderDefaultCtor() {
+        // Construct the params with default Builder constructor
+        PictureInPictureParams params = new Builder().build();
+
+        // Ensures the PictureInPictureParams constructed has nothing being set
+        assertFalse(params.hasSetAspectRatio());
+        assertFalse(params.hasSetExpandedAspectRatio());
+        assertFalse(params.hasSetActions());
+        assertFalse(params.hasSetCloseAction());
+        assertFalse(params.hasSetTitle());
+        assertFalse(params.hasSetSubtitle());
+    }
+
+    @Test
+    public void testBuilderCopyCtor() {
+        // Construct a PictureInPictureParams with some parameters being set
+        PictureInPictureParams params = new Builder()
+                .setAspectRatio(new Rational(1, 2))
+                .setActions(new ArrayList<>())
+                .setSourceRectHint(new Rect(0, 0, 100, 100))
+                .build();
+
+        // Build a new PictureInPictureParams using the copy constructor
+        PictureInPictureParams newParams = new Builder(params).build();
+
+        // Ensures the two PictureInPictureParams share the same parameters
+        assertEquals(params.getAspectRatioRational(), newParams.getAspectRatioRational());
+        assertEquals(params.getActions(), params.getActions());
+        assertEquals(params.getSourceRectHint(), params.getSourceRectHint());
+    }
 }
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index 354ba27..9f2d821 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -2016,6 +2016,36 @@
                 is(emptyOrNullString()));
     }
 
+    @Test
+    public void makeUidVisible_throwsException() throws Exception {
+        final int recipientUid = sPm.getPackageUid(
+                QUERIES_NOTHING, PackageManager.PackageInfoFlags.of(0));
+        final int visibleUid = sPm.getPackageUid(
+                TARGET_NO_API, PackageManager.PackageInfoFlags.of(0));
+        assertThrows(SecurityException.class,
+                () -> sPm.makeUidVisible(recipientUid, visibleUid));
+    }
+
+    @Test
+    public void makeUidVisible_queriesNothing_canSeeStub() throws Exception {
+        ensurePackageIsInstalled(TARGET_STUB, TARGET_STUB_APK);
+        try {
+            assertNotVisible(QUERIES_NOTHING, TARGET_STUB);
+
+            final int recipientUid = sPm.getPackageUid(
+                    QUERIES_NOTHING, PackageManager.PackageInfoFlags.of(0));
+            final int visibleUid = sPm.getPackageUid(
+                    TARGET_STUB, PackageManager.PackageInfoFlags.of(0));
+            SystemUtil.runWithShellPermissionIdentity(
+                    () -> sPm.makeUidVisible(recipientUid, visibleUid),
+                            Manifest.permission.MAKE_UID_VISIBLE);
+
+            assertVisible(QUERIES_NOTHING, TARGET_STUB);
+        } finally {
+            ensurePackageIsNotInstalled(TARGET_STUB);
+        }
+    }
+
     private void assertNotVisible(String sourcePackageName, String targetPackageName)
             throws Exception {
         if (!sGlobalFeatureEnabled) return;
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
index 48bdf6d..3d067c0 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
@@ -346,8 +346,10 @@
   ASSERT_OK(iface->RepeatInterface(empty, &ret));
   EXPECT_EQ(empty.get(), ret.get());
 
-  // interfaces are always nullable in AIDL C++, and that behavior was carried
-  // over to the NDK backend for consistency
+  // b/210547999
+  // interface writes are always nullable in AIDL C++ (but reads are not
+  // nullable by default). However, the NDK backend follows the Java behavior
+  // and always allows interfaces to be nullable (for reads and writes).
   ASSERT_OK(iface->RepeatInterface(nullptr, &ret));
   EXPECT_EQ(nullptr, ret.get());
 
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
index c5d45a2..15c4f1c 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -414,7 +414,7 @@
         assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
 
         // Verify return value if Bluetooth is not enabled
-        assertNull(mAdapter.getUuids());
+        assertEquals(mAdapter.getUuids().length, 0);
 
     }
 
@@ -440,7 +440,7 @@
 
     public void test_BluetoothConnectionCallback_disconnectReasonText() {
         assertEquals("Reason unknown", BluetoothAdapter.BluetoothConnectionCallback
-                .disconnectReasonText(BluetoothStatusCodes.ERROR_UNKNOWN));
+                .disconnectReasonToString(BluetoothStatusCodes.ERROR_UNKNOWN));
     }
 
     public void test_registerBluetoothConnectionCallback() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCodecsTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCodecsTest.java
new file mode 100644
index 0000000..10c18a2
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCodecsTest.java
@@ -0,0 +1,302 @@
+/*
+ * 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 android.bluetooth.cts;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.test.AndroidTestCase;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class BluetoothCodecsTest extends AndroidTestCase {
+    private static final String TAG = BluetoothCodecsTest.class.getSimpleName();
+
+    // Codec configs: A and B are same; C is different
+    private static final BluetoothCodecConfig config_A =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig config_B =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig config_C =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    // Local capabilities: A and B are same; C is different
+    private static final BluetoothCodecConfig local_capability1_A =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability1_B =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability1_C =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability2_A =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability2_B =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability2_C =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    // Selectable capabilities: A and B are same; C is different
+    private static final BluetoothCodecConfig selectable_capability1_A =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability1_B =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability1_C =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_A =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_B =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_C =
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A =
+            new ArrayList() {{
+                    add(local_capability1_A);
+                    add(local_capability2_A);
+            }};
+
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B =
+            new ArrayList() {{
+                    add(local_capability1_B);
+                    add(local_capability2_B);
+            }};
+
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C =
+            new ArrayList() {{
+                    add(local_capability1_C);
+                    add(local_capability2_C);
+            }};
+
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A =
+            new ArrayList() {{
+                    add(selectable_capability1_A);
+                    add(selectable_capability2_A);
+            }};
+
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B =
+            new ArrayList() {{
+                    add(selectable_capability1_B);
+                    add(selectable_capability2_B);
+            }};
+
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C =
+            new ArrayList() {{
+                    add(selectable_capability1_C);
+                    add(selectable_capability2_C);
+            }};
+
+    private static final BluetoothCodecStatus bcs_A =
+            new BluetoothCodecStatus.Builder()
+                    .setCodecConfig(config_A)
+                    .setCodecsLocalCapabilities(LOCAL_CAPABILITY_A)
+                    .setCodecsSelectableCapabilities(SELECTABLE_CAPABILITY_A)
+                    .build();
+    private static final BluetoothCodecStatus bcs_B =
+            new BluetoothCodecStatus.Builder()
+                    .setCodecConfig(config_B)
+                    .setCodecsLocalCapabilities(LOCAL_CAPABILITY_B)
+                    .setCodecsSelectableCapabilities(SELECTABLE_CAPABILITY_B)
+                    .build();
+    private static final BluetoothCodecStatus bcs_C =
+            new BluetoothCodecStatus.Builder()
+                    .setCodecConfig(config_C)
+                    .setCodecsLocalCapabilities(LOCAL_CAPABILITY_C)
+                    .setCodecsSelectableCapabilities(SELECTABLE_CAPABILITY_C)
+                    .build();
+
+    public void test_BluetoothCodecStatusBuilder() {
+        BluetoothCodecStatus builderConfig = new BluetoothCodecStatus.Builder()
+                .setCodecConfig(config_A)
+                .setCodecsLocalCapabilities(LOCAL_CAPABILITY_B)
+                .setCodecsSelectableCapabilities(SELECTABLE_CAPABILITY_C)
+                .build();
+
+        assertTrue(Objects.equals(builderConfig.getCodecConfig(), config_A));
+        assertTrue(Objects.equals(builderConfig.getCodecsLocalCapabilities(),
+                LOCAL_CAPABILITY_B));
+        assertTrue(Objects.equals(builderConfig.getCodecsSelectableCapabilities(),
+                SELECTABLE_CAPABILITY_C));
+    }
+
+    public void test_BluetoothCodecConfigBuilder() {
+        BluetoothCodecConfig builderConfig = new BluetoothCodecConfig.Builder()
+                .setCodecType(config_A.getCodecType())
+                .setCodecPriority(config_A.getCodecPriority())
+                .setSampleRate(config_A.getSampleRate())
+                .setBitsPerSample(config_A.getBitsPerSample())
+                .setChannelMode(config_A.getChannelMode())
+                .setCodecSpecific1(config_A.getCodecSpecific1())
+                .setCodecSpecific2(config_A.getCodecSpecific2())
+                .setCodecSpecific3(config_A.getCodecSpecific3())
+                .setCodecSpecific4(config_A.getCodecSpecific4())
+                .build();
+
+        assertTrue(Objects.equals(builderConfig, config_A));
+        assertTrue(builderConfig.isMandatoryCodec());
+    }
+
+    public void test_GetCodecConfig() {
+        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_A));
+        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B));
+        assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C));
+    }
+
+    public void test_CodecsCapabilities() {
+        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A));
+        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B));
+        assertFalse(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C));
+
+        assertTrue(bcs_A.getCodecsSelectableCapabilities()
+                                 .equals(SELECTABLE_CAPABILITY_A));
+        assertTrue(bcs_A.getCodecsSelectableCapabilities()
+                                  .equals(SELECTABLE_CAPABILITY_B));
+        assertFalse(bcs_A.getCodecsSelectableCapabilities()
+                                  .equals(SELECTABLE_CAPABILITY_C));
+    }
+
+    public void test_IsCodecConfigSelectable() {
+        assertFalse(bcs_A.isCodecConfigSelectable(null));
+        assertTrue(bcs_A.isCodecConfigSelectable(selectable_capability1_C));
+        assertTrue(bcs_A.isCodecConfigSelectable(selectable_capability2_C));
+
+        // Not selectable due to multiple channel modes
+        assertFalse(bcs_A.isCodecConfigSelectable(selectable_capability1_A));
+        assertFalse(bcs_A.isCodecConfigSelectable(selectable_capability1_B));
+        assertFalse(bcs_A.isCodecConfigSelectable(selectable_capability2_A));
+        assertFalse(bcs_A.isCodecConfigSelectable(selectable_capability2_B));
+    }
+
+    private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
+            int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
+            long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
+        return new BluetoothCodecConfig.Builder()
+                    .setCodecType(sourceCodecType)
+                    .setCodecPriority(codecPriority)
+                    .setSampleRate(sampleRate)
+                    .setBitsPerSample(bitsPerSample)
+                    .setChannelMode(channelMode)
+                    .setCodecSpecific1(codecSpecific1)
+                    .setCodecSpecific2(codecSpecific2)
+                    .setCodecSpecific3(codecSpecific3)
+                    .setCodecSpecific4(codecSpecific4)
+                    .build();
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
index af30292..0100442 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
@@ -115,6 +115,21 @@
     }
 
     @Test
+    public void testCreateCodecConfigMetadataFromCopy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                new BluetoothLeAudioCodecConfigMetadata.Builder()
+                        .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+        BluetoothLeAudioCodecConfigMetadata codecMetadataCopy =
+                new BluetoothLeAudioCodecConfigMetadata.Builder(codecMetadata).build();
+        assertEquals(codecMetadata, codecMetadataCopy);
+        assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadataCopy.getAudioLocation());
+        assertArrayEquals(TEST_METADATA_BYTES, codecMetadata.getRawMetadata());
+    }
+
+    @Test
     public void testCreateCodecConfigMetadataFromBytes() {
         if (shouldSkipTest()) {
             return;
@@ -124,8 +139,7 @@
         byte[] metadataBytes = codecMetadata.getRawMetadata();
         assertNotNull(metadataBytes);
         assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
-        // TODO: Implement implicit LTV byte conversion in the API class
-        // assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
+        assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
     }
 
     private boolean shouldSkipTest() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
index 6c32580..08deed4 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
@@ -117,8 +117,22 @@
                         .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
         assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
         assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
-        // TODO: Implement implicit LTV byte conversion in the API class
-        // assertArrayEquals(TEST_METADATA_BYTES, contentMetadata.getRawMetadata());
+        assertArrayEquals(TEST_METADATA_BYTES, contentMetadata.getRawMetadata());
+    }
+
+    @Test
+    public void testCreateCodecConfigMetadataFromCopy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioContentMetadata contentMetadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
+        BluetoothLeAudioContentMetadata contentMetadataCopy =
+                new BluetoothLeAudioContentMetadata.Builder(contentMetadata).build();
+        assertEquals(TEST_PROGRAM_INFO, contentMetadataCopy.getProgramInfo());
+        assertEquals(TEST_LANGUAGE, contentMetadataCopy.getLanguage());
+        assertArrayEquals(TEST_METADATA_BYTES, contentMetadataCopy.getRawMetadata());
     }
 
     @Test
@@ -131,9 +145,8 @@
         byte[] metadataBytes = contentMetadata.getRawMetadata();
         assertNotNull(metadataBytes);
         assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
-        // TODO: Implement implicit LTV byte conversion in the API class
-        // assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
-        // assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
+        assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
+        assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
     }
 
     private boolean shouldSkipTest() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
index 6b349e7..1c0cb12 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeAudioCodecStatus;
 import android.bluetooth.BluetoothLeAudioCodecConfig;
 import android.bluetooth.BluetoothManager;
 import android.bluetooth.BluetoothProfile;
@@ -35,6 +36,7 @@
 import com.android.compatibility.common.util.ApiLevelUtil;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
@@ -176,47 +178,27 @@
                 mBluetoothLeAudio.getConnectionPolicy(null));
     }
 
-    public void test_setVolume() {
+    public void testRegisterCallback() {
         if (!(mHasBluetooth && mIsLeAudioSupported)) return;
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeAudio);
 
-        // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
-        assertThrows(SecurityException.class, () -> mBluetoothLeAudio.setVolume(42));
-    }
+        Executor executor = mContext.getMainExecutor();
+        BluetoothLeAudio.Callback callback =
+                new BluetoothLeAudio.Callback() {
+                    @Override
+                    public void onCodecConfigChanged(int groupId,
+                                                     BluetoothLeAudioCodecStatus status) {}
+                };
 
-    public void testGetCodecStatus() {
-        if (!(mHasBluetooth && mIsLeAudioSupported)) return;
-
-        assertTrue(waitForProfileConnect());
-        assertNotNull(mBluetoothLeAudio);
-
-        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
-        assertNull(mBluetoothLeAudio.getCodecStatus(testDevice));
-        assertThrows(IllegalArgumentException.class, () -> {
-            mBluetoothLeAudio.getCodecStatus(null);
-        });
-    }
-
-    public void testSetCodecConfigPreference() {
-        if (!(mHasBluetooth && mIsLeAudioSupported)) return;
-
-        assertTrue(waitForProfileConnect());
-        assertNotNull(mBluetoothLeAudio);
-
-        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
-        BluetoothLeAudioCodecConfig codecConfig = new BluetoothLeAudioCodecConfig.Builder()
-                .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
-                .setCodecPriority(0)
-                .build();
-        mBluetoothLeAudio.setCodecConfigPreference(testDevice, codecConfig);
-        assertNull(mBluetoothLeAudio.getCodecStatus(testDevice));
-        assertThrows(IllegalArgumentException.class, () -> {
-            mBluetoothLeAudio.setCodecConfigPreference(null, null);
-        });
+        // Verify parameter
+        assertThrows(NullPointerException.class, () ->
+                mBluetoothLeAudio.registerCallback(null, callback));
+        assertThrows(NullPointerException.class, () ->
+                mBluetoothLeAudio.registerCallback(executor, null));
+        assertThrows(NullPointerException.class, () ->
+                mBluetoothLeAudio.unregisterCallback(null));
     }
 
     private boolean waitForProfileConnect() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
index 5651320..d0f3118 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
@@ -19,13 +19,20 @@
 import static android.Manifest.permission.BLUETOOTH_CONNECT;
 import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudioCodecConfigMetadata;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothLeBroadcastChannel;
 import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastSubgroup;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.os.Build;
@@ -50,6 +57,17 @@
     private static final int TEST_PA_SYNC_INTERVAL = 100;
     private static final int TEST_PRESENTATION_DELAY_MS = 345;
 
+    private static final int TEST_CODEC_ID = 42;
+    private static final BluetoothLeBroadcastChannel[] TEST_CHANNELS = {null};
+
+    // For BluetoothLeAudioCodecConfigMetadata
+    private static final long TEST_AUDIO_LOCATION_FRONT_LEFT = 0x01;
+
+    // For BluetoothLeAudioContentMetadata
+    private static final String TEST_PROGRAM_INFO = "Test";
+    // German language code in ISO 639-3
+    private static final String TEST_LANGUAGE = "deu";
+
     private Context mContext;
     private boolean mHasBluetooth;
     private BluetoothAdapter mAdapter;
@@ -107,25 +125,99 @@
         }
         BluetoothDevice testDevice =
                 mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);
-        BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder();
-        BluetoothLeBroadcastMetadata metadata =
-                builder.setEncrypted(false)
+        BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder()
+                        .setEncrypted(false)
                         .setSourceDevice(testDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM)
                         .setSourceAdvertisingSid(TEST_ADVERTISER_SID)
                         .setBroadcastId(TEST_BROADCAST_ID)
                         .setBroadcastCode(null)
                         .setPaSyncInterval(TEST_PA_SYNC_INTERVAL)
-                        .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS)
-                        .build();
+                        .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS);
+        // builder expect at least one subgroup
+        assertThrows(IllegalArgumentException.class, builder::build);
+        BluetoothLeBroadcastSubgroup[] subgroups = new BluetoothLeBroadcastSubgroup[] {
+                createBroadcastSubgroup()
+        };
+        for (BluetoothLeBroadcastSubgroup subgroup : subgroups) {
+            builder.addSubgroup(subgroup);
+        }
+        BluetoothLeBroadcastMetadata metadata = builder.build();
+        assertFalse(metadata.isEncrypted());
         assertEquals(testDevice, metadata.getSourceDevice());
         assertEquals(BluetoothDevice.ADDRESS_TYPE_RANDOM, metadata.getSourceAddressType());
+        assertEquals(TEST_ADVERTISER_SID, metadata.getSourceAdvertisingSid());
         assertEquals(TEST_BROADCAST_ID, metadata.getBroadcastId());
         assertNull(metadata.getBroadcastCode());
         assertEquals(TEST_PA_SYNC_INTERVAL, metadata.getPaSyncInterval());
         assertEquals(TEST_PRESENTATION_DELAY_MS, metadata.getPresentationDelayMicros());
+        assertArrayEquals(subgroups,
+                metadata.getSubgroups().toArray(new BluetoothLeBroadcastSubgroup[0]));
+        builder.clearSubgroup();
+        // builder expect at least one subgroup
+        assertThrows(IllegalArgumentException.class, builder::build);
+    }
+
+    @Test
+    public void testCreateMetadataFromCopy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothDevice testDevice =
+                mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);
+        BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder()
+                .setEncrypted(false)
+                .setSourceDevice(testDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM)
+                .setSourceAdvertisingSid(TEST_ADVERTISER_SID)
+                .setBroadcastId(TEST_BROADCAST_ID)
+                .setBroadcastCode(null)
+                .setPaSyncInterval(TEST_PA_SYNC_INTERVAL)
+                .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS);
+        // builder expect at least one subgroup
+        assertThrows(IllegalArgumentException.class, builder::build);
+        BluetoothLeBroadcastSubgroup[] subgroups = new BluetoothLeBroadcastSubgroup[] {
+                createBroadcastSubgroup()
+        };
+        for (BluetoothLeBroadcastSubgroup subgroup : subgroups) {
+            builder.addSubgroup(subgroup);
+        }
+        BluetoothLeBroadcastMetadata metadata = builder.build();
+        BluetoothLeBroadcastMetadata metadataCopy =
+                new BluetoothLeBroadcastMetadata.Builder(metadata).build();
+        assertFalse(metadataCopy.isEncrypted());
+        assertEquals(testDevice, metadataCopy.getSourceDevice());
+        assertEquals(BluetoothDevice.ADDRESS_TYPE_RANDOM, metadataCopy.getSourceAddressType());
+        assertEquals(TEST_ADVERTISER_SID, metadataCopy.getSourceAdvertisingSid());
+        assertEquals(TEST_BROADCAST_ID, metadataCopy.getBroadcastId());
+        assertNull(metadataCopy.getBroadcastCode());
+        assertEquals(TEST_PA_SYNC_INTERVAL, metadataCopy.getPaSyncInterval());
+        assertEquals(TEST_PRESENTATION_DELAY_MS, metadataCopy.getPresentationDelayMicros());
+        assertArrayEquals(subgroups,
+                metadataCopy.getSubgroups().toArray(new BluetoothLeBroadcastSubgroup[0]));
+        builder.clearSubgroup();
+        // builder expect at least one subgroup
+        assertThrows(IllegalArgumentException.class, builder::build);
     }
 
     private boolean shouldSkipTest() {
         return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
     }
+
+    static BluetoothLeBroadcastSubgroup createBroadcastSubgroup() {
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                new BluetoothLeAudioCodecConfigMetadata.Builder()
+                        .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+        BluetoothLeAudioContentMetadata contentMetadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
+        BluetoothLeBroadcastSubgroup.Builder builder = new BluetoothLeBroadcastSubgroup.Builder()
+                .setCodecId(TEST_CODEC_ID)
+                .setCodecSpecificConfig(codecMetadata)
+                .setContentMetadata(contentMetadata)
+                .setNoChannelPreference(true);
+        for (BluetoothLeBroadcastChannel channel : TEST_CHANNELS) {
+            builder.addChannel(channel);
+        }
+        return builder.build();
+    }
+
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
index 3ad73c7..ea72dcd 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
@@ -21,9 +21,12 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioCodecConfigMetadata;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
 import android.bluetooth.BluetoothLeBroadcastChannel;
 import android.bluetooth.BluetoothLeBroadcastSubgroup;
 import android.bluetooth.BluetoothProfile;
@@ -47,6 +50,14 @@
     private static final int TEST_CODEC_ID = 42;
     private static final BluetoothLeBroadcastChannel[] TEST_CHANNELS = {null};
 
+    // For BluetoothLeAudioCodecConfigMetadata
+    private static final long TEST_AUDIO_LOCATION_FRONT_LEFT = 0x01;
+
+    // For BluetoothLeAudioContentMetadata
+    private static final String TEST_PROGRAM_INFO = "Test";
+    // German language code in ISO 639-3
+    private static final String TEST_LANGUAGE = "deu";
+
     private Context mContext;
     private boolean mHasBluetooth;
     private BluetoothAdapter mAdapter;
@@ -102,18 +113,63 @@
         if (shouldSkipTest()) {
             return;
         }
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                new BluetoothLeAudioCodecConfigMetadata.Builder()
+                        .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+        BluetoothLeAudioContentMetadata contentMetadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
         BluetoothLeBroadcastSubgroup.Builder builder = new BluetoothLeBroadcastSubgroup.Builder()
                 .setCodecId(TEST_CODEC_ID)
-                .setCodecSpecificConfig(null)
-                .setContentMetadata(null)
+                .setCodecSpecificConfig(codecMetadata)
+                .setContentMetadata(contentMetadata)
                 .setNoChannelPreference(true);
         for (BluetoothLeBroadcastChannel channel : TEST_CHANNELS) {
             builder.addChannel(channel);
         }
         BluetoothLeBroadcastSubgroup subgroup = builder.build();
         assertEquals(TEST_CODEC_ID, subgroup.getCodecId());
+        assertEquals(codecMetadata, subgroup.getCodecSpecificConfig());
+        assertEquals(contentMetadata, subgroup.getContentMetadata());
+        assertTrue(subgroup.isNoChannelPreference());
         assertArrayEquals(TEST_CHANNELS,
                 subgroup.getChannels().toArray(new BluetoothLeBroadcastChannel[0]));
+        builder.clearChannel();
+        // builder expect at least one channel
+        assertThrows(IllegalArgumentException.class, builder::build);
+    }
+
+    @Test
+    public void testCreateBroadcastSubgroupFromCopy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                new BluetoothLeAudioCodecConfigMetadata.Builder()
+                        .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+        BluetoothLeAudioContentMetadata contentMetadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
+        BluetoothLeBroadcastSubgroup.Builder builder = new BluetoothLeBroadcastSubgroup.Builder()
+                .setCodecId(TEST_CODEC_ID)
+                .setCodecSpecificConfig(codecMetadata)
+                .setContentMetadata(contentMetadata)
+                .setNoChannelPreference(true);
+        for (BluetoothLeBroadcastChannel channel : TEST_CHANNELS) {
+            builder.addChannel(channel);
+        }
+        BluetoothLeBroadcastSubgroup subgroup = builder.build();
+        BluetoothLeBroadcastSubgroup subgroupCopy =
+                new BluetoothLeBroadcastSubgroup.Builder(subgroup).build();
+        assertEquals(TEST_CODEC_ID, subgroupCopy.getCodecId());
+        assertEquals(codecMetadata, subgroupCopy.getCodecSpecificConfig());
+        assertEquals(contentMetadata, subgroupCopy.getContentMetadata());
+        assertTrue(subgroupCopy.isNoChannelPreference());
+        assertArrayEquals(TEST_CHANNELS,
+                subgroupCopy.getChannels().toArray(new BluetoothLeBroadcastChannel[0]));
+        builder.clearChannel();
+        // builder expect at least one channel
+        assertThrows(IllegalArgumentException.class, builder::build);
     }
 
     private boolean shouldSkipTest() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServiceManagerTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServiceManagerTest.java
new file mode 100644
index 0000000..f81a29c
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServiceManagerTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.bluetooth.cts;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.pm.PackageManager;
+import android.os.BluetoothServiceManager;
+import android.os.BluetoothServiceManager.ServiceNotFoundException;
+import android.os.BluetoothServiceManager.ServiceRegisterer;
+import android.os.IBinder;
+import android.test.AndroidTestCase;
+
+public class BluetoothServiceManagerTest extends AndroidTestCase {
+
+    private boolean mHasBluetooth;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_BLUETOOTH);
+    }
+
+    public void test_ServiceRegisterer() {
+        if (!mHasBluetooth) {
+            return;
+        }
+        BluetoothServiceManager serviceManager = new BluetoothServiceManager();
+        ServiceRegisterer serviceRegisterer =
+                serviceManager.getBluetoothManagerServiceRegisterer();
+
+        assertThrows(SecurityException.class, () ->
+                serviceRegisterer.register(serviceRegisterer.get()));
+
+        IBinder bluetoothServiceBinder = serviceRegisterer.get();
+        assertNotNull(bluetoothServiceBinder);
+
+        bluetoothServiceBinder = serviceRegisterer.tryGet();
+        assertNotNull(bluetoothServiceBinder);
+
+        try {
+            bluetoothServiceBinder = serviceRegisterer.getOrThrow();
+            assertNotNull(bluetoothServiceBinder);
+        } catch (ServiceNotFoundException exception) {
+            fail("ServiceNotFoundException should not be thrown");
+        }
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanResultTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanResultTest.java
index f323712..71a61b9 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanResultTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanResultTest.java
@@ -72,4 +72,39 @@
                 TIMESTAMP_NANOS);
         assertEquals(0, result.describeContents());
     }
+
+    @SmallTest
+    public void testConstructor() {
+        if (!mContext.getPackageManager().
+                  hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) return;
+
+        BluetoothDevice device =
+                BluetoothAdapter.getDefaultAdapter().getRemoteDevice(DEVICE_ADDRESS);
+        int eventType = 0xAAAA;
+        int primaryPhy = 0xAAAB;
+        int secondaryPhy = 0xAABA;
+        int advertisingSid = 0xAABB;
+        int txPower = 0xABAA;
+        int rssi = 0xABAB;
+        int periodicAdvertisingInterval = 0xABBA;
+        long timestampNanos = 0xABBB;
+        ScanResult result = new ScanResult(device, eventType, primaryPhy, secondaryPhy,
+                advertisingSid, txPower, rssi, periodicAdvertisingInterval, null, timestampNanos);
+        assertEquals(result.getDevice(), device);
+        assertNull(result.getScanRecord());
+        assertEquals(result.getRssi(), rssi);
+        assertEquals(result.getTimestampNanos(), timestampNanos);
+        assertEquals(result.getDataStatus(), 0x01);
+        assertEquals(result.getPrimaryPhy(), primaryPhy);
+        assertEquals(result.getSecondaryPhy(), secondaryPhy);
+        assertEquals(result.getAdvertisingSid(), advertisingSid);
+        assertEquals(result.getTxPower(), txPower);
+        assertEquals(result.getPeriodicAdvertisingInterval(), periodicAdvertisingInterval);
+
+        // specific value of event type for isLegacy and isConnectable to be true
+        ScanResult result2 = new ScanResult(device, 0x11, primaryPhy, secondaryPhy,
+                advertisingSid, txPower, rssi, periodicAdvertisingInterval, null, timestampNanos);
+        assertTrue(result2.isLegacy());
+        assertTrue(result2.isConnectable());
+    }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanSettingsTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanSettingsTest.java
index 7033c3c..a1b928f 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/ScanSettingsTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/ScanSettingsTest.java
@@ -16,6 +16,8 @@
 
 package android.bluetooth.cts;
 
+import static org.junit.Assert.assertThrows;
+
 import android.bluetooth.le.ScanSettings;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
@@ -33,9 +35,81 @@
         assertEquals(ScanSettings.SCAN_MODE_LOW_POWER, settings.getScanMode());
         assertEquals(0, settings.getScanResultType());
         assertEquals(0, settings.getReportDelayMillis());
+        assertEquals(true, settings.getLegacy());
+        assertEquals(ScanSettings.PHY_LE_ALL_SUPPORTED, settings.getPhy());
     }
 
     @SmallTest
+    public void testBuilderSettings() {
+        ScanSettings.Builder builder = new ScanSettings.Builder();
+
+        // setScanMode boundary check
+        assertThrows("Check boundary of ScanSettings.Builder.setScanMode argument",
+                IllegalArgumentException.class,
+                () -> builder.setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC - 1));
+        assertThrows("Check boundary of ScanSettings.Builder.setScanMode argument",
+                IllegalArgumentException.class,
+                () -> builder.setScanMode(6)); // 6 = ScanSettings.SCAN_MODE_SCREEN_OFF_BALANCED + 1
+
+        // setCallbackType boundary check
+        assertThrows("Check boundary of ScanSettings.Builder.setCallbackType argument",
+                IllegalArgumentException.class,
+                () -> builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES - 1));
+        assertThrows("Check boundary of ScanSettings.Builder.setCallbackType argument",
+                IllegalArgumentException.class,
+                () -> builder.setCallbackType(ScanSettings.CALLBACK_TYPE_MATCH_LOST + 1));
+
+        // setScanResultType boundary check
+        assertThrows("Check boundary of ScanSettings.Builder.setScanResultType argument",
+                IllegalArgumentException.class,
+                () -> builder.setScanResultType(ScanSettings.SCAN_RESULT_TYPE_FULL - 1));
+        assertThrows("Check boundary of ScanSettings.Builder.setScanResultType argument",
+                IllegalArgumentException.class,
+                () -> builder.setScanResultType(ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED + 1));
+
+        assertThrows("Check boundary of ScanSettings.Builder.setReportDelay argument",
+                IllegalArgumentException.class,
+                () -> builder.setReportDelay(-1));
+
+        // setNumOfMatches boundary check
+        assertThrows("Check boundary of ScanSettings.Builder.setNumOfMatches argument",
+                IllegalArgumentException.class,
+                () -> builder.setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT - 1));
+        assertThrows("Check boundary of ScanSettings.Builder.setNumOfMatches argument",
+                IllegalArgumentException.class,
+                () -> builder.setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT + 1));
+
+        // setMatchMode boundary check
+        assertThrows("Check boundary of ScanSettings.Builder.setMatchMode argument",
+                IllegalArgumentException.class,
+                () -> builder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE - 1));
+        assertThrows("Check boundary of ScanSettings.Builder.setMatchMode argument",
+                IllegalArgumentException.class,
+                () -> builder.setMatchMode(ScanSettings.MATCH_MODE_STICKY + 1));
+
+        int cbType = ScanSettings.CALLBACK_TYPE_MATCH_LOST | ScanSettings.CALLBACK_TYPE_FIRST_MATCH;
+
+        ScanSettings settings = builder
+            .setScanMode(ScanSettings.SCAN_MODE_BALANCED)
+            .setCallbackType(cbType)
+            .setScanResultType(ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED)
+            .setReportDelay(0xDEAD)
+            .setNumOfMatches(ScanSettings.MATCH_NUM_FEW_ADVERTISEMENT)
+            .setMatchMode(ScanSettings.MATCH_MODE_STICKY)
+            .setLegacy(false)
+            .setPhy(0xCAFE)
+            .build();
+
+        assertEquals(ScanSettings.SCAN_MODE_BALANCED, settings.getScanMode());
+        assertEquals(cbType, settings.getCallbackType());
+        assertEquals(ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED, settings.getScanResultType());
+        assertEquals(0xDEAD, settings.getReportDelayMillis());
+        assertEquals(false, settings.getLegacy());
+        assertEquals(0xCAFE, settings.getPhy());
+    }
+
+
+    @SmallTest
     public void testDescribeContents() {
         ScanSettings settings = new ScanSettings.Builder().build();
         assertEquals(0, settings.describeContents());
diff --git a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
index 0c62806..9d18368 100644
--- a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
@@ -26,6 +26,8 @@
 import android.car.Car;
 import android.car.VehiclePropertyIds;
 import android.car.telemetry.CarTelemetryManager;
+import android.car.telemetry.TelemetryProto;
+import android.os.PersistableBundle;
 import android.platform.test.annotations.RequiresDevice;
 import android.util.ArrayMap;
 
@@ -34,8 +36,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.car.telemetry.TelemetryProto;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -261,11 +261,11 @@
 
         private final Semaphore mSemaphore = new Semaphore(0);
         private final Map<String, byte[]> mErrorMap = new ArrayMap<>();
-        private final Map<String, byte[]> mReportMap = new ArrayMap<>();
+        private final Map<String, PersistableBundle> mReportMap = new ArrayMap<>();
         private final Map<String, Integer> mStatusMap = new ArrayMap<>();
 
         @Override
-        public void onResult(@NonNull String metricsConfigName, @Nullable byte[] report,
+        public void onResult(@NonNull String metricsConfigName, @Nullable PersistableBundle report,
                 @Nullable byte[] error, int status) {
             mReportMap.put(metricsConfigName, report);
             mErrorMap.put(metricsConfigName, error);
diff --git a/tests/tests/car_builtin/AndroidManifest.xml b/tests/tests/car_builtin/AndroidManifest.xml
index d86153d..40e5e09 100644
--- a/tests/tests/car_builtin/AndroidManifest.xml
+++ b/tests/tests/car_builtin/AndroidManifest.xml
@@ -41,6 +41,22 @@
         <service android:name="android.car.cts.builtin.os.SharedMemoryTestService"
             android:process=":shdmemservice">
         </service>
+
+        <activity android:name="android.car.cts.builtin.app.ActivityManagerHelperTest$ActivityA"
+                  android:taskAffinity="android.car.cts.builtin.amTestTask1"
+                  android:exported="true">
+        </activity>
+
+        <activity android:name="android.car.cts.builtin.app.ActivityManagerHelperTest$ActivityB"
+                  android:taskAffinity="android.car.cts.builtin.amTestTask1"
+                  android:exported="true">
+        </activity>
+
+        <activity android:name="android.car.cts.builtin.app.ActivityManagerHelperTest$ActivityC"
+                  android:taskAffinity="android.car.cts.builtin.amTestTask2"
+                  android:exported="true">
+        </activity>
+
         <service android:name="android.car.cts.builtin.os.ServiceManagerTestService"
             android:process=":testservice">
         </service>
diff --git a/tests/tests/car_builtin/AndroidTest.xml b/tests/tests/car_builtin/AndroidTest.xml
index 1bc7a1f..2ace59c 100644
--- a/tests/tests/car_builtin/AndroidTest.xml
+++ b/tests/tests/car_builtin/AndroidTest.xml
@@ -26,6 +26,7 @@
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
         <option name="test-file-name" value="CtsCarBuiltinApiTestCases.apk"/>
+        <option name="test-file-name" value="CtsCarBuiltinSimpleApp.apk"/>
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="setprop log.tag.CAR.TEST VERBOSE" />
diff --git a/tests/tests/car_builtin/apps/SimpleApp/Android.bp b/tests/tests/car_builtin/apps/SimpleApp/Android.bp
new file mode 100644
index 0000000..9e79dc4
--- /dev/null
+++ b/tests/tests/car_builtin/apps/SimpleApp/Android.bp
@@ -0,0 +1,40 @@
+// 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: "CtsCarBuiltinSimpleApp",
+    defaults: ["cts_defaults"],
+    sdk_version: "current",
+    srcs: [
+        "src/**/*.java",
+    ],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "truth-prebuilt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.base",
+        "android.car-test-stubs",
+    ],
+}
diff --git a/tests/tests/car_builtin/apps/SimpleApp/AndroidManifest.xml b/tests/tests/car_builtin/apps/SimpleApp/AndroidManifest.xml
new file mode 100644
index 0000000..1a03ca5
--- /dev/null
+++ b/tests/tests/car_builtin/apps/SimpleApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?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.car.cts.builtin.apps.simple">
+    <application>
+        <activity android:name="android.car.cts.builtin.apps.simple.SimpleActivity"
+                  android:exported="true">
+        </activity>
+    </application>
+</manifest>
+
diff --git a/tests/tests/car_builtin/apps/SimpleApp/src/android/car/cts/builtin/apps/simple/SimpleActivity.java b/tests/tests/car_builtin/apps/SimpleApp/src/android/car/cts/builtin/apps/simple/SimpleActivity.java
new file mode 100644
index 0000000..1bf376f
--- /dev/null
+++ b/tests/tests/car_builtin/apps/SimpleApp/src/android/car/cts/builtin/apps/simple/SimpleActivity.java
@@ -0,0 +1,25 @@
+/*
+ * 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.car.cts.builtin.apps.simple;
+
+import android.app.Activity;
+
+/**
+ * A very simple activity for testing PackageManagerHelper.
+ */
+public final class SimpleActivity extends Activity {
+}
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/activity/ActivityManagerTestActivityBase.java b/tests/tests/car_builtin/src/android/car/cts/builtin/activity/ActivityManagerTestActivityBase.java
new file mode 100644
index 0000000..38df2b8
--- /dev/null
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/activity/ActivityManagerTestActivityBase.java
@@ -0,0 +1,53 @@
+/*
+ * 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.car.cts.builtin.activity;
+
+import android.app.Activity;
+import android.util.Log;
+
+public abstract class ActivityManagerTestActivityBase extends Activity {
+    public static final String TAG = ActivityManagerTestActivityBase.class.getSimpleName();
+
+    private volatile boolean mIsVisible;
+    private volatile boolean mHasFocus;
+
+    public boolean isVisible() {
+        return mIsVisible;
+    }
+
+    public boolean hasFocus() {
+        return mHasFocus;
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        mHasFocus = hasFocus;
+        Log.d(TAG, "hasFocus: " + hasFocus);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mIsVisible = true;
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mIsVisible = false;
+    }
+}
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
index bc3fc04..f840863 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
@@ -16,22 +16,49 @@
 
 package android.car.cts.builtin.app;
 
-import static com.google.common.truth.Truth.assertThat;
+import static android.car.builtin.app.ActivityManagerHelper.ProcessObserverCallback;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.app.TaskInfo;
 import android.car.builtin.app.ActivityManagerHelper;
+import android.car.cts.builtin.activity.ActivityManagerTestActivityBase;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Process;
+import android.os.UserHandle;
+import android.server.wm.ActivityManagerTestBase;
+import android.util.Log;
 
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.SystemUtil;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 @RunWith(AndroidJUnit4.class)
-public final class ActivityManagerHelperTest {
+public final class ActivityManagerHelperTest extends ActivityManagerTestBase {
 
     private static final String TAG = ActivityManagerHelperTest.class.getSimpleName();
 
+    private static final String PERMISSION_SET_ACTIVITY_WATCHER =
+            "android.permission.SET_ACTIVITY_WATCHER";
     private static final String NOT_REQUESTED_PERMISSION_CAR_MILEAGE =
             "android.car.permission.CAR_MILEAGE";
     private static final String NOT_REQUESTED_PERMISSION_READ_CAR_POWER_POLICY =
@@ -39,8 +66,22 @@
 
     private static final String GRANTED_PERMISSION_INTERACT_ACROSS_USERS =
             "android.permission.INTERACT_ACROSS_USERS";
+    private static final String PERMISSION_REMOVE_TASKS = "android.permission.REMOVE_TASKS";
+    private static final String PERMISSION_GET_TASKS = "android.permission.GET_TASKS";
+    private static final String PERMISSION_MANAGE_ACTIVITY_TASKS =
+            "android.permission.MANAGE_ACTIVITY_TASKS";
 
-    private static final int OWNING_UID = -1;
+    private static final String SIMPLE_APP_PACKAGE_NAME = "android.car.cts.builtin.apps.simple";
+    private static final String SIMPLE_ACTIVITY_NAME = "SimpleActivity";
+    private static final String START_SIMPLE_ACTIVITY_COMMAND = "am start -W -n "
+            + SIMPLE_APP_PACKAGE_NAME + "/." + SIMPLE_ACTIVITY_NAME;
+
+    private static final int OWNING_UID = UserHandle.ALL.getIdentifier();
+    private static final int MAX_NUM_TASKS = 1_000;
+    private static final int TIMEOUT_MS = 20_000;
+
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private final Context mContext = mInstrumentation.getContext();
 
     @Test
     public void testCheckComponentPermission() throws Exception {
@@ -54,17 +95,96 @@
 
     @Test
     public void testSetFocusedRootTask() throws Exception {
-        //TODO(b/201005730): implement the test case to test setFocusedRootTask API.
+        // setup
+        ActivityA task1BottomActivity = launchTestActivity(ActivityA.class);
+        ActivityB task1TopActivity = launchTestActivity(ActivityB.class);
+        ActivityC task2TopActivity = launchTestActivity(ActivityC.class);
+
+        logActivityStack("amTestActivitys ",
+                task1BottomActivity, task1TopActivity, task2TopActivity);
+
+        assertWithMessage("bottom activity is the task root")
+                .that(task1BottomActivity.isTaskRoot()).isTrue();
+        assertWithMessage("task id of the top activity in the task1")
+                .that(task1TopActivity.getTaskId()).isEqualTo(task1BottomActivity.getTaskId());
+        assertWithMessage("task id of the top activity in the task2")
+                .that(task2TopActivity.getTaskId()).isNotEqualTo(task1TopActivity.getTaskId());
+        assertWithMessage("task1 top activity is visible")
+                .that(task1TopActivity.isVisible()).isFalse();
+        assertWithMessage("task2 top activity is visible")
+                .that(task2TopActivity.isVisible()).isTrue();
+
+        // execute
+        try {
+            mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    PERMISSION_MANAGE_ACTIVITY_TASKS);
+
+            ActivityManagerHelper.setFocusedRootTask(task1BottomActivity.getTaskId());
+        } finally {
+            mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
+        }
+
+
+        // assert
+        ComponentName activityName = task1TopActivity.getComponentName();
+        waitAndAssertTopResumedActivity(activityName, DEFAULT_DISPLAY,
+                "Activity must be resumed");
+        assertWithMessage("task1 top activity has focus")
+                .that(task1TopActivity.hasFocus()).isTrue();
+        assertWithMessage("task1 top activity is visible")
+                .that(task1TopActivity.isVisible()).isTrue();
+
+        // teardown
+        task1TopActivity.finish();
+        task1BottomActivity.finish();
+        task2TopActivity.finish();
     }
 
     @Test
     public void testRemoveTask() throws Exception {
-        //TODO(b/201005730): implement the test case to test setRemoveTask API.
+        // setup
+        ActivityC testActivity = launchTestActivity(ActivityC.class);
+        int taskId = testActivity.getTaskId();
+        assertThat(doesTaskExist(taskId)).isTrue();
+
+        // execute
+        try {
+            mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    PERMISSION_REMOVE_TASKS);
+
+            ActivityManagerHelper.removeTask(taskId);
+        } finally {
+            mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
+        }
+
+        // assert
+        PollingCheck.waitFor(TIMEOUT_MS, () -> testActivity.isDestroyed());
+        assertThat(doesTaskExist(taskId)).isFalse();
     }
 
     @Test
     public void testProcessObserverCallback() throws Exception {
-        //TODO(b/201005730): implement the test case to test processObserverCallback API.
+        // setup
+        ProcessObserverCallbackTestImpl callbackImpl = new ProcessObserverCallbackTestImpl();
+        launchSimpleActivity();
+
+        // execute
+        try {
+            mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                        PERMISSION_SET_ACTIVITY_WATCHER);
+
+            ActivityManagerHelper.registerProcessObserverCallback(callbackImpl);
+
+            ArrayList<Integer> appTasks = getAppTasks(SIMPLE_APP_PACKAGE_NAME);
+            appTasks.forEach((taskId) -> ActivityManagerHelper.removeTask(taskId));
+
+            // assert
+            assertThat(callbackImpl.isProcessDiedObserved()).isTrue();
+        } finally {
+            // teardown
+            ActivityManagerHelper.unregisterProcessObserverCallback(callbackImpl);
+            mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
+        }
     }
 
     private void assertComponentPermissionGranted(String permission) throws Exception {
@@ -78,4 +198,100 @@
                 Process.myUid(), /* owningUid= */ OWNING_UID, /* exported= */ true))
                 .isEqualTo(PackageManager.PERMISSION_DENIED);
     }
+
+    private static final class ProcessObserverCallbackTestImpl extends ProcessObserverCallback {
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+
+        private int mObservedPid = -1;
+        private int mObservedUid = -1;
+        private boolean mProcessDiedObserved;
+
+        @Override
+        public void onProcessDied(int pid, int uid) {
+            mProcessDiedObserved = true;
+            Log.d(TAG, "ProcessDied: pid " + pid + " uid " + uid);
+            mLatch.countDown();
+        }
+
+        public boolean isProcessDiedObserved() throws Exception {
+            if (!mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                throw new Exception("process died is not observed in " + TIMEOUT_MS + " ms)");
+            }
+            return mProcessDiedObserved;
+        }
+    }
+
+    private void launchSimpleActivity() {
+        SystemUtil.runShellCommand(START_SIMPLE_ACTIVITY_COMMAND);
+    }
+
+    private ArrayList<Integer> getAppTasks(String pkgName) {
+        ActivityManager am = mContext.getSystemService(ActivityManager.class);
+
+        List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(MAX_NUM_TASKS);
+        ArrayList<Integer> appTasks = new ArrayList<>();
+        for (ActivityManager.RunningTaskInfo taskInfo : runningTasks) {
+            String taskPackageName = taskInfo.baseActivity.getPackageName();
+            int taskId = taskInfo.taskId;
+            Log.d(TAG, "tasks package name: " + taskPackageName);
+            if (taskPackageName.equals(pkgName)) {
+                Log.d(TAG, "getAppTask(): adding " + SIMPLE_APP_PACKAGE_NAME + " task " + taskId);
+                appTasks.add(taskId);
+            }
+        }
+
+        return appTasks;
+    }
+
+    private <T> T launchTestActivity(Class<T> type) {
+        Intent startIntent = new Intent(mContext, type)
+                .addFlags(FLAG_ACTIVITY_NEW_TASK);
+
+        Activity testActivity = (Activity) mInstrumentation
+                .startActivitySync(startIntent, /* options = */ null);
+
+        ComponentName testActivityName = testActivity.getComponentName();
+        waitAndAssertTopResumedActivity(testActivityName, DEFAULT_DISPLAY,
+                "Activity must be resumed");
+
+        return type.cast(testActivity);
+    }
+
+    // The logging order of the Activities follows the stack order. The first Activity
+    // in the parameter list is logged at last.
+    private static void logActivityStack(String msg, Activity... activityStack) {
+        for (int index = activityStack.length - 1; index >= 0; index--) {
+            String logMsg = String.format("%s\tindex=%d taskId=%d",
+                    msg, index, activityStack[index].getTaskId());
+            Log.d(TAG, logMsg);
+        }
+    }
+
+    private boolean doesTaskExist(int taskId) {
+        boolean retVal = false;
+        try {
+            mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
+                    PERMISSION_REMOVE_TASKS);
+            ActivityManager am = mContext.getSystemService(ActivityManager.class);
+            List<ActivityManager.RunningTaskInfo> taskList = am.getRunningTasks(MAX_NUM_TASKS);
+            for (TaskInfo taskInfo : taskList) {
+                if (taskInfo.taskId == taskId) {
+                    retVal = true;
+                    break;
+                }
+            }
+        } finally {
+            mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
+        }
+        return retVal;
+    }
+
+    public static final class ActivityA extends ActivityManagerTestActivityBase {
+    }
+
+    public static final class ActivityB extends ActivityManagerTestActivityBase {
+    }
+
+    public static final class ActivityC extends ActivityManagerTestActivityBase {
+    }
 }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
index 2c2e3f1..9b30f5b 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
@@ -23,14 +23,18 @@
 
 import android.car.builtin.content.pm.PackageManagerHelper;
 import android.car.cts.builtin.R;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.Process;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -39,33 +43,37 @@
 import org.junit.runner.RunWith;
 
 import java.util.Arrays;
+import java.util.function.ToIntFunction;
 
 @RunWith(AndroidJUnit4.class)
 public final class PackageManagerHelperTest {
 
     private static final String TAG = PackageManagerHelperTest.class.getSimpleName();
     private static final String ANDROID_CAR_PKG = "com.android.car";
+    private static final String ANDROID_CAR_SHELL_PKG = "com.android.shell";
+    private static final String ANDROID_CAR_SHELL_PKG_SHARED = "shared:android.uid.shell";
     private static final String CAR_BUILTIN_CTS_PKG = "android.car.cts.builtin";
+    private static final String[] CAR_BUILTIN_CTS_SERVICE_NAMES = {
+        "android.car.cts.builtin.os.SharedMemoryTestService",
+        "android.car.cts.builtin.os.ServiceManagerTestService"
+    };
 
     private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
     private final PackageManager mPackageManager = mContext.getPackageManager();
 
     @Test
     public void testGetPackageInfoAsUser() throws Exception {
-        // setup
         String expectedActivityName = "android.car.cts.builtin.activity.SimpleActivity";
         int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_SERVICES;
         int curUser = UserHandle.myUserId();
 
-        // execution
         PackageInfo pkgInfoUser = PackageManagerHelper.getPackageInfoAsUser(mPackageManager,
                 CAR_BUILTIN_CTS_PKG, flags, curUser);
         ApplicationInfo appInfo = pkgInfoUser.applicationInfo;
         ActivityInfo[] activities = pkgInfoUser.activities;
         ServiceInfo[] services = pkgInfoUser.services;
 
-        // assertion
         assertThat(appInfo).isNotNull();
         assertThat(appInfo.descriptionRes).isEqualTo(R.string.app_description);
         assertThat(activities).isNotNull();
@@ -75,13 +83,11 @@
 
     @Test
     public void testAppTypeChecking() throws Exception {
-        // setup
         ApplicationInfo systemApp = mPackageManager
                 .getApplicationInfo(ANDROID_CAR_PKG, /* flags= */ 0);
         ApplicationInfo ctsApp = mPackageManager
                 .getApplicationInfo(CAR_BUILTIN_CTS_PKG, /* flags= */ 0);
 
-        // execution and assertion
         assertThat(PackageManagerHelper.isSystemApp(systemApp)).isTrue();
         assertThat(PackageManagerHelper.isUpdatedSystemApp(systemApp)).isFalse();
         assertThat(PackageManagerHelper.isSystemExtApp(systemApp)).isFalse();
@@ -101,26 +107,73 @@
 
     @Test
     public void testGetSystemUiPackageName() throws Exception {
-        // TODO (b/201822684): implement this test case to test getSystemUiPackageName()
-        // builtin API
+        String systemuiPackageName = PackageManagerHelper.getSystemUiPackageName(mContext);
+        // The default SystemUI package name is com.android.systemui. But OEMs can override
+        // it via com.android.internal.R.string.config_systemUIServiceComponent.So, it can
+        // not assert with respect to a specific (constant) value.
+        Log.d(TAG, "System UI package name=" + systemuiPackageName);
+        assertThat(systemuiPackageName).isNotNull();
     }
 
     @Test
     public void testGetNamesForUids() throws Exception {
-        // TODO (b/201822684): implement this test case to test getNamesForUids()
-        // builtin API
+        String[] initPackageNames = {ANDROID_CAR_SHELL_PKG, CAR_BUILTIN_CTS_PKG};
+        // The CarShell has package name as com.android.shell but it also has sharedUserId as
+        // android.uid.shell. Therefore, the return from Android framework should be
+        // shared:com.android.shell instead of com.android.shell
+        String[][] expectedPackageNames = {
+            {ANDROID_CAR_SHELL_PKG_SHARED, CAR_BUILTIN_CTS_PKG},
+            {ANDROID_CAR_SHELL_PKG_SHARED},
+            {CAR_BUILTIN_CTS_PKG}
+        };
+
+        int[] packageUids = convertPackageNamesToUids(initPackageNames);
+        int[][] packageUidsList = {
+            packageUids,
+            {packageUids[0]},
+            {packageUids[1]}
+        };
+
+        for (int index = 0; index < expectedPackageNames.length; index++) {
+            String[] packageNames = PackageManagerHelper
+                    .getNamesForUids(mPackageManager, packageUidsList[index]);
+            assertThat(packageNames).isEqualTo(expectedPackageNames[index]);
+        }
     }
 
     @Test
     public void testGetPackageUidAsUser() throws Exception {
-        // TODO (b/201822684): implement this test case to test getPackageUidAsUser()
-        // builtin API
+        int userId = UserHandle.SYSTEM.getIdentifier();
+        int expectedUid = UserHandle.SYSTEM.getUid(Process.SYSTEM_UID);
+
+        // com.android.car package has the shared SYSTEM_UID
+        int actualUid = PackageManagerHelper
+                .getPackageUidAsUser(mPackageManager, ANDROID_CAR_PKG, userId);
+
+        assertThat(actualUid).isEqualTo(expectedUid);
     }
 
     @Test
     public void testGetComponentName() throws Exception {
-        // TODO (b/201822684): implement this test case to test getComponentName()
-        // builtin API
+        int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_INSTRUMENTATION
+                | PackageManager.GET_SERVICES;
+        int curUser = UserHandle.myUserId();
+        PackageInfo pkgInfoUser = PackageManagerHelper.getPackageInfoAsUser(mPackageManager,
+                CAR_BUILTIN_CTS_PKG, flags, curUser);
+        ServiceInfo[] serviceInfos = pkgInfoUser.services;
+
+        assertThat(serviceInfos).isNotNull();
+        ArraySet<String> serviceClassSet = new ArraySet<>();
+        for (ServiceInfo info : serviceInfos) {
+            ComponentName componentName = PackageManagerHelper.getComponentName(info);
+            Log.d(TAG, "class name: " + componentName.flattenToString());
+            assertThat(componentName).isNotNull();
+            assertThat(componentName.getPackageName()).isEqualTo(CAR_BUILTIN_CTS_PKG);
+            serviceClassSet.add(componentName.getClassName());
+        }
+
+        assertThat(serviceClassSet.containsAll(Arrays.asList(CAR_BUILTIN_CTS_SERVICE_NAMES)))
+                .isTrue();
     }
 
     @Test
@@ -141,4 +194,17 @@
     private boolean hasActivity(String activityName, ActivityInfo[] activities) {
         return Arrays.stream(activities).anyMatch(a -> activityName.equals(a.name));
     }
+
+    private int[] convertPackageNamesToUids(String[] packageNames) {
+        ToIntFunction<String> packageNameToUid = (pkgName) -> {
+            int uid = Process.INVALID_UID;
+            try {
+                uid = mPackageManager.getPackageUid(pkgName, /* flags= */0);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.wtf(TAG, pkgName + " does not exist", e);
+            }
+            return uid;
+        };
+        return Arrays.stream(packageNames).mapToInt(packageNameToUid).toArray();
+    }
 }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/util/EventLogHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/util/EventLogHelperTest.java
index 7740462..62b7d83 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/util/EventLogHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/util/EventLogHelperTest.java
@@ -16,6 +16,11 @@
 
 package android.car.cts.builtin.util;
 
+import static android.car.cts.builtin.util.LogcatHelper.Buffer.EVENTS;
+import static android.car.cts.builtin.util.LogcatHelper.Level.INFO;
+import static android.car.cts.builtin.util.LogcatHelper.assertLogcatMessage;
+import static android.car.cts.builtin.util.LogcatHelper.clearLog;
+
 import android.car.builtin.util.EventLogHelper;
 
 import org.junit.Before;
@@ -24,369 +29,367 @@
 public final class EventLogHelperTest {
 
     private static final int TIMEOUT_MS = 10_000;
-    // All Eventlogs would be logged to event buffer.
-    private static final LogcatHelper.Buffer BUFFER = LogcatHelper.Buffer.EVENTS;
 
     @Before
     public void setup() {
-        LogcatHelper.clearLog();
+        clearLog();
     }
 
     @Test
     public void testWriteCarHelperStart() {
         EventLogHelper.writeCarHelperStart();
 
-        assertLogMessage("I car_helper_start:");
+        assertLogMessage("car_helper_start");
     }
 
     @Test
     public void testWriteCarHelperBootPhase() {
         EventLogHelper.writeCarHelperBootPhase(1);
 
-        assertLogMessage("I car_helper_boot_phase: 1");
+        assertLogMessage("car_helper_boot_phase", "1");
     }
 
     @Test
     public void testWriteCarHelperUserStarting() {
         EventLogHelper.writeCarHelperUserStarting(100);
 
-        assertLogMessage("I car_helper_user_starting: 100");
+        assertLogMessage("car_helper_user_starting", "100");
     }
 
     @Test
     public void testWriteCarHelperUserSwitching() {
         EventLogHelper.writeCarHelperUserSwitching(100, 101);
 
-        assertLogMessage("I car_helper_user_switching: [100,101]");
+        assertLogMessage("car_helper_user_switching", "[100,101]");
     }
 
     @Test
     public void testWriteCarHelperUserUnlocking() {
         EventLogHelper.writeCarHelperUserUnlocking(100);
 
-        assertLogMessage("I car_helper_user_unlocking: 100");
+        assertLogMessage("car_helper_user_unlocking", "100");
     }
 
     @Test
     public void testWriteCarHelperUserUnlocked() {
         EventLogHelper.writeCarHelperUserUnlocked(100);
 
-        assertLogMessage("I car_helper_user_unlocked: 100");
+        assertLogMessage("car_helper_user_unlocked", "100");
     }
 
     @Test
     public void testWriteCarHelperUserStopping() {
         EventLogHelper.writeCarHelperUserStopping(100);
 
-        assertLogMessage("I car_helper_user_stopping: 100");
+        assertLogMessage("car_helper_user_stopping", "100");
     }
 
     @Test
     public void testWriteCarHelperUserStopped() {
         EventLogHelper.writeCarHelperUserStopped(100);
 
-        assertLogMessage("I car_helper_user_stopped: 100");
+        assertLogMessage("car_helper_user_stopped", "100");
     }
 
     @Test
     public void testWriteCarHelperServiceConnected() {
         EventLogHelper.writeCarHelperServiceConnected();
 
-        assertLogMessage("I car_helper_svc_connected");
+        assertLogMessage("car_helper_svc_connected");
     }
 
     @Test
     public void testWriteCarServiceInit() {
         EventLogHelper.writeCarServiceInit(101);
 
-        assertLogMessage("I car_service_init: 101");
+        assertLogMessage("car_service_init", "101");
     }
 
     @Test
     public void testWriteCarServiceVhalReconnected() {
         EventLogHelper.writeCarServiceVhalReconnected(101);
 
-        assertLogMessage("I car_service_vhal_reconnected: 101");
+        assertLogMessage("car_service_vhal_reconnected", "101");
     }
 
     @Test
     public void testWriteCarServiceSetCarServiceHelper() {
         EventLogHelper.writeCarServiceSetCarServiceHelper(101);
 
-        assertLogMessage("I car_service_set_car_service_helper: 101");
+        assertLogMessage("car_service_set_car_service_helper", "101");
     }
 
     @Test
     public void testWriteCarServiceOnUserLifecycle() {
         EventLogHelper.writeCarServiceOnUserLifecycle(1, 2, 3);
 
-        assertLogMessage("I car_service_on_user_lifecycle: [1,2,3]");
+        assertLogMessage("car_service_on_user_lifecycle", "[1,2,3]");
     }
 
     @Test
     public void testWriteCarServiceCreate() {
         EventLogHelper.writeCarServiceCreate(true);
 
-        assertLogMessage("I car_service_create: 1");
+        assertLogMessage("car_service_create", "1");
     }
 
     @Test
     public void testWriteCarServiceConnected() {
         EventLogHelper.writeCarServiceConnected("testString");
 
-        assertLogMessage("I car_service_connected: testString");
+        assertLogMessage("car_service_connected", "testString");
     }
 
     @Test
     public void testWriteCarServiceDestroy() {
         EventLogHelper.writeCarServiceDestroy(true);
 
-        assertLogMessage("I car_service_destroy: 1");
+        assertLogMessage("car_service_destroy", "1");
     }
 
     @Test
     public void testWriteCarServiceVhalDied() {
         EventLogHelper.writeCarServiceVhalDied(101);
 
-        assertLogMessage("I car_service_vhal_died: 101");
+        assertLogMessage("car_service_vhal_died", "101");
     }
 
     @Test
     public void testWriteCarServiceInitBootUser() {
         EventLogHelper.writeCarServiceInitBootUser();
 
-        assertLogMessage("I car_service_init_boot_user");
+        assertLogMessage("car_service_init_boot_user");
     }
 
     @Test
     public void testWriteCarServiceOnUserRemoved() {
         EventLogHelper.writeCarServiceOnUserRemoved(101);
 
-        assertLogMessage("I car_service_on_user_removed: 101");
+        assertLogMessage("car_service_on_user_removed", "101");
     }
 
     @Test
     public void testWriteCarUserServiceInitialUserInfoReq() {
         EventLogHelper.writeCarUserServiceInitialUserInfoReq(1, 2, 3, 4, 5);
 
-        assertLogMessage("I car_user_svc_initial_user_info_req: [1,2,3,4,5]");
+        assertLogMessage("car_user_svc_initial_user_info_req", "[1,2,3,4,5]");
     }
 
     @Test
     public void testWriteCarUserServiceInitialUserInfoResp() {
         EventLogHelper.writeCarUserServiceInitialUserInfoResp(1, 2, 3, 4, "string1", "string2");
 
-        assertLogMessage("I car_user_svc_initial_user_info_resp: [1,2,3,4,string1,string2]");
+        assertLogMessage("car_user_svc_initial_user_info_resp", "[1,2,3,4,string1,string2]");
     }
 
     @Test
     public void testWriteCarUserServiceSetInitialUser() {
         EventLogHelper.writeCarUserServiceSetInitialUser(101);
 
-        assertLogMessage("I car_user_svc_set_initial_user: 101");
+        assertLogMessage("car_user_svc_set_initial_user", "101");
     }
 
     @Test
     public void testWriteCarUserServiceSetLifecycleListener() {
         EventLogHelper.writeCarUserServiceSetLifecycleListener(101, "string1");
 
-        assertLogMessage("I car_user_svc_set_lifecycle_listener: [101,string1]");
+        assertLogMessage("car_user_svc_set_lifecycle_listener", "[101,string1]");
     }
 
     @Test
     public void testWriteCarUserServiceResetLifecycleListener() {
         EventLogHelper.writeCarUserServiceResetLifecycleListener(101, "string1");
 
-        assertLogMessage("I car_user_svc_reset_lifecycle_listener: [101,string1]");
+        assertLogMessage("car_user_svc_reset_lifecycle_listener", "[101,string1]");
     }
 
     @Test
     public void testWriteCarUserServiceSwitchUserReq() {
         EventLogHelper.writeCarUserServiceSwitchUserReq(101, 102);
 
-        assertLogMessage("I car_user_svc_switch_user_req: [101,102]");
+        assertLogMessage("car_user_svc_switch_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceSwitchUserResp() {
         EventLogHelper.writeCarUserServiceSwitchUserResp(101, 102, "string");
 
-        assertLogMessage("I car_user_svc_switch_user_resp: [101,102,string]");
+        assertLogMessage("car_user_svc_switch_user_resp", "[101,102,string]");
     }
 
     @Test
     public void testWriteCarUserServicePostSwitchUserReq() {
         EventLogHelper.writeCarUserServicePostSwitchUserReq(101, 102);
 
-        assertLogMessage("I car_user_svc_post_switch_user_req: [101,102]");
+        assertLogMessage("car_user_svc_post_switch_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceGetUserAuthReq() {
         EventLogHelper.writeCarUserServiceGetUserAuthReq(101, 102, 103);
 
-        assertLogMessage("I car_user_svc_get_user_auth_req: [101,102,103]");
+        assertLogMessage("car_user_svc_get_user_auth_req", "[101,102,103]");
     }
 
     @Test
     public void testWriteCarUserServiceLogoutUserReq() {
         EventLogHelper.writeCarUserServiceLogoutUserReq(101, 102);
 
-        assertLogMessage("I car_user_svc_logout_user_req: [101,102]");
+        assertLogMessage("car_user_svc_logout_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceLogoutUserResp() {
         EventLogHelper.writeCarUserServiceLogoutUserResp(101, 102, "string");
 
-        assertLogMessage("I car_user_svc_logout_user_resp: [101,102,string]");
+        assertLogMessage("car_user_svc_logout_user_resp", "[101,102,string]");
     }
 
     @Test
     public void testWriteCarUserServiceGetUserAuthResp() {
         EventLogHelper.writeCarUserServiceGetUserAuthResp(101);
 
-        assertLogMessage("I car_user_svc_get_user_auth_resp: 101");
+        assertLogMessage("car_user_svc_get_user_auth_resp", "101");
     }
 
     @Test
     public void testWriteCarUserServiceSwitchUserUiReq() {
         EventLogHelper.writeCarUserServiceSwitchUserUiReq(101);
 
-        assertLogMessage("I car_user_svc_switch_user_ui_req: 101");
+        assertLogMessage("car_user_svc_switch_user_ui_req", "101");
     }
 
     @Test
     public void testWriteCarUserServiceSwitchUserFromHalReq() {
         EventLogHelper.writeCarUserServiceSwitchUserFromHalReq(101, 102);
 
-        assertLogMessage("I car_user_svc_switch_user_from_hal_req: [101,102]");
+        assertLogMessage("car_user_svc_switch_user_from_hal_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceSetUserAuthReq() {
         EventLogHelper.writeCarUserServiceSetUserAuthReq(101, 102, 103);
 
-        assertLogMessage("I car_user_svc_set_user_auth_req: [101,102,103]");
+        assertLogMessage("car_user_svc_set_user_auth_req", "[101,102,103]");
     }
 
     @Test
     public void testWriteCarUserServiceSetUserAuthResp() {
         EventLogHelper.writeCarUserServiceSetUserAuthResp(101, "string");
 
-        assertLogMessage("I car_user_svc_set_user_auth_resp: [101,string]");
+        assertLogMessage("car_user_svc_set_user_auth_resp", "[101,string]");
     }
 
     @Test
     public void testWriteCarUserServiceCreateUserReq() {
         EventLogHelper.writeCarUserServiceCreateUserReq("string1", "string2", 101, 102, 103);
 
-        assertLogMessage("I car_user_svc_create_user_req: [string1,string2,101,102,103]");
+        assertLogMessage("car_user_svc_create_user_req", "[string1,string2,101,102,103]");
     }
 
     @Test
     public void testWriteCarUserServiceCreateUserResp() {
         EventLogHelper.writeCarUserServiceCreateUserResp(101, 102, "string");
 
-        assertLogMessage("I car_user_svc_create_user_resp: [101,102,string]");
+        assertLogMessage("car_user_svc_create_user_resp", "[101,102,string]");
     }
 
     @Test
     public void testWriteCarUserServiceCreateUserUserCreated() {
         EventLogHelper.writeCarUserServiceCreateUserUserCreated(101, "string1", "string2", 102);
 
-        assertLogMessage("I car_user_svc_create_user_user_created: [101,string1,string2,102]");
+        assertLogMessage("car_user_svc_create_user_user_created", "[101,string1,string2,102]");
     }
 
     @Test
     public void testWriteCarUserServiceCreateUserUserRemoved() {
         EventLogHelper.writeCarUserServiceCreateUserUserRemoved(101, "string");
 
-        assertLogMessage("I car_user_svc_create_user_user_removed: [101,string]");
+        assertLogMessage("car_user_svc_create_user_user_removed", "[101,string]");
     }
 
     @Test
     public void testWriteCarUserServiceRemoveUserReq() {
         EventLogHelper.writeCarUserServiceRemoveUserReq(101, 102);
 
-        assertLogMessage("I car_user_svc_remove_user_req: [101,102]");
+        assertLogMessage("car_user_svc_remove_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceRemoveUserResp() {
         EventLogHelper.writeCarUserServiceRemoveUserResp(101, 102);
 
-        assertLogMessage("I car_user_svc_remove_user_resp: [101,102]");
+        assertLogMessage("car_user_svc_remove_user_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceNotifyAppLifecycleListener() {
         EventLogHelper.writeCarUserServiceNotifyAppLifecycleListener(101, "string", 102, 103, 104);
 
-        assertLogMessage("I car_user_svc_notify_app_lifecycle_listener: [101,string,102,103,104]");
+        assertLogMessage("car_user_svc_notify_app_lifecycle_listener", "[101,string,102,103,104]");
     }
 
     @Test
     public void testWriteCarUserServiceNotifyInternalLifecycleListener() {
         EventLogHelper.writeCarUserServiceNotifyInternalLifecycleListener("string", 102, 103, 104);
 
-        assertLogMessage("I car_user_svc_notify_internal_lifecycle_listener: [string,102,103,104]");
+        assertLogMessage("car_user_svc_notify_internal_lifecycle_listener", "[string,102,103,104]");
     }
 
     @Test
     public void testWriteCarUserServicePreCreationRequested() {
         EventLogHelper.writeCarUserServicePreCreationRequested(101, 102);
 
-        assertLogMessage("I car_user_svc_pre_creation_requested: [101,102]");
+        assertLogMessage("car_user_svc_pre_creation_requested", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServicePreCreationStatus() {
         EventLogHelper.writeCarUserServicePreCreationStatus(101, 102, 103, 104, 105, 106, 107);
 
-        assertLogMessage("I car_user_svc_pre_creation_status: [101,102,103,104,105,106,107]");
+        assertLogMessage("car_user_svc_pre_creation_status", "[101,102,103,104,105,106,107]");
     }
 
     @Test
     public void testWriteCarUserServiceStartUserInBackgroundReq() {
         EventLogHelper.writeCarUserServiceStartUserInBackgroundReq(101);
 
-        assertLogMessage("I car_user_svc_start_user_in_background_req: 101");
+        assertLogMessage("car_user_svc_start_user_in_background_req", "101");
     }
 
     @Test
     public void testWriteCarUserServiceStartUserInBackgroundResp() {
         EventLogHelper.writeCarUserServiceStartUserInBackgroundResp(101, 102);
 
-        assertLogMessage("I car_user_svc_start_user_in_background_resp: [101,102]");
+        assertLogMessage("car_user_svc_start_user_in_background_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceStopUserReq() {
         EventLogHelper.writeCarUserServiceStopUserReq(101);
 
-        assertLogMessage("I car_user_svc_stop_user_req: 101");
+        assertLogMessage("car_user_svc_stop_user_req", "101");
     }
 
     @Test
     public void testWriteCarUserServiceStopUserResp() {
         EventLogHelper.writeCarUserServiceStopUserResp(101, 102);
 
-        assertLogMessage("I car_user_svc_stop_user_resp: [101,102]");
+        assertLogMessage("car_user_svc_stop_user_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserServiceInitialUserInfoReqComplete() {
         EventLogHelper.writeCarUserServiceInitialUserInfoReqComplete(101);
 
-        assertLogMessage("I car_user_svc_initial_user_info_req_complete: 101");
+        assertLogMessage("car_user_svc_initial_user_info_req_complete", "101");
     }
 
     @Test
     public void testWriteCarUserHalInitialUserInfoReq() {
         EventLogHelper.writeCarUserHalInitialUserInfoReq(101, 102, 103);
 
-        assertLogMessage("I car_user_hal_initial_user_info_req: [101,102,103]");
+        assertLogMessage("car_user_hal_initial_user_info_req", "[101,102,103]");
     }
 
     @Test
@@ -394,29 +397,29 @@
         EventLogHelper.writeCarUserHalInitialUserInfoResp(101, 102, 103, 104, 105, "string1",
                 "string2");
 
-        assertLogMessage(
-                "I car_user_hal_initial_user_info_resp: [101,102,103,104,105,string1,string2]");
+        assertLogMessage("car_user_hal_initial_user_info_resp",
+                "[101,102,103,104,105,string1,string2]");
     }
 
     @Test
     public void testWriteCarUserHalSwitchUserReq() {
         EventLogHelper.writeCarUserHalSwitchUserReq(101, 102, 103, 104);
 
-        assertLogMessage("I car_user_hal_switch_user_req: [101,102,103,104]");
+        assertLogMessage("car_user_hal_switch_user_req", "[101,102,103,104]");
     }
 
     @Test
     public void testWriteCarUserHalSwitchUserResp() {
         EventLogHelper.writeCarUserHalSwitchUserResp(101, 102, 103, "string");
 
-        assertLogMessage("I car_user_hal_switch_user_resp: [101,102,103,string]");
+        assertLogMessage("car_user_hal_switch_user_resp", "[101,102,103,string]");
     }
 
     @Test
     public void testWriteCarUserHalPostSwitchUserReq() {
         EventLogHelper.writeCarUserHalPostSwitchUserReq(101, 102, 103);
 
-        assertLogMessage("I car_user_hal_post_switch_user_req: [101,102,103]");
+        assertLogMessage("car_user_hal_post_switch_user_req", "[101,102,103]");
     }
 
     @Test
@@ -426,7 +429,7 @@
         };
         EventLogHelper.writeCarUserHalGetUserAuthReq(objectArray);
 
-        assertLogMessage("I car_user_hal_get_user_auth_req: [101,102,103,string,104]");
+        assertLogMessage("car_user_hal_get_user_auth_req", "[101,102,103,string,104]");
     }
 
     @Test
@@ -436,14 +439,14 @@
         };
         EventLogHelper.writeCarUserHalGetUserAuthResp(objectArray);
 
-        assertLogMessage("I car_user_hal_get_user_auth_resp: [101,102,103,string,104]");
+        assertLogMessage("car_user_hal_get_user_auth_resp", "[101,102,103,string,104]");
     }
 
     @Test
     public void testWriteCarUserHalLegacySwitchUserReq() {
         EventLogHelper.writeCarUserHalLegacySwitchUserReq(101, 102, 103);
 
-        assertLogMessage("I car_user_hal_legacy_switch_user_req: [101,102,103]");
+        assertLogMessage("car_user_hal_legacy_switch_user_req", "[101,102,103]");
     }
 
     @Test
@@ -453,7 +456,7 @@
         };
         EventLogHelper.writeCarUserHalSetUserAuthReq(objectArray);
 
-        assertLogMessage("I car_user_hal_set_user_auth_req: [101,102,103,string,104]");
+        assertLogMessage("car_user_hal_set_user_auth_req", "[101,102,103,string,104]");
     }
 
     @Test
@@ -463,84 +466,84 @@
         };
         EventLogHelper.writeCarUserHalSetUserAuthResp(objectArray);
 
-        assertLogMessage("I car_user_hal_set_user_auth_resp: [101,102,103,string,104]");
+        assertLogMessage("car_user_hal_set_user_auth_resp", "[101,102,103,string,104]");
     }
 
     @Test
     public void testWriteCarUserHalOemSwitchUserReq() {
         EventLogHelper.writeCarUserHalOemSwitchUserReq(101, 102);
 
-        assertLogMessage("I car_user_hal_oem_switch_user_req: [101,102]");
+        assertLogMessage("car_user_hal_oem_switch_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserHalCreateUserReq() {
         EventLogHelper.writeCarUserHalCreateUserReq(101, "string", 102, 103);
 
-        assertLogMessage("I car_user_hal_create_user_req: [101,string,102,103]");
+        assertLogMessage("car_user_hal_create_user_req", "[101,string,102,103]");
     }
 
     @Test
     public void testWriteCarUserHalCreateUserResp() {
         EventLogHelper.writeCarUserHalCreateUserResp(101, 102, 103, "string");
 
-        assertLogMessage("I car_user_hal_create_user_resp: [101,102,103,string]");
+        assertLogMessage("car_user_hal_create_user_resp", "[101,102,103,string]");
     }
 
     @Test
     public void testWriteCarUserHalRemoveUserReq() {
         EventLogHelper.writeCarUserHalRemoveUserReq(101, 102);
 
-        assertLogMessage("I car_user_hal_remove_user_req: [101,102]");
+        assertLogMessage("car_user_hal_remove_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserManagerAddListener() {
         EventLogHelper.writeCarUserManagerAddListener(101, "string", true);
 
-        assertLogMessage("I car_user_mgr_add_listener: [101,string,1]");
+        assertLogMessage("car_user_mgr_add_listener", "[101,string,1]");
     }
 
     @Test
     public void testWriteCarUserManagerRemoveListener() {
         EventLogHelper.writeCarUserManagerRemoveListener(101, "string");
 
-        assertLogMessage("I car_user_mgr_remove_listener: [101,string]");
+        assertLogMessage("car_user_mgr_remove_listener", "[101,string]");
     }
 
     @Test
     public void testWriteCarUserManagerDisconnected() {
         EventLogHelper.writeCarUserManagerDisconnected(101);
 
-        assertLogMessage("I car_user_mgr_disconnected: 101");
+        assertLogMessage("car_user_mgr_disconnected", "101");
     }
 
     @Test
     public void testWriteCarUserManagerSwitchUserReq() {
         EventLogHelper.writeCarUserManagerSwitchUserReq(101, 102);
 
-        assertLogMessage("I car_user_mgr_switch_user_req: [101,102]");
+        assertLogMessage("car_user_mgr_switch_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserManagerSwitchUserResp() {
         EventLogHelper.writeCarUserManagerSwitchUserResp(101, 102, "string");
 
-        assertLogMessage("I car_user_mgr_switch_user_resp: [101,102,string]");
+        assertLogMessage("car_user_mgr_switch_user_resp", "[101,102,string]");
     }
 
     @Test
     public void testWriteCarUserManagerLogoutUserReq() {
         EventLogHelper.writeCarUserManagerLogoutUserReq(42108);
 
-        assertLogMessage("I car_user_mgr_logout_user_req: [42108]");
+        assertLogMessage("car_user_mgr_logout_user_req", "42108");
     }
 
     @Test
     public void testWriteCarUserManagerLogoutUserResp() {
         EventLogHelper.writeCarUserManagerLogoutUserResp(42108, 1, "D'OH!");
 
-        assertLogMessage("I car_user_mgr_logout_user_resp: [42108,1,D'OH!]");
+        assertLogMessage("car_user_mgr_logout_user_resp", "[42108,1,D'OH!]");
     }
 
     @Test
@@ -550,7 +553,7 @@
         };
         EventLogHelper.writeCarUserManagerGetUserAuthReq(objectArray);
 
-        assertLogMessage("I car_user_mgr_get_user_auth_req: [101,102,103,string,104]");
+        assertLogMessage("car_user_mgr_get_user_auth_req", "[101,102,103,string,104]");
     }
 
     @Test
@@ -560,7 +563,7 @@
         };
         EventLogHelper.writeCarUserManagerGetUserAuthResp(objectArray);
 
-        assertLogMessage("I car_user_mgr_get_user_auth_resp: [101,102,103,string,104]");
+        assertLogMessage("car_user_mgr_get_user_auth_resp", "[101,102,103,string,104]");
     }
 
     @Test
@@ -570,7 +573,7 @@
         };
         EventLogHelper.writeCarUserManagerSetUserAuthReq(objectArray);
 
-        assertLogMessage("I car_user_mgr_set_user_auth_req: [101,102,103,string,104]");
+        assertLogMessage("car_user_mgr_set_user_auth_req", "[101,102,103,string,104]");
     }
 
     @Test
@@ -580,136 +583,140 @@
         };
         EventLogHelper.writeCarUserManagerSetUserAuthResp(objectArray);
 
-        assertLogMessage("I car_user_mgr_set_user_auth_resp: [101,102,103,string,104]");
+        assertLogMessage("car_user_mgr_set_user_auth_resp", "[101,102,103,string,104]");
     }
 
     @Test
     public void testWriteCarUserManagerCreateUserReq() {
         EventLogHelper.writeCarUserManagerCreateUserReq(101, "string1", "string2", 102);
 
-        assertLogMessage("I car_user_mgr_create_user_req: [101,string1,string2,102]");
+        assertLogMessage("car_user_mgr_create_user_req", "[101,string1,string2,102]");
     }
 
     @Test
     public void testWriteCarUserManagerCreateUserResp() {
         EventLogHelper.writeCarUserManagerCreateUserResp(101, 102, "string");
 
-        assertLogMessage("I car_user_mgr_create_user_resp: [101,102,string]");
+        assertLogMessage("car_user_mgr_create_user_resp", "[101,102,string]");
     }
 
     @Test
     public void testWriteCarUserManagerRemoveUserReq() {
         EventLogHelper.writeCarUserManagerRemoveUserReq(101, 102);
 
-        assertLogMessage("I car_user_mgr_remove_user_req: [101,102]");
+        assertLogMessage("car_user_mgr_remove_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserManagerRemoveUserResp() {
         EventLogHelper.writeCarUserManagerRemoveUserResp(101, 102);
 
-        assertLogMessage("I car_user_mgr_remove_user_resp: [101,102]");
+        assertLogMessage("car_user_mgr_remove_user_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarUserManagerNotifyLifecycleListener() {
         EventLogHelper.writeCarUserManagerNotifyLifecycleListener(101, 102, 103, 104);
 
-        assertLogMessage("I car_user_mgr_notify_lifecycle_listener: [101,102,103,104]");
+        assertLogMessage("car_user_mgr_notify_lifecycle_listener", "[101,102,103,104]");
     }
 
     @Test
     public void testWriteCarUserManagerPreCreateUserReq() {
         EventLogHelper.writeCarUserManagerPreCreateUserReq(101);
 
-        assertLogMessage("I car_user_mgr_pre_create_user_req: 101");
+        assertLogMessage("car_user_mgr_pre_create_user_req", "101");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerRemoveUserReq() {
         EventLogHelper.writeCarDevicePolicyManagerRemoveUserReq(101, 102);
 
-        assertLogMessage("I car_dp_mgr_remove_user_req: [101,102]");
+        assertLogMessage("car_dp_mgr_remove_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerRemoveUserResp() {
         EventLogHelper.writeCarDevicePolicyManagerRemoveUserResp(101, 102);
 
-        assertLogMessage("I car_dp_mgr_remove_user_resp: [101,102]");
+        assertLogMessage("car_dp_mgr_remove_user_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerCreateUserReq() {
         EventLogHelper.writeCarDevicePolicyManagerCreateUserReq(101, "string", 102);
 
-        assertLogMessage("I car_dp_mgr_create_user_req: [101,string,102]");
+        assertLogMessage("car_dp_mgr_create_user_req", "[101,string,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerCreateUserResp() {
         EventLogHelper.writeCarDevicePolicyManagerCreateUserResp(101, 102);
 
-        assertLogMessage("I car_dp_mgr_create_user_resp: [101,102]");
+        assertLogMessage("car_dp_mgr_create_user_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerStartUserInBackgroundReq() {
         EventLogHelper.writeCarDevicePolicyManagerStartUserInBackgroundReq(101, 102);
 
-        assertLogMessage("I car_dp_mgr_start_user_in_background_req: [101,102]");
+        assertLogMessage("car_dp_mgr_start_user_in_background_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerStartUserInBackgroundResp() {
         EventLogHelper.writeCarDevicePolicyManagerStartUserInBackgroundResp(101, 102);
 
-        assertLogMessage("I car_dp_mgr_start_user_in_background_resp: [101,102]");
+        assertLogMessage("car_dp_mgr_start_user_in_background_resp", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerStopUserReq() {
         EventLogHelper.writeCarDevicePolicyManagerStopUserReq(101, 102);
 
-        assertLogMessage("I car_dp_mgr_stop_user_req: [101,102]");
+        assertLogMessage("car_dp_mgr_stop_user_req", "[101,102]");
     }
 
     @Test
     public void testWriteCarDevicePolicyManagerStopUserResp() {
         EventLogHelper.writeCarDevicePolicyManagerStopUserResp(101, 102);
 
-        assertLogMessage("I car_dp_mgr_stop_user_resp: [101,102]");
+        assertLogMessage("car_dp_mgr_stop_user_resp", "[101,102]");
     }
 
     @Test
     public void testWritePowerPolicyChange() {
         EventLogHelper.writePowerPolicyChange("string");
 
-        assertLogMessage("I car_pwr_mgr_pwr_policy_change: string");
+        assertLogMessage("car_pwr_mgr_pwr_policy_change", "string");
     }
 
     @Test
     public void testWriteCarPowerManagerStateChange() {
         EventLogHelper.writeCarPowerManagerStateChange(101);
 
-        assertLogMessage("I car_pwr_mgr_state_change: 101");
+        assertLogMessage("car_pwr_mgr_state_change", "101");
     }
 
     @Test
     public void testWriteCarPowerManagerStateRequest() {
         EventLogHelper.writeCarPowerManagerStateRequest(101, 102);
 
-        assertLogMessage("I car_pwr_mgr_state_req: [101,102]");
+        assertLogMessage("car_pwr_mgr_state_req", "[101,102]");
     }
 
     @Test
     public void testWriteGarageModeEvent() {
         EventLogHelper.writeGarageModeEvent(101);
 
-        assertLogMessage("I car_pwr_mgr_garage_mode: 101");
+        assertLogMessage("car_pwr_mgr_garage_mode", "101");
     }
 
-    private void assertLogMessage(String match) {
-        LogcatHelper.assertLogcatMessage(match, BUFFER, TIMEOUT_MS);
+    private void assertLogMessage(String event, String values) {
+        assertLogcatMessage(EVENTS, INFO, event, values, TIMEOUT_MS);
+    }
+
+    private void assertLogMessage(String event) {
+        assertLogMessage(event, /* values=*/ "");
     }
 }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/util/LogcatHelper.java b/tests/tests/car_builtin/src/android/car/cts/builtin/util/LogcatHelper.java
index f067980..4293f20 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/util/LogcatHelper.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/util/LogcatHelper.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.fail;
 
 import android.app.UiAutomation;
+import android.car.cts.builtin.util.LogcatHelper.Level;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
 import android.util.Log;
@@ -39,6 +40,8 @@
 
     private static final boolean VERBOSE = false;
 
+    private static final int DEFAULT_TIMEOUT_MS = 60_000;
+
     private LogcatHelper() {}
 
     /**
@@ -49,31 +52,52 @@
     }
 
     /**
-     * Asserts if a message appears in logcat messages within given timeout. All logcat buffers are
-     * searched.
-     *
-     * @param match to find in the logcat messages
-     * @param timeout for waiting the message
+     * Logcat levels to search.
      */
-    public static void assertLogcatMessage(String match, int timeout) {
-        assertLogcatMessage(match, Buffer.ALL, timeout);
+    public enum Level {
+        VERBOSE("V"), DEBUG("D"), INFO("I"), WARN("W"), ERROR("E"), ASSERT("A");
+
+        private String mValue;
+
+        public String getValue() {
+            return mValue;
+        }
+
+        Level(String v) {
+            mValue = v;
+        }
     }
 
     /**
-     * Asserts if a message appears in logcat messages within given timeout in the given buffer.
+     * Asserts that a message appears on {@code logcat}, using a default timeout.
      *
-     * @param match to find in the logcat messages
-     * @param buffer is logcat buffer to search
+     * @param buffer logcat buffer to search
+     * @param level expected log level
+     * @parma tag expected log tag
+     * @param message substring of the expected message
      * @param timeout for waiting the message
      */
-    public static void assertLogcatMessage(String match, Buffer buffer, int timeout) {
+    public static void assertLogcatMessage(Buffer buffer, Level level, String tag, String message) {
+        assertLogcatMessage(buffer, level, tag, message, DEFAULT_TIMEOUT_MS);
+    }
+
+    /**
+     * Asserts that a message appears on {@code logcat}.
+     *
+     * @param buffer logcat buffer to search
+     * @param level expected log level
+     * @parma tag expected log tag
+     * @param message substring of the expected message
+     * @param timeout for waiting the message
+     */
+    public static void assertLogcatMessage(Buffer buffer, Level level, String tag, String message,
+            int timeout) {
+        String match = String.format("%s %s: %s", level.mValue, tag, message);
         long startTime = SystemClock.elapsedRealtime();
         UiAutomation automation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         String command = "logcat -b " + buffer.name().toLowerCase();
         ParcelFileDescriptor output = automation.executeShellCommand(command);
-        if (VERBOSE) {
-            Log.v(TAG, "ran '" + command + "'; will now look for '" + match + "'");
-        }
+        Log.d(TAG, "ran '" + command + "'; will now look for '" + match + "'");
         FileDescriptor fd = output.getFileDescriptor();
         FileInputStream fileInputStream = new FileInputStream(fd);
         try (BufferedReader bufferedReader = new BufferedReader(
@@ -84,9 +108,7 @@
                     Log.v(TAG, "Checking line '" + line + "'");
                 }
                 if (line.contains(match)) {
-                    if (VERBOSE) {
-                        Log.v(TAG, "Found match, returning");
-                    }
+                    Log.d(TAG, "Found match on line '" + line + "', returning");
                     return;
                 }
                 if ((SystemClock.elapsedRealtime() - startTime) > timeout) {
@@ -99,13 +121,17 @@
     }
 
     /**
-     * Asserts if a message does not appears in logcat messages within given timeout. If the message
-     * appears, then assertion will fail.
+     * Asserts that a message DOESN'T appears on {@code logcat}.
      *
-     * @param match to find in the logcat messages
+     * @param buffer is logcat buffer to search
+     * @param level expected log level
+     * @parma tag expected log tag
+     * @param message substring of the message that shouldn't appeard
      * @param timeout for waiting the message
      */
-    public static void assertNoLogcatMessage(String match, int timeout) throws Exception {
+    public static void assertNoLogcatMessage(Buffer buffer, Level level, String tag, String message,
+            int timeout) throws Exception {
+        String match = String.format("%s %s: %s", level.mValue, tag, message);
         long startTime = SystemClock.elapsedRealtime();
         UiAutomation automation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         ParcelFileDescriptor output = automation.executeShellCommand("logcat -b all");
@@ -131,6 +157,16 @@
      * Clears all logs.
      */
     public static void clearLog() {
+        if (VERBOSE) {
+            Log.d(TAG, "Clearing logcat logs");
+        }
         SystemUtil.runShellCommand("logcat -b all -c");
     }
+
+    /**
+     * Sets the log level of the given tag.
+     */
+    public static void setLogLevel(String tag, Level level) {
+        SystemUtil.runShellCommand("setprop log.tag." + tag + " " + level.getValue());
+    }
 }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/util/SlogfTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/util/SlogfTest.java
index 83f630d..1740eb5 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/util/SlogfTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/util/SlogfTest.java
@@ -16,28 +16,27 @@
 
 package android.car.cts.builtin.util;
 
-import static android.car.cts.builtin.util.SlogfTest.Level.ASSERT;
-import static android.car.cts.builtin.util.SlogfTest.Level.DEBUG;
-import static android.car.cts.builtin.util.SlogfTest.Level.ERROR;
-import static android.car.cts.builtin.util.SlogfTest.Level.INFO;
-import static android.car.cts.builtin.util.SlogfTest.Level.VERBOSE;
-import static android.car.cts.builtin.util.SlogfTest.Level.WARN;
+import static android.car.cts.builtin.util.LogcatHelper.Level.ASSERT;
+import static android.car.cts.builtin.util.LogcatHelper.Level.DEBUG;
+import static android.car.cts.builtin.util.LogcatHelper.Level.ERROR;
+import static android.car.cts.builtin.util.LogcatHelper.Level.INFO;
+import static android.car.cts.builtin.util.LogcatHelper.Level.VERBOSE;
+import static android.car.cts.builtin.util.LogcatHelper.Level.WARN;
+import static android.car.cts.builtin.util.LogcatHelper.clearLog;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.car.builtin.util.Slogf;
+import android.car.cts.builtin.util.LogcatHelper.Level;
 import android.util.Log;
 
-import com.android.compatibility.common.util.SystemUtil;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public final class SlogfTest {
     private static final String TAG = SlogfTest.class.getSimpleName();
-    // Comes from Slogf.CAR_TEST_TAG;
-    private static final String CAR_TEST_TAG = "CAR.TEST";
+
     private static final int TIMEOUT_MS = 10_000;
     // All Slogf would be logged to system buffer.
     private static final LogcatHelper.Buffer BUFFER = LogcatHelper.Buffer.SYSTEM;
@@ -51,20 +50,6 @@
     private static final String FORMATTED_MSG = "This message is a format with two args %s and %s.";
     private static final String EXCEPTION_MSG = "This message should exist in logcat.";
 
-    enum Level {
-        VERBOSE("V"), DEBUG("D"), INFO("I"), WARN("W"), ERROR("E"), ASSERT("A");
-
-        private String mValue;
-
-        public String getValue() {
-            return mValue;
-        }
-
-        Level(String v) {
-            mValue = v;
-        }
-    }
-
     @Before
     public void setup() {
         setLogLevel(VERBOSE);
@@ -389,15 +374,24 @@
     @Test
     public void testIsLoggableFalse() throws Exception {
         setLogLevel(ERROR);
+        setCarTestTagLogLevel(ASSERT);
 
         assertThat(Slogf.isLoggable(TAG, Log.VERBOSE)).isFalse();
     }
 
     @Test
+    public void testIsLoggableFalse_withCarTestTagEnabled() throws Exception {
+        setLogLevel(ERROR);
+        setCarTestTagLogLevel(VERBOSE);
+
+        assertThat(Slogf.isLoggable(TAG, Log.VERBOSE)).isTrue();
+    }
+
+    @Test
     public void testSlogfIsfLoggableWorksSameAsLogIsLoggable() throws Exception {
         setLogLevel(INFO);
         // Emulate the tag as if it's not in the car tests.
-        setLogLevel(CAR_TEST_TAG, ASSERT);
+        setCarTestTagLogLevel(ASSERT);
 
         assertThat(Log.isLoggable(TAG, Log.DEBUG)).isFalse();
         assertThat(Slogf.isLoggable(TAG, Log.DEBUG)).isFalse();
@@ -414,29 +408,24 @@
         assertThat(Slogf.isLoggable(TAG, Log.DEBUG)).isTrue();
     }
 
-    private void clearLog() {
-        LogcatHelper.clearLog();
-    }
-
     private void setLogLevel(Level level) {
-        setLogLevel(TAG, level);
+        LogcatHelper.setLogLevel(TAG, level);
     }
 
-    private void setLogLevel(String tag, Level level) {
-        SystemUtil.runShellCommand("setprop log.tag." + tag + " " + level.getValue());
+    private void setCarTestTagLogLevel(Level level) {
+        // CAR.TEST Comes from Slogf.CAR_TEST_TAG;
+        LogcatHelper.setLogLevel("CAR.TEST", level);
     }
 
     private void assertNoLogcatMessage(Level level, String format, Object... args)
             throws Exception {
-        String match = String.format(LOGCAT_LINE_FORMAT, level.getValue(), TAG,
-                String.format(format, args));
-        LogcatHelper.assertNoLogcatMessage(match, NOT_LOGGED_WAIT_TIME_MS);
+        String message = String.format(format, args);
+        LogcatHelper.assertNoLogcatMessage(BUFFER, level, TAG, message, NOT_LOGGED_WAIT_TIME_MS);
     }
 
     private void assertLogcatMessage(Level level, String format, Object... args) {
-        String match = String.format(LOGCAT_LINE_FORMAT, level.getValue(), TAG,
-                String.format(format, args));
-        LogcatHelper.assertLogcatMessage(match, BUFFER, TIMEOUT_MS);
+        String message = String.format(format, args);
+        LogcatHelper.assertLogcatMessage(BUFFER, level, TAG, message, TIMEOUT_MS);
     }
 
     private void assertLogcatStackTrace(Level level, Throwable throwable) {
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimeUtilsTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimeUtilsTest.java
index 92393d3..099b5ad 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimeUtilsTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimeUtilsTest.java
@@ -16,16 +16,26 @@
 
 package android.car.cts.builtin.util;
 
+import static android.car.cts.builtin.util.LogcatHelper.Buffer.MAIN;
+import static android.car.cts.builtin.util.LogcatHelper.Level.INFO;
+import static android.car.cts.builtin.util.LogcatHelper.assertLogcatMessage;
+import static android.car.cts.builtin.util.LogcatHelper.clearLog;
+
 import android.car.builtin.util.TimeUtils;
 
+import org.junit.Before;
 import org.junit.Test;
 
 import java.io.PrintWriter;
 
 public final class TimeUtilsTest {
-    private PrintWriter mWriter = new PrintWriter(System.out);
 
-    private static final int TIMEOUT_MS = 60_000;
+    private final PrintWriter mWriter = new PrintWriter(System.out);
+
+    @Before
+    public void clearLogcat() {
+        clearLog();
+    }
 
     @Test
     public void testDumpTime() {
@@ -33,7 +43,7 @@
         mWriter.flush();
 
         // Time utils change long into date-time format.
-        LogcatHelper.assertLogcatMessage("System.out: 1970-01-01 00:00:00.179", TIMEOUT_MS);
+        assertLogMessage("1970-01-01 00:00:00.179");
     }
 
     @Test
@@ -42,6 +52,10 @@
         mWriter.flush();
 
         // Time utils change long into human readable text.
-        LogcatHelper.assertLogcatMessage("System.out: +789ms", TIMEOUT_MS);
+        assertLogMessage("+789ms");
+    }
+
+    private void assertLogMessage(String message) {
+        assertLogcatMessage(MAIN, INFO, "System.out", message);
     }
 }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimingsTraceLogTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimingsTraceLogTest.java
index 0fec391..0b74a16 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimingsTraceLogTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/util/TimingsTraceLogTest.java
@@ -16,17 +16,25 @@
 
 package android.car.cts.builtin.util;
 
+import static android.car.cts.builtin.util.LogcatHelper.Buffer.SYSTEM;
+import static android.car.cts.builtin.util.LogcatHelper.Level.DEBUG;
 import static android.car.cts.builtin.util.LogcatHelper.assertLogcatMessage;
+import static android.car.cts.builtin.util.LogcatHelper.clearLog;
 
 import android.car.builtin.os.TraceHelper;
 import android.car.builtin.util.TimingsTraceLog;
 
+import org.junit.Before;
 import org.junit.Test;
 
 public final class TimingsTraceLogTest {
 
     private static final String TAG = TimingsTraceLogTest.class.getSimpleName();
-    private static final int TIMEOUT_MS = 60_000;
+
+    @Before
+    public void clearLogcat() {
+        clearLog();
+    }
 
     @Test
     public void testTimingsTraceLog() {
@@ -35,8 +43,7 @@
         timingsTraceLog.traceBegin("testTimingsTraceLog");
         timingsTraceLog.traceEnd();
 
-        assertLogcatMessage("TimingsTraceLogTest: testTimingsTraceLog took to complete",
-                TIMEOUT_MS);
+        assertLogMessage("testTimingsTraceLog took to complete");
     }
 
     @Test
@@ -45,8 +52,10 @@
                 new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE);
         timingsTraceLog.logDuration("testTimingsTraceLogDuration", 159);
 
-        assertLogcatMessage(
-                "TimingsTraceLogTest: testTimingsTraceLogDuration took to complete: 159ms",
-                TIMEOUT_MS);
+        assertLogMessage("testTimingsTraceLogDuration took to complete: 159ms");
+    }
+
+    private void assertLogMessage(String message) {
+        assertLogcatMessage(SYSTEM, DEBUG, TAG, message);
     }
 }
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/CompanionDeviceManagerUi.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/CompanionDeviceManagerUi.kt
index e144dc8..8b8ead8 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/CompanionDeviceManagerUi.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/CompanionDeviceManagerUi.kt
@@ -52,6 +52,9 @@
 
     fun clickNegativeButton() = click(NEGATIVE_BUTTON, "Negative button")
 
+    fun clickNegativeButtonMultipleDevices() = click(
+            NEGATIVE_BUTTON_MULTIPLE_DEVICES, "Negative button for multiple devices")
+
     private fun click(selector: BySelector, description: String) = ui.waitShortAndFind(
             Until.findObject(selector), "$description  is not found")
             .click()
@@ -66,6 +69,8 @@
                 By.pkg(PACKAGE_NAME).clazz(".Button").clickable(true)
         private val POSITIVE_BUTTON = By.copy(CLICKABLE_BUTTON).res(PACKAGE_NAME, "btn_positive")
         private val NEGATIVE_BUTTON = By.copy(CLICKABLE_BUTTON).res(PACKAGE_NAME, "btn_negative")
+        private val NEGATIVE_BUTTON_MULTIPLE_DEVICES = By.copy(CLICKABLE_BUTTON)
+                .res(PACKAGE_NAME, "btn_negative_multiple_devices")
 
         private val DEVICE_LIST = By.pkg(PACKAGE_NAME)
             .clazz("androidx.recyclerview.widget.RecyclerView")
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
index 05e9e31a..db46b68 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/UiAutomationTestBase.kt
@@ -89,7 +89,11 @@
         displayName: String? = null
     ) = test_cancelled(singleDevice, selfManaged, displayName) {
             // User "rejects" the request.
-            confirmationUi.clickNegativeButton()
+            if (singleDevice || selfManaged) {
+                confirmationUi.clickNegativeButton()
+            } else {
+                confirmationUi.clickNegativeButtonMultipleDevices()
+            }
         }
 
     protected fun test_userDismissed(
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
new file mode 100644
index 0000000..d47696e
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
@@ -0,0 +1,291 @@
+/*
+ * 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.content.pm.cts
+
+import android.Manifest
+import android.app.UiAutomation
+import android.content.Context
+import android.content.Context.RECEIVER_EXPORTED
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.content.pm.cts.PackageManagerShellCommandTest.FullyRemovedBroadcastReceiver
+import android.content.pm.cts.util.AbandonAllPackageSessionsRule
+import androidx.test.InstrumentationRegistry
+import com.android.bedstead.harrier.BedsteadJUnit4
+import com.android.bedstead.harrier.DeviceState
+import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser
+import com.android.bedstead.harrier.annotations.StringTestParameter
+import com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS
+import com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL
+import com.android.bedstead.nene.users.UserReference
+import com.android.compatibility.common.util.SystemUtil
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.File
+
+@EnsureHasSecondaryUser
+@RunWith(BedsteadJUnit4::class)
+class PackageManagerShellCommandMultiUserTest {
+
+    companion object {
+
+        private const val TEST_APP_PACKAGE = PackageManagerShellCommandTest.TEST_APP_PACKAGE
+        private const val TEST_HW5 = PackageManagerShellCommandTest.TEST_HW5
+
+        @JvmField
+        @ClassRule
+        @Rule
+        val deviceState = DeviceState()
+
+        @JvmField
+        @ClassRule
+        var mAbandonSessionsRule = AbandonAllPackageSessionsRule()
+
+        private val context: Context = InstrumentationRegistry.getContext()
+        private val uiAutomation: UiAutomation =
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+    }
+
+    private lateinit var primaryUser: UserReference
+    private lateinit var secondaryUser: UserReference
+
+    @Before
+    fun cacheUsers() {
+        primaryUser = deviceState.primaryUser()
+        secondaryUser = deviceState.secondaryUser()
+    }
+
+    private var mPackageVerifier: String? = null
+    private var mStreamingVerificationTimeoutMs =
+        PackageManagerShellCommandTest.DEFAULT_STREAMING_VERIFICATION_TIMEOUT
+
+    @Before
+    fun setup() {
+        uninstallPackageSilently(TEST_APP_PACKAGE)
+        assertFalse(PackageManagerShellCommandTest.isAppInstalled(TEST_APP_PACKAGE))
+        mPackageVerifier =
+            SystemUtil.runShellCommand("settings get global verifier_verify_adb_installs")
+        // Disable the package verifier for non-incremental installations to avoid the dialog
+        // when installing an app.
+        SystemUtil.runShellCommand("settings put global verifier_verify_adb_installs 0")
+        mStreamingVerificationTimeoutMs = SystemUtil.runShellCommand(
+            "settings get global streaming_verifier_timeout"
+        )
+            .toLongOrNull()
+            ?: PackageManagerShellCommandTest.DEFAULT_STREAMING_VERIFICATION_TIMEOUT
+    }
+
+    @After
+    fun reset() {
+        uninstallPackageSilently(TEST_APP_PACKAGE)
+        assertFalse(PackageManagerShellCommandTest.isAppInstalled(TEST_APP_PACKAGE))
+        assertEquals(null, PackageManagerShellCommandTest.getSplits(TEST_APP_PACKAGE))
+
+        // Reset the global settings to their original values.
+        SystemUtil.runShellCommand(
+            "settings put global verifier_verify_adb_installs $mPackageVerifier"
+        )
+
+        // Set the test override to invalid.
+        setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", "invalid")
+        setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "invalid")
+        setSystemProperty("debug.pm.adb_verifier_override_package", "invalid")
+    }
+
+    @Test
+    fun testGetFirstInstallTime(
+        @StringTestParameter(
+            "install",
+            "install-streaming",
+            "install-incremental"
+        ) installTypeString: String
+    ) {
+        val startTimeMillisForPrimaryUser = System.currentTimeMillis()
+        installPackageAsUser(TEST_HW5, primaryUser, installTypeString)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        val origFirstInstallTimeForPrimaryUser =
+            getFirstInstallTimeAsUser(TEST_APP_PACKAGE, primaryUser)
+        // Validate the timestamp
+        assertTrue(origFirstInstallTimeForPrimaryUser > 0)
+        assertTrue(startTimeMillisForPrimaryUser < origFirstInstallTimeForPrimaryUser)
+        assertTrue(System.currentTimeMillis() > origFirstInstallTimeForPrimaryUser)
+
+        // Install again with replace and the firstInstallTime should remain the same
+        installPackage(TEST_HW5, installTypeString)
+        var firstInstallTimeForPrimaryUser =
+            getFirstInstallTimeAsUser(TEST_APP_PACKAGE, primaryUser)
+        assertEquals(origFirstInstallTimeForPrimaryUser, firstInstallTimeForPrimaryUser)
+
+        // Start another user and install this test itself for that user
+        var startTimeMillisForSecondaryUser = System.currentTimeMillis()
+        installExistingPackageAsUser(context.packageName, secondaryUser)
+        assertTrue(isAppInstalledForUser(context.packageName, secondaryUser))
+        // Install test package with replace
+        installPackageAsUser(TEST_HW5, secondaryUser, installTypeString)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        firstInstallTimeForPrimaryUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, primaryUser)
+        // firstInstallTime should remain unchanged for the current user
+        assertEquals(origFirstInstallTimeForPrimaryUser, firstInstallTimeForPrimaryUser)
+        var firstInstallTimeForSecondaryUser =
+            getFirstInstallTimeAsUser(TEST_APP_PACKAGE, secondaryUser)
+        // firstInstallTime for the other user should be different
+        assertNotEquals(firstInstallTimeForPrimaryUser, firstInstallTimeForSecondaryUser)
+        assertTrue(startTimeMillisForSecondaryUser < firstInstallTimeForSecondaryUser)
+        assertTrue(System.currentTimeMillis() > firstInstallTimeForSecondaryUser)
+
+        // Uninstall for the other user
+        uninstallPackageAsUser(TEST_APP_PACKAGE, secondaryUser)
+        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        // Install test package as an existing package
+        startTimeMillisForSecondaryUser = System.currentTimeMillis()
+        installExistingPackageAsUser(TEST_APP_PACKAGE, secondaryUser)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        firstInstallTimeForPrimaryUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, primaryUser)
+        // firstInstallTime still remains unchanged for the current user
+        assertEquals(origFirstInstallTimeForPrimaryUser, firstInstallTimeForPrimaryUser)
+        firstInstallTimeForSecondaryUser =
+            getFirstInstallTimeAsUser(TEST_APP_PACKAGE, secondaryUser)
+        // firstInstallTime for the other user should be different
+        assertNotEquals(firstInstallTimeForPrimaryUser, firstInstallTimeForSecondaryUser)
+        assertTrue(startTimeMillisForSecondaryUser < firstInstallTimeForSecondaryUser)
+        assertTrue(System.currentTimeMillis() > firstInstallTimeForSecondaryUser)
+
+        // Uninstall for all users
+        uninstallPackageSilently(TEST_APP_PACKAGE)
+        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        // Reinstall for all users
+        installPackage(TEST_HW5, installTypeString)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        firstInstallTimeForPrimaryUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, primaryUser)
+        // First install time is now different because the package was fully uninstalled
+        assertNotEquals(origFirstInstallTimeForPrimaryUser, firstInstallTimeForPrimaryUser)
+        firstInstallTimeForSecondaryUser =
+            getFirstInstallTimeAsUser(TEST_APP_PACKAGE, secondaryUser)
+        // Same firstInstallTime because package was installed for both users at the same time
+        assertEquals(firstInstallTimeForPrimaryUser, firstInstallTimeForSecondaryUser)
+    }
+
+    @Test
+    fun testPackageFullyRemovedBroadcastAfterUninstall(
+        @StringTestParameter(
+            "install",
+            "install-streaming",
+            "install-incremental"
+        ) installTypeString: String
+    ) {
+        installExistingPackageAsUser(context.packageName, secondaryUser)
+        installPackage(TEST_HW5, installTypeString)
+        assertTrue(isAppInstalledForUser(context.packageName, primaryUser))
+        assertTrue(isAppInstalledForUser(context.packageName, secondaryUser))
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        val broadcastReceiverForPrimaryUser =
+            FullyRemovedBroadcastReceiver(TEST_APP_PACKAGE, primaryUser.id())
+        val broadcastReceiverForSecondaryUser =
+            FullyRemovedBroadcastReceiver(TEST_APP_PACKAGE, secondaryUser.id())
+        val intentFilter = IntentFilter()
+        intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
+        intentFilter.addDataScheme("package")
+        context.registerReceiver(
+            broadcastReceiverForPrimaryUser, intentFilter, RECEIVER_EXPORTED
+        )
+        uiAutomation.adoptShellPermissionIdentity(
+            Manifest.permission.INTERACT_ACROSS_USERS,
+            Manifest.permission.INTERACT_ACROSS_USERS_FULL
+        )
+        try {
+            context.createContextAsUser(secondaryUser.userHandle(), 0).registerReceiver(
+                broadcastReceiverForSecondaryUser, intentFilter, RECEIVER_EXPORTED
+            )
+        } finally {
+            uiAutomation.dropShellPermissionIdentity()
+        }
+        // Verify that uninstall with "keep data" doesn't send the broadcast
+        uninstallPackageWithKeepData(TEST_APP_PACKAGE, secondaryUser)
+        assertFalse(broadcastReceiverForSecondaryUser.isBroadcastReceived)
+        installExistingPackageAsUser(TEST_APP_PACKAGE, secondaryUser)
+        // Verify that uninstall on a specific user only sends the broadcast to the user
+        uninstallPackageAsUser(TEST_APP_PACKAGE, secondaryUser)
+        assertTrue(broadcastReceiverForSecondaryUser.isBroadcastReceived)
+        assertFalse(broadcastReceiverForPrimaryUser.isBroadcastReceived)
+        uninstallPackageSilently(TEST_APP_PACKAGE)
+        assertTrue(broadcastReceiverForPrimaryUser.isBroadcastReceived)
+    }
+
+    private fun getFirstInstallTimeAsUser(packageName: String, user: UserReference) =
+        context.createContextAsUser(user.userHandle(), 0)
+            .packageManager
+            .getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))
+            .firstInstallTime
+
+    private fun installPackage(baseName: String, installTypeString: String) {
+        val file = File(PackageManagerShellCommandTest.createApkPath(baseName))
+        assertThat(SystemUtil.runShellCommand("pm $installTypeString -t -g ${file.path}"))
+            .isEqualTo("Success\n")
+    }
+
+    private fun installExistingPackageAsUser(packageName: String, user: UserReference) {
+        val userId = user.id()
+        assertThat(SystemUtil.runShellCommand("pm install-existing --user $userId $packageName"))
+            .isEqualTo("Package $packageName installed for user: $userId\n")
+    }
+
+    private fun installPackageAsUser(
+        baseName: String,
+        user: UserReference,
+        installTypeString: String
+    ) {
+        val file = File(PackageManagerShellCommandTest.createApkPath(baseName))
+        assertThat(
+            SystemUtil.runShellCommand(
+                "pm $installTypeString -t -g --user ${user.id()} ${file.path}"
+            )
+        )
+            .isEqualTo("Success\n")
+    }
+
+    private fun uninstallPackageAsUser(packageName: String, user: UserReference) =
+        assertThat(SystemUtil.runShellCommand("pm uninstall --user ${user.id()} $packageName"))
+            .isEqualTo("Success\n")
+
+    private fun uninstallPackageWithKeepData(packageName: String, user: UserReference) =
+        SystemUtil.runShellCommand("pm uninstall -k --user ${user.id()} $packageName")
+
+    private fun uninstallPackageSilently(packageName: String) =
+        SystemUtil.runShellCommand("pm uninstall $packageName")
+
+    private fun isAppInstalledForUser(packageName: String, user: UserReference) =
+        SystemUtil.runShellCommand("pm list packages --user ${user.id()} $packageName")
+            .split("\\r?\\n".toRegex())
+            .any { it == "package:$packageName" }
+
+    private fun setSystemProperty(name: String, value: String) =
+        assertThat(SystemUtil.runShellCommand("setprop $name $value"))
+            .isEmpty()
+}
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
index da8a7ab..d923ad7 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -66,7 +66,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.platform.test.annotations.AppModeFull;
 import android.util.PackageUtils;
 
@@ -79,7 +78,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -109,12 +107,12 @@
 @RunWith(Parameterized.class)
 @AppModeFull
 public class PackageManagerShellCommandTest {
-    private static final String TEST_APP_PACKAGE = "com.example.helloworld";
+    static final String TEST_APP_PACKAGE = "com.example.helloworld";
 
     private static final String CTS_PACKAGE_NAME = "android.content.cts";
 
     private static final String TEST_APK_PATH = "/data/local/tmp/cts/content/";
-    private static final String TEST_HW5 = "HelloWorld5.apk";
+    static final String TEST_HW5 = "HelloWorld5.apk";
     private static final String TEST_HW5_SPLIT0 = "HelloWorld5_hdpi-v4.apk";
     private static final String TEST_HW5_SPLIT1 = "HelloWorld5_mdpi-v4.apk";
     private static final String TEST_HW5_SPLIT2 = "HelloWorld5_xhdpi-v4.apk";
@@ -154,7 +152,7 @@
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 
-    private static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT = 3 * 1000;
+    static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT = 3 * 1000;
 
     @Rule
     public AbandonAllPackageSessionsRule mAbandonSessionsRule = new AbandonAllPackageSessionsRule();
@@ -1398,90 +1396,6 @@
         }
     }
 
-    @Ignore
-    @Test
-    public void testGetFirstInstallTime() throws Exception {
-        final int currentUser = getContext().getUserId();
-        final long startTimeMillisForCurrentUser = System.currentTimeMillis();
-        installPackage(TEST_HW5);
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, currentUser));
-        final long origFirstInstallTimeForCurrentUser = getFirstInstallTimeAsUser(
-                TEST_APP_PACKAGE, currentUser);
-        // Validate the timestamp
-        assertTrue(origFirstInstallTimeForCurrentUser > 0);
-        assertTrue(startTimeMillisForCurrentUser < origFirstInstallTimeForCurrentUser);
-        assertTrue(System.currentTimeMillis() > origFirstInstallTimeForCurrentUser);
-
-        // Install again with replace and the firstInstallTime should remain the same
-        installPackage(TEST_HW5);
-        long firstInstallTimeForCurrentUser = getFirstInstallTimeAsUser(
-                TEST_APP_PACKAGE, currentUser);
-        assertEquals(origFirstInstallTimeForCurrentUser, firstInstallTimeForCurrentUser);
-
-        // Start another user and install this test itself for that user
-        mSecondUser = createUser("Another User");
-        assertTrue(startUser(mSecondUser));
-        long startTimeMillisForSecondUser = System.currentTimeMillis();
-        installExistingPackageAsUser(getContext().getPackageName(), mSecondUser);
-        assertTrue(isAppInstalledForUser(getContext().getPackageName(), mSecondUser));
-        // Install test package with replace
-        installPackageAsUser(TEST_HW5, mSecondUser);
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-        firstInstallTimeForCurrentUser = getFirstInstallTimeAsUser(
-                TEST_APP_PACKAGE, currentUser);
-        // firstInstallTime should remain unchanged for the current user
-        assertEquals(origFirstInstallTimeForCurrentUser, firstInstallTimeForCurrentUser);
-
-        long firstInstallTimeForSecondUser = getFirstInstallTimeAsUser(
-                TEST_APP_PACKAGE, mSecondUser);
-        // firstInstallTime for the other user should be different
-        assertNotEquals(firstInstallTimeForCurrentUser, firstInstallTimeForSecondUser);
-        assertTrue(startTimeMillisForSecondUser < firstInstallTimeForSecondUser);
-        assertTrue(System.currentTimeMillis() > firstInstallTimeForSecondUser);
-
-        // Uninstall for the other user
-        uninstallPackageAsUser(TEST_APP_PACKAGE, mSecondUser);
-        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-        // Install test package as an existing package
-        startTimeMillisForSecondUser = System.currentTimeMillis();
-        installExistingPackageAsUser(TEST_APP_PACKAGE, mSecondUser);
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-
-        firstInstallTimeForCurrentUser = getFirstInstallTimeAsUser(
-                TEST_APP_PACKAGE, currentUser);
-        // firstInstallTime still remains unchanged for the current user
-        assertEquals(origFirstInstallTimeForCurrentUser, firstInstallTimeForCurrentUser);
-        firstInstallTimeForSecondUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, mSecondUser);
-        // firstInstallTime for the other user should be different
-        assertNotEquals(firstInstallTimeForCurrentUser, firstInstallTimeForSecondUser);
-        assertTrue(startTimeMillisForSecondUser < firstInstallTimeForSecondUser);
-        assertTrue(System.currentTimeMillis() > firstInstallTimeForSecondUser);
-
-        // Uninstall for all users
-        uninstallPackageSilently(TEST_APP_PACKAGE);
-        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, currentUser));
-        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-        // Reinstall for all users
-        installPackage(TEST_HW5);
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, currentUser));
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-        firstInstallTimeForCurrentUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, currentUser);
-        // First install time is now different because the package was fully uninstalled
-        assertNotEquals(origFirstInstallTimeForCurrentUser, firstInstallTimeForCurrentUser);
-        firstInstallTimeForSecondUser = getFirstInstallTimeAsUser(TEST_APP_PACKAGE, mSecondUser);
-        // Same firstInstallTime because package was installed for both users at the same time
-        assertEquals(firstInstallTimeForCurrentUser, firstInstallTimeForSecondUser);
-    }
-
-    private long getFirstInstallTimeAsUser(String packageName, int userId)
-            throws PackageManager.NameNotFoundException {
-        final Context contextAsUser = getContext().createContextAsUser(UserHandle.of(userId), 0);
-        final PackageManager packageManager = contextAsUser.getPackageManager();
-        final PackageInfo packageInfo = packageManager.getPackageInfo(packageName,
-                PackageManager.PackageInfoFlags.of(0));
-        return packageInfo.firstInstallTime;
-    }
-
     @Test
     public void testAppWithNoAppStorageUpdateSuccess() throws Exception {
         installPackage(TEST_HW_NO_APP_STORAGE);
@@ -1523,49 +1437,6 @@
         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
     }
 
-    @Ignore
-    @Test
-    public void testPackageFullyRemovedBroadcastAfterUninstall() throws IOException {
-        final int currentUser = getContext().getUserId();
-        // Start another user and install this test itself for that user
-        mSecondUser = createUser("Another User");
-        assertTrue(startUser(mSecondUser));
-        installExistingPackageAsUser(getContext().getPackageName(), mSecondUser);
-        installPackage(TEST_HW5);
-        assertTrue(isAppInstalledForUser(getContext().getPackageName(), currentUser));
-        assertTrue(isAppInstalledForUser(getContext().getPackageName(), mSecondUser));
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, currentUser));
-        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, mSecondUser));
-        final FullyRemovedBroadcastReceiver broadcastReceiverForCurrentUser =
-                new FullyRemovedBroadcastReceiver(TEST_APP_PACKAGE, currentUser);
-        final FullyRemovedBroadcastReceiver broadcastReceiverForSecondUser =
-                new FullyRemovedBroadcastReceiver(TEST_APP_PACKAGE, mSecondUser);
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
-        intentFilter.addDataScheme("package");
-        getContext().registerReceiver(
-                broadcastReceiverForCurrentUser, intentFilter, RECEIVER_EXPORTED);
-        getUiAutomation().adoptShellPermissionIdentity(
-                android.Manifest.permission.INTERACT_ACROSS_USERS,
-                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
-        try {
-            getContext().createContextAsUser(UserHandle.of(mSecondUser), 0).registerReceiver(
-                    broadcastReceiverForSecondUser, intentFilter, RECEIVER_EXPORTED);
-        } finally {
-            getUiAutomation().dropShellPermissionIdentity();
-        }
-        // Verify that uninstall with "keep data" doesn't send the broadcast
-        uninstallPackageWithKeepData(TEST_APP_PACKAGE, mSecondUser);
-        assertFalse(broadcastReceiverForSecondUser.isBroadcastReceived());
-        installExistingPackageAsUser(TEST_APP_PACKAGE, mSecondUser);
-        // Verify that uninstall on a specific user only sends the broadcast to the user
-        uninstallPackageAsUser(TEST_APP_PACKAGE, mSecondUser);
-        assertTrue(broadcastReceiverForSecondUser.isBroadcastReceived());
-        assertFalse(broadcastReceiverForCurrentUser.isBroadcastReceived());
-        uninstallPackageSilently(TEST_APP_PACKAGE);
-        assertTrue(broadcastReceiverForCurrentUser.isBroadcastReceived());
-    }
-
     @Test
     public void testQuerySdkSandboxPackageName() throws Exception {
         final PackageManager pm = getPackageManager();
@@ -1601,7 +1472,7 @@
         assertEquals(pm.getSdkSandboxPackageName(), names[0]);
     }
 
-    private static class FullyRemovedBroadcastReceiver extends BroadcastReceiver {
+    static class FullyRemovedBroadcastReceiver extends BroadcastReceiver {
         private final String mTargetPackage;
         private final int mTargetUserId;
         private final ConditionVariable mUserReceivedBroadcast;
@@ -1694,7 +1565,7 @@
         assertEquals("Success\n", executeShellCommand("pm install-commit " + sessionId));
     }
 
-    private boolean isAppInstalled(String packageName) throws IOException {
+    static boolean isAppInstalled(String packageName) throws IOException {
         final String commandResult = executeShellCommand("pm list packages");
         final int prefixLength = "package:".length();
         return Arrays.stream(commandResult.split("\\r?\\n")).anyMatch(
@@ -1702,14 +1573,6 @@
                         packageName));
     }
 
-    private boolean isAppInstalledForUser(String packageName, int userId) throws IOException {
-        final String commandResult = executeShellCommand(
-                String.format("pm list packages --user %d %s", userId, packageName)
-        );
-        return Arrays.stream(commandResult.split("\\r?\\n"))
-                .anyMatch(line -> line.equals("package:" + packageName));
-    }
-
     private boolean isSdkInstalled(String name, int versionMajor) throws IOException {
         final String sdkString = name + ":" + versionMajor;
         final String commandResult = executeShellCommand("pm list sdks");
@@ -1735,7 +1598,7 @@
         }
     }
 
-    private String getSplits(String packageName) throws IOException {
+    static String getSplits(String packageName) throws IOException {
         final String commandResult = executeShellCommand("pm dump " + packageName);
         final String prefix = "    splits=[";
         final int prefixLength = prefix.length();
@@ -1748,7 +1611,7 @@
         return splits.substring(prefixLength, splits.length() - 1);
     }
 
-    private static String createApkPath(String baseName) {
+    static String createApkPath(String baseName) {
         return TEST_APK_PATH + baseName;
     }
 
@@ -1766,20 +1629,6 @@
         assertTrue(result, result.startsWith(expectedResultStartsWith));
     }
 
-    /* Install a package for a new user; this would replace the old package */
-    private void installPackageAsUser(String baseName, int userId) throws IOException {
-        File file = new File(createApkPath(baseName));
-        assertEquals("Success\n", executeShellCommand(
-                "pm " + mInstall + " -t -g --user " + userId + " " + file.getPath()));
-    }
-
-    /* Install an existing package for a new user */
-    private void installExistingPackageAsUser(String packageName, int userId) throws IOException {
-        String result = executeShellCommand(
-                String.format("pm install-existing --user %d %s", userId, packageName));
-        assertEquals("Package " + packageName + " installed for user: " + userId + "\n", result);
-    }
-
     private void updatePackage(String packageName, String baseName) throws IOException {
         File file = new File(createApkPath(baseName));
         assertEquals("Success\n", executeShellCommand(
@@ -1866,15 +1715,6 @@
         return executeShellCommand("pm uninstall " + packageName);
     }
 
-    /* Uninstall for one user */
-    private void uninstallPackageAsUser(String packageName, int userId) throws IOException {
-        executeShellCommand(String.format("pm uninstall --user %d %s", userId, packageName));
-    }
-
-    private void uninstallPackageWithKeepData(String packageName, int userId) throws IOException {
-        executeShellCommand(String.format("pm uninstall -k --user %d %s", userId, packageName));
-    }
-
     private void uninstallSplits(String packageName, String[] splitNames) throws IOException {
         for (String splitName : splitNames) {
             assertEquals("Success\n",
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index d3a045f..bff425b 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -41,6 +41,8 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.google.common.truth.Expect;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -109,6 +111,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.xmlpull.v1.XmlPullParser;
@@ -231,6 +234,8 @@
 
     private final ServiceTestRule mServiceTestRule = new ServiceTestRule();
 
+    @Rule public final Expect expect = Expect.create();
+
     @Before
     public void setup() throws Exception {
         mContext = InstrumentationRegistry.getContext();
@@ -1738,20 +1743,26 @@
      */
     @Test
     public void testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates() {
+        final Set<String> packageNames = new HashSet<>();
         runTestWithFlags(PACKAGE_INFO_MATCH_FLAGS,
-                this::testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates);
+                flags -> testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates(flags,
+                        packageNames));
     }
 
-    public void testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates(int flags) {
+    public void testGetInstalledPackages_WithFactoryFlag_ContainsNoDuplicates(int flags,
+            Set<String> packageNames) {
         List<PackageInfo> packageInfos =
                 mPackageManager.getInstalledPackages(
                         PackageManager.PackageInfoFlags.of(flags | MATCH_FACTORY_ONLY));
-        Set<String> foundPackages = new HashSet<>();
+
+        final Set<String> localPackageNames = new HashSet<>();
         for (PackageInfo pi : packageInfos) {
-            if (foundPackages.contains(pi.packageName)) {
-                throw new AssertionError(pi.packageName + " is listed at least twice.");
+            final String packageName = pi.packageName;
+            // Duplicate: already in local.
+            // Dedup error messages: not in global.
+            if (!localPackageNames.add(pi.packageName) && packageNames.add(packageName)) {
+                expect.withMessage("Duplicate package " + packageName + " detected").fail();
             }
-            foundPackages.add(pi.packageName);
         }
     }
 
diff --git a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
index 1c2cbad..272e062 100644
--- a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
@@ -290,7 +290,7 @@
 
     private static class RemoteTest implements AutoCloseable {
         private static final int SPIN_SLEEP_MS = 500;
-        private static final long RESPONSE_TIMEOUT_MS = 60 * 1000;
+        private static final long RESPONSE_TIMEOUT_MS = 120 * 1000;
 
         private final ShellInstallSession mSession;
         private final String mTestName;
diff --git a/tests/tests/display/src/android/display/cts/BrightnessTest.java b/tests/tests/display/src/android/display/cts/BrightnessTest.java
index 95c7b5e..73d900f 100644
--- a/tests/tests/display/src/android/display/cts/BrightnessTest.java
+++ b/tests/tests/display/src/android/display/cts/BrightnessTest.java
@@ -66,12 +66,14 @@
     private DisplayManager mDisplayManager;
     private PowerManager.WakeLock mWakeLock;
     private Context mContext;
+    private PackageManager mPackageManager;
 
     @Before
     public void setUp() {
         mContext = InstrumentationRegistry.getContext();
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         PowerManager pm = mContext.getSystemService(PowerManager.class);
+        mPackageManager = mContext.getPackageManager();
 
         mWakeLock = pm.newWakeLock(
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
@@ -91,6 +93,9 @@
 
     @Test
     public void testBrightnessSliderTracking() throws InterruptedException {
+        // Only run if we have a valid ambient light sensor.
+        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT));
+
         // Don't run as there is no app that has permission to access slider usage.
         assumeTrue(
                 numberOfSystemAppsWithPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) > 0);
@@ -174,6 +179,9 @@
 
     @Test
     public void testNoColorSampleData() throws InterruptedException {
+        // Only run if we have a valid ambient light sensor.
+        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT));
+
           // Don't run as there is no app that has permission to access slider usage.
         assumeTrue(
                 numberOfSystemAppsWithPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) > 0);
@@ -330,6 +338,9 @@
 
     @Test
     public void testSliderEventsReflectCurves() throws InterruptedException {
+        // Only run if we have a valid ambient light sensor.
+        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT));
+
         // Don't run as there is no app that has permission to access slider usage.
         assumeTrue(
                 numberOfSystemAppsWithPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) > 0);
@@ -426,6 +437,9 @@
 
     @Test
     public void testSetAndGetPerDisplay() throws InterruptedException{
+        // Only run if we have a valid ambient light sensor.
+        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT));
+
         assumeTrue(numberOfSystemAppsWithPermission(
                 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) > 0);
 
diff --git a/tests/tests/dreams/AndroidTest.xml b/tests/tests/dreams/AndroidTest.xml
index cc4c9b5..18f7891 100644
--- a/tests/tests/dreams/AndroidTest.xml
+++ b/tests/tests/dreams/AndroidTest.xml
@@ -19,6 +19,7 @@
     <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="parameter" value="all_foldable_states" />
     <option name="not-shardable" value="true" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
diff --git a/tests/tests/gameservice/AndroidManifest.xml b/tests/tests/gameservice/AndroidManifest.xml
index a81e64d..936184b 100644
--- a/tests/tests/gameservice/AndroidManifest.xml
+++ b/tests/tests/gameservice/AndroidManifest.xml
@@ -20,6 +20,9 @@
 
     <uses-permission android:name="android.permission.MANAGE_GAME_ACTIVITY"/>
     <uses-permission android:name="android.service.games.cts.TEST_START_ACTIVITY"/>
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.MANAGE_MEDIA"/>
 
     <application android:label="CtsGameServiceTestApp">
 
@@ -47,6 +50,7 @@
         </service>
 
         <uses-library android:name="android.test.runner" />
+        <activity android:name="android.service.games.testing.GetResultActivity"/>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
index 6d458ae..d95cabe 100644
--- a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
+++ b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
@@ -20,30 +20,44 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.app.Activity;
 import android.app.GameManager;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.ImageDecoder;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.provider.MediaStore;
 import android.service.games.testing.ActivityResult;
+import android.service.games.testing.GetResultActivity;
 import android.service.games.testing.IGameServiceTestService;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
 import android.support.test.uiautomator.Until;
+import android.util.Log;
 import android.util.Size;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 
-import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.PollingCheck;
@@ -57,7 +71,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameter;
 
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
@@ -68,6 +86,8 @@
  */
 @RunWith(AndroidJUnit4.class)
 public final class GameServiceTest {
+    static final String TAG = "GameServiceTest";
+
     private static final String GAME_PACKAGE_NAME = "android.service.games.cts.game";
     private static final String FALSE_POSITIVE_GAME_PACKAGE_NAME =
             "android.service.games.cts.falsepositive";
@@ -83,7 +103,11 @@
     private static final String TOUCH_VERIFIER_PACKAGE_NAME =
             "android.service.games.cts.touchverifier";
 
+    @Parameter(0)
+    public String mVolumeName;
+
     private ServiceConnection mServiceConnection;
+    private ContentResolver mContentResolver;
 
     @Before
     public void setUp() throws Exception {
@@ -106,9 +130,11 @@
 
         GameManager gameManager =
                 getInstrumentation().getContext().getSystemService(GameManager.class);
+
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(gameManager,
                 manager -> manager.setGameServiceProvider(
                         getInstrumentation().getContext().getPackageName()));
+        mContentResolver = getInstrumentation().getContext().getContentResolver();
     }
 
     @After
@@ -378,7 +404,7 @@
     }
 
     @Test
-    public void takeScreenshot_expectedBitmapReturned() throws Exception {
+    public void takeScreenshot_expectedScreenshotSaved() throws Exception {
         assumeGameServiceFeaturePresent();
 
         launchAndWaitForPackage(TAKE_SCREENSHOT_VERIFIER_PACKAGE_NAME);
@@ -386,68 +412,131 @@
         // Make sure that the overlay is shown so that assertions can be made to check that
         // the overlay is excluded from the game screenshot.
         getTestService().showOverlayForFocusedGameSession();
-        Rect overlayBounds = waitForTouchableOverlayBounds();
+        final Rect overlayBounds = waitForTouchableOverlayBounds();
 
-        Bitmap gameScreenshot = getTestService().getBitmapScreenshotForFocusedGameSession();
+        long startTimeSecs = Instant.now().getEpochSecond();
+        final boolean ret = getTestService().takeScreenshotForFocusedGameSession();
 
-        // Make sure a screenshot was taken and has the same dimensions as the device screen.
-        assertNotNull(gameScreenshot);
+        // Make sure a screenshot was taken, saved in media, and has the same dimensions as the
+        // device screen.
+        assertTrue(ret);
+        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+        final List<Uri> list = new ArrayList<>();
+        try (Cursor cursor = mContentResolver.query(contentUri,
+                new String[]{MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME,
+                        MediaStore.MediaColumns.DATE_ADDED}, null, null,
+                MediaStore.MediaColumns.DATE_ADDED + " DESC")) {
+            while (cursor.moveToNext()) {
+                final long addedTimeSecs = cursor.getLong(2);
+                // try to find the latest screenshot file created within 5s
+                if (addedTimeSecs >= startTimeSecs && addedTimeSecs - startTimeSecs < 5) {
+                    final long id = cursor.getLong(0);
+                    final Uri screenshotUri = ContentUris.withAppendedId(contentUri, id);
+                    final String name = cursor.getString(1);
+                    Log.d(TAG, "Found screenshot with name " + name);
+                    list.add(screenshotUri);
+                    final ImageDecoder.Source source = ImageDecoder.createSource(mContentResolver,
+                            screenshotUri);
+                    // convert the hardware bitmap to a mutable 4-byte bitmap to get/compare pixel
+                    final Bitmap gameScreenshot = ImageDecoder.decodeBitmap(source).copy(
+                            Bitmap.Config.ARGB_8888, true);
 
-        Size screenSize = getScreenSize();
-        assertThat(gameScreenshot.getWidth()).isEqualTo(screenSize.getWidth());
-        assertThat(gameScreenshot.getHeight()).isEqualTo(screenSize.getHeight());
+                    final Size screenSize = getScreenSize();
+                    assertThat(gameScreenshot.getWidth()).isEqualTo(screenSize.getWidth());
+                    assertThat(gameScreenshot.getHeight()).isEqualTo(screenSize.getHeight());
 
-        // The test game is always fullscreen red. It is too expensive to verify that the entire
-        // bitmap is red, so spot check certain areas.
+                    // The test game is always fullscreen red. It is too expensive to verify that
+                    // the entire bitmap is red, so spot check certain areas.
 
-        // 1. Make sure that the overlay is excluded from the screenshot by checking pixels within
-        // the overlay bounds:
+                    // 1. Make sure that the overlay is excluded from the screenshot by checking
+                    // pixels within the overlay bounds:
 
-        // top-left of overlay bounds:
-        assertThat(
-                gameScreenshot.getPixel(overlayBounds.left + 1, overlayBounds.top + 1)).isEqualTo(
-                Color.RED);
-        // bottom-left corner of overlay bounds:
-        assertThat(gameScreenshot.getPixel(overlayBounds.left + 1,
-                overlayBounds.bottom - 1)).isEqualTo(Color.RED);
-        // top-right corner of overlay bounds:
-        assertThat(
-                gameScreenshot.getPixel(overlayBounds.right - 1, overlayBounds.top + 1)).isEqualTo(
-                Color.RED);
-        // bottom-right corner of overlay bounds:
-        assertThat(gameScreenshot.getPixel(overlayBounds.right - 1,
-                overlayBounds.bottom - 1)).isEqualTo(Color.RED);
-        // middle corner of overlay bounds:
-        assertThat(gameScreenshot.getPixel((overlayBounds.left + overlayBounds.right) / 2,
-                (overlayBounds.top + overlayBounds.bottom) / 2)).isEqualTo(Color.RED);
+                    // top-left of overlay bounds:
+                    assertThat(
+                            gameScreenshot.getPixel(overlayBounds.left + 1,
+                                    overlayBounds.top + 1)).isEqualTo(
+                            Color.RED);
+                    // bottom-left corner of overlay bounds:
+                    assertThat(gameScreenshot.getPixel(overlayBounds.left + 1,
+                            overlayBounds.bottom - 1)).isEqualTo(Color.RED);
+                    // top-right corner of overlay bounds:
+                    assertThat(
+                            gameScreenshot.getPixel(overlayBounds.right - 1,
+                                    overlayBounds.top + 1)).isEqualTo(
+                            Color.RED);
+                    // bottom-right corner of overlay bounds:
+                    assertThat(gameScreenshot.getPixel(overlayBounds.right - 1,
+                            overlayBounds.bottom - 1)).isEqualTo(Color.RED);
+                    // middle corner of overlay bounds:
+                    assertThat(
+                            gameScreenshot.getPixel((overlayBounds.left + overlayBounds.right) / 2,
+                                    (overlayBounds.top + overlayBounds.bottom) / 2)).isEqualTo(
+                            Color.RED);
 
-        // 2. Also check some pixels between the edge of the screen and the overlay bounds:
+                    // 2. Also check some pixels between the edge of the screen and the overlay
+                    // bounds:
 
-        // above and to the left of the overlay
-        assertThat(
-                gameScreenshot.getPixel(overlayBounds.left / 2, overlayBounds.top / 2)).isEqualTo(
-                Color.RED);
-        // below and to the left of the overlay
-        assertThat(gameScreenshot.getPixel(overlayBounds.left / 2,
-                (overlayBounds.bottom + gameScreenshot.getHeight()) / 2)).isEqualTo(Color.RED);
-        // above and to the right of the overlay
-        assertThat(gameScreenshot.getPixel((overlayBounds.left + gameScreenshot.getWidth()) / 2,
-                overlayBounds.top / 2)).isEqualTo(Color.RED);
-        // below and to the right of the overlay
-        assertThat(gameScreenshot.getPixel((overlayBounds.left + gameScreenshot.getWidth()) / 2,
-                (overlayBounds.bottom + gameScreenshot.getHeight()) / 2)).isEqualTo(Color.RED);
+                    // above and to the left of the overlay
+                    assertThat(
+                            gameScreenshot.getPixel(overlayBounds.left / 2,
+                                    overlayBounds.top / 2)).isEqualTo(
+                            Color.RED);
+                    // below and to the left of the overlay
+                    assertThat(gameScreenshot.getPixel(overlayBounds.left / 2,
+                            (overlayBounds.bottom + gameScreenshot.getHeight()) / 2)).isEqualTo(
+                            Color.RED);
+                    // above and to the right of the overlay
+                    assertThat(gameScreenshot.getPixel(
+                            (overlayBounds.left + gameScreenshot.getWidth()) / 2,
+                            overlayBounds.top / 2)).isEqualTo(Color.RED);
+                    // below and to the right of the overlay
+                    assertThat(gameScreenshot.getPixel(
+                            (overlayBounds.left + gameScreenshot.getWidth()) / 2,
+                            (overlayBounds.bottom + gameScreenshot.getHeight()) / 2)).isEqualTo(
+                            Color.RED);
 
-        // 3. Finally check some pixels at the corners of the screen:
+                    // 3. Finally check some pixels at the corners of the screen:
 
-        // top-left corner of screen
-        assertThat(gameScreenshot.getPixel(0, 0)).isEqualTo(Color.RED);
-        // bottom-left corner of screen
-        assertThat(gameScreenshot.getPixel(0, gameScreenshot.getHeight() - 1)).isEqualTo(Color.RED);
-        // top-right corner of screen
-        assertThat(gameScreenshot.getPixel(gameScreenshot.getWidth() - 1, 0)).isEqualTo(Color.RED);
-        // bottom-right corner of screen
-        assertThat(gameScreenshot.getPixel(gameScreenshot.getWidth() - 1,
-                gameScreenshot.getHeight() - 1)).isEqualTo(Color.RED);
+                    // top-left corner of screen
+                    assertThat(gameScreenshot.getPixel(0, 0)).isEqualTo(Color.RED);
+                    // bottom-left corner of screen
+                    assertThat(
+                            gameScreenshot.getPixel(0, gameScreenshot.getHeight() - 1)).isEqualTo(
+                            Color.RED);
+                    // top-right corner of screen
+                    assertThat(gameScreenshot.getPixel(gameScreenshot.getWidth() - 1, 0)).isEqualTo(
+                            Color.RED);
+                    // bottom-right corner of screen
+                    assertThat(gameScreenshot.getPixel(gameScreenshot.getWidth() - 1,
+                            gameScreenshot.getHeight() - 1)).isEqualTo(Color.RED);
+                    final PendingIntent pi = MediaStore.createDeleteRequest(mContentResolver,
+                            ImmutableList.of(screenshotUri));
+                    final GetResultActivity.Result result = startIntentWithGrant(pi);
+                    assertEquals(Activity.RESULT_OK, result.resultCode);
+                }
+            }
+        }
+        assertThat(list.size()).isGreaterThan(0);
+    }
+
+    private GetResultActivity.Result startIntentWithGrant(PendingIntent pi) throws Exception {
+        final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+        final Intent intent = new Intent(inst.getContext(), GetResultActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        final UiDevice device = UiDevice.getInstance(inst);
+        final GetResultActivity activity = (GetResultActivity) inst.startActivitySync(intent);
+        inst.waitForIdleSync();
+        activity.mResult.clear();
+        device.waitForIdle();
+        activity.startIntentSenderForResult(pi.getIntentSender(), 42, null, 0, 0, 0);
+        device.waitForIdle();
+        final UiSelector grant = new UiSelector().textMatches("(?i)Allow");
+        final boolean grantExists = new UiObject(grant).waitForExists(5000);
+        if (grantExists) {
+            device.findObject(grant).click();
+        }
+        return activity.getResult();
     }
 
     private IGameServiceTestService getTestService() {
diff --git a/tests/tests/gameservice/src/android/service/games/GameServiceTestService.java b/tests/tests/gameservice/src/android/service/games/GameServiceTestService.java
index bd0198f..31a4efd 100644
--- a/tests/tests/gameservice/src/android/service/games/GameServiceTestService.java
+++ b/tests/tests/gameservice/src/android/service/games/GameServiceTestService.java
@@ -20,7 +20,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -154,37 +153,36 @@
         }
 
         @Override
-        public Bitmap getBitmapScreenshotForFocusedGameSession() {
+        public boolean takeScreenshotForFocusedGameSession() {
+            boolean result = false;
             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
-            if (focusedGameSession == null) {
-                return null;
+            if (focusedGameSession != null) {
+                CountDownLatch countDownLatch = new CountDownLatch(1);
+                final boolean[] ret = new boolean[1];
+                ScreenshotCallback callback =
+                        new ScreenshotCallback() {
+                            @Override
+                            public void onFailure(int statusCode) {
+                                ret[0] = false;
+                                countDownLatch.countDown();
+                            }
+
+                            @Override
+                            public void onSuccess() {
+                                ret[0] = true;
+                                countDownLatch.countDown();
+                            }
+                        };
+                focusedGameSession.takeScreenshot(Runnable::run, callback);
+                try {
+                    countDownLatch.await(
+                            SCREENSHOT_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    return false;
+                }
+                result = ret[0];
             }
-
-            CountDownLatch countDownLatch = new CountDownLatch(1);
-            Bitmap[] ret = new Bitmap[1];
-            ScreenshotCallback callback =
-                    new ScreenshotCallback() {
-                        @Override
-                        public void onFailure(int statusCode) {
-                            countDownLatch.countDown();
-                        }
-
-                        @Override
-                        public void onSuccess(Bitmap bitmap) {
-                            ret[0] = bitmap;
-                            countDownLatch.countDown();
-                        }
-                    };
-            focusedGameSession.takeScreenshot(Runnable::run, callback);
-
-            try {
-                countDownLatch.await(
-                        SCREENSHOT_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                return null;
-            }
-
-            return ret[0];
+            return result;
         }
 
         public OnSystemBarVisibilityChangedInfo getOnSystemBarVisibilityChangedInfo() {
diff --git a/tests/tests/gameservice/src/android/service/games/testing/GetResultActivity.java b/tests/tests/gameservice/src/android/service/games/testing/GetResultActivity.java
new file mode 100644
index 0000000..87f42dd
--- /dev/null
+++ b/tests/tests/gameservice/src/android/service/games/testing/GetResultActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.games.testing;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class GetResultActivity extends Activity {
+    public static class Result {
+        public final int requestCode;
+        public final int resultCode;
+        public final Intent data;
+
+        public Result(int requestCode, int resultCode, Intent data) {
+            this.requestCode = requestCode;
+            this.resultCode = resultCode;
+            this.data = data;
+        }
+    }
+    public LinkedBlockingQueue<Result> mResult = new LinkedBlockingQueue<>();
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mResult.offer(new Result(requestCode, resultCode, data));
+        finish();
+    }
+
+    public Result getResult() {
+        final Result result;
+        try {
+            result = mResult.poll(20, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        if (result == null) {
+            throw new IllegalStateException("Activity didn't receive a Result in 20 seconds");
+        }
+        return result;
+    }
+}
diff --git a/tests/tests/gameservice/src/android/service/games/testing/IGameServiceTestService.aidl b/tests/tests/gameservice/src/android/service/games/testing/IGameServiceTestService.aidl
index cd227bb..90ed0fe 100644
--- a/tests/tests/gameservice/src/android/service/games/testing/IGameServiceTestService.aidl
+++ b/tests/tests/gameservice/src/android/service/games/testing/IGameServiceTestService.aidl
@@ -16,7 +16,6 @@
 package android.service.games.testing;
 
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.service.games.testing.ActivityResult;
@@ -43,7 +42,7 @@
 
     void showOverlayForFocusedGameSession();
 
-    Bitmap getBitmapScreenshotForFocusedGameSession();
+    boolean takeScreenshotForFocusedGameSession();
 
     OnSystemBarVisibilityChangedInfo getOnSystemBarVisibilityChangedInfo();
 
diff --git a/tests/tests/graphics/src/android/graphics/text/cts/MeasuredTextTest.java b/tests/tests/graphics/src/android/graphics/text/cts/MeasuredTextTest.java
index ec4bcfb..089ce23 100644
--- a/tests/tests/graphics/src/android/graphics/text/cts/MeasuredTextTest.java
+++ b/tests/tests/graphics/src/android/graphics/text/cts/MeasuredTextTest.java
@@ -63,9 +63,9 @@
         new MeasuredText.Builder(text.toCharArray())
                 .appendStyleRun(sPaint, text.length(), false /* isRtl */).build();
 
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        config.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
         new MeasuredText.Builder(text.toCharArray())
                 .appendStyleRun(sPaint, config, text.length(), false /* isRtl */).build();
     }
diff --git a/tests/tests/hardware/OWNERS b/tests/tests/hardware/OWNERS
index 8001641..21b257e 100644
--- a/tests/tests/hardware/OWNERS
+++ b/tests/tests/hardware/OWNERS
@@ -8,4 +8,4 @@
 # Trust that people only touch their own resources.
 per-file *.xml=*
 # Only input tests use JSON so far
-per-file *.json=svv@google.com
+per-file *.json=file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/tests/tests/hardware/src/android/hardware/input/OWNERS b/tests/tests/hardware/src/android/hardware/input/OWNERS
index b0a2050..c88bfe9 100644
--- a/tests/tests/hardware/src/android/hardware/input/OWNERS
+++ b/tests/tests/hardware/src/android/hardware/input/OWNERS
@@ -1,4 +1 @@
-# Bug component:136048
-lzye@google.com
-michaelwr@google.com
-svv@google.com
+include platform/frameworks/base:/INPUT_OWNERS
diff --git a/tests/tests/keystore/Android.bp b/tests/tests/keystore/Android.bp
index 931f04e..8b18756 100644
--- a/tests/tests/keystore/Android.bp
+++ b/tests/tests/keystore/Android.bp
@@ -117,3 +117,25 @@
     // sdk_version: "test_current",
     platform_apis: true,
 }
+
+android_test {
+    name: "CtsKeystoreWycheproofTestCases",
+    defaults: ["cts_defaults"],
+    manifest: "CtsKeystoreWycheproofTestManifest.xml",
+    test_config: "CtsKeystoreWycheproofTestConfig.xml",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+    static_libs: [
+        "cts-core-test-runner-axt",
+        "wycheproof-keystore",
+    ],
+    // sdk_version: "test_current",
+    platform_apis: true,
+}
diff --git a/tests/tests/keystore/CtsKeystoreWycheproofTestConfig.xml b/tests/tests/keystore/CtsKeystoreWycheproofTestConfig.xml
new file mode 100644
index 0000000..0b09028
--- /dev/null
+++ b/tests/tests/keystore/CtsKeystoreWycheproofTestConfig.xml
@@ -0,0 +1,33 @@
+<?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 Keystore wycheproof tests">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="security" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsKeystoreWycheproofTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.keystore.cts.wycheproof" />
+        <option name="runtime-hint" value="17m" />
+        <option name="test-timeout" value="34m" />
+        <option name="hidden-api-checks" value="false" />
+        <option name="isolated-storage" value="false" />
+    </test>
+</configuration>
diff --git a/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
new file mode 100644
index 0000000..9ef7249
--- /dev/null
+++ b/tests/tests/keystore/CtsKeystoreWycheproofTestManifest.xml
@@ -0,0 +1,33 @@
+<?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.keystore.cts.wycheproof">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.keystore.cts.wycheproof"
+                     android:label="CTS tests of android.keystore.cts.wycheproof">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java b/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
index 7feecd1..30bd40b 100644
--- a/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
+++ b/tests/tests/keystore/src/android/keystore/cts/Curve25519Test.java
@@ -37,6 +37,7 @@
 import java.security.NoSuchProviderException;
 import java.security.ProviderException;
 import java.security.spec.ECGenParameterSpec;
+import java.security.spec.NamedParameterSpec;
 
 @RunWith(AndroidJUnit4.class)
 public class Curve25519Test {
@@ -119,4 +120,34 @@
 
         assertThrows(InvalidAlgorithmParameterException.class, () -> kpg.initialize(keySpec));
     }
+
+    @Test
+    public void x25519CannotCreateKeyUsingKPGWithNamedParameterSpec()
+            throws NoSuchAlgorithmException, NoSuchProviderException,
+            InvalidAlgorithmParameterException {
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH", "AndroidKeyStore");
+
+        NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
+        try {
+            kpg.initialize(paramSpec);
+            fail("Should not be able to generate keys using NamedParameterSpec");
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage()).contains("cannot be initialized using NamedParameterSpec");
+        }
+    }
+
+    @Test
+    public void ed25519CannotCreateKeyUsingKPGWithNamedParameterSpec()
+            throws NoSuchAlgorithmException, NoSuchProviderException,
+            InvalidAlgorithmParameterException {
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH", "AndroidKeyStore");
+
+        NamedParameterSpec paramSpec = new NamedParameterSpec("Ed25519");
+        try {
+            kpg.initialize(paramSpec);
+            fail("Should not be able to generate keys using NamedParameterSpec");
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage()).contains("cannot be initialized using NamedParameterSpec");
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index d182cfc..d5f919a 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -80,6 +80,8 @@
 import androidx.test.filters.RequiresDevice;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.CddTest;
+
 import com.google.common.collect.ImmutableSet;
 
 import org.bouncycastle.asn1.x500.X500Name;
@@ -726,6 +728,7 @@
         testDeviceIdAttestationFailure(AttestationUtils.ID_TYPE_MEID, "Unable to retrieve MEID");
     }
 
+    @CddTest(requirement="9.11.4")
     @Test
     public void testMandatoryDeviceidAttestation() {
         // ID attestation is only mandatory on devices that have shipped with T and
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
index 98cb2c3..8c6759d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyFactoryTest.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.fail;
 
 import android.content.Context;
-import android.keystore.cts.util.TestUtils;
 import android.keystore.cts.R;
+import android.keystore.cts.util.TestUtils;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyInfo;
 import android.security.keystore.KeyProperties;
@@ -32,6 +32,9 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.InputStream;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -41,6 +44,8 @@
 import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
 import java.security.Provider;
+import java.security.Provider.Service;
+import java.security.PublicKey;
 import java.security.Security;
 import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAPublicKey;
@@ -52,8 +57,6 @@
 import java.security.spec.RSAPrivateKeySpec;
 import java.security.spec.RSAPublicKeySpec;
 import java.security.spec.X509EncodedKeySpec;
-import java.security.Provider.Service;
-import java.security.PublicKey;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -65,9 +68,6 @@
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @RunWith(AndroidJUnit4.class)
 public class KeyFactoryTest {
     private static final String EXPECTED_PROVIDER_NAME = TestUtils.EXPECTED_PROVIDER_NAME;
@@ -94,6 +94,9 @@
         Set<String> actualAlgsLowerCase = new HashSet<String>();
         Set<String> expectedAlgsLowerCase = new HashSet<String>(
                 Arrays.asList(TestUtils.toLowerCase(EXPECTED_ALGORITHMS)));
+        // XDH is also a supported algorithm, but not available for other tests as the keys
+        // generated with it have more limited set of uses.
+        expectedAlgsLowerCase.add("xdh");
         for (Service service : services) {
             if ("KeyFactory".equalsIgnoreCase(service.getType())) {
                 String algLowerCase = service.getAlgorithm().toLowerCase(Locale.US);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
index 5820089..ff1944e 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
@@ -16,6 +16,7 @@
 
 package android.media.codec.cts;
 
+import android.content.Context;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
@@ -23,16 +24,31 @@
 import android.media.cts.InputSurface;
 import android.media.cts.OutputSurface;
 import android.opengl.GLES20;
-import android.test.AndroidTestCase;
 import android.util.Log;
 
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+import static org.junit.Assert.fail;
 
 /**
  * This test has three steps:
@@ -48,15 +64,14 @@
  * no longer exercising the code in the way we expect it to be used (and the code
  * gets a bit unwieldy).
  */
-public class DecodeEditEncodeTest extends AndroidTestCase {
+@RunWith(Parameterized.class)
+public class DecodeEditEncodeTest {
     private static final String TAG = "DecodeEditEncode";
     private static final boolean WORK_AROUND_BUGS = false;  // avoid fatal codec bugs
     private static final boolean VERBOSE = false;           // lots of logging
     private static final boolean DEBUG_SAVE_FILE = false;   // save copy of encoded movie
 
     // parameters for the encoder
-                                                            // H.264 Advanced Video Coding
-    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
     private static final int FRAME_RATE = 15;               // 15fps
     private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
     private static final String KEY_ALLOW_FRAME_DROP = "allow-frame-drop";
@@ -93,26 +108,73 @@
             "  gl_FragColor = texture2D(sTexture, vTextureCoord).rbga;\n" +
             "}\n";
 
+    // component names
+    private final String mEncoderName;
+    private final String mDecoderName;
+    // mime
+    private final String mMediaType;
     // size of a frame, in pixels
-    private int mWidth = -1;
-    private int mHeight = -1;
+    private final int mWidth;
+    private final int mHeight;
     // bit rate, in bits per second
-    private int mBitRate = -1;
+    private final int mBitRate;
 
     // largest color component delta seen (i.e. actual vs. expected)
     private int mLargestColorDelta;
 
+    static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+        final List<Object[]> argsList = new ArrayList<>();
+        int argLength = exhaustiveArgsList.get(0).length;
+        for (Object[] arg : exhaustiveArgsList) {
+            String[] encoderNamesForMime = MediaUtils.getEncoderNamesForMime((String)arg[0]);
+            String[] decoderNamesForMime = MediaUtils.getDecoderNamesForMime((String)arg[0]);
+            Object[] testArgs = new Object[argLength + 2];
+            // Add encoder name and decoder name as first two arguments and then
+            // copy arguments passed
+            testArgs[0] = encoderNamesForMime[0];
+            testArgs[1] = decoderNamesForMime[0];
+            System.arraycopy(arg, 0, testArgs, 2, argLength);
+            argsList.add(testArgs);
+        }
+        return argsList;
+    }
 
-    public void testVideoEditQCIF() throws Throwable {
-        setParameters(176, 144, 1100000);
-        VideoEditWrapper.runTest(this);
+    @Before
+    public void shouldSkip() {
+        MediaFormat format = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+        assumeTrue(MediaUtils.supports(mEncoderName, format));
+        assumeTrue(MediaUtils.supports(mDecoderName, format));
     }
-    public void testVideoEditQVGA() throws Throwable {
-        setParameters(320, 240, 2000000);
-        VideoEditWrapper.runTest(this);
+
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4})")
+    public static Collection<Object[]> input() {
+        final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+                // mediaType, width, height, bitrate
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 176, 144, 1000000},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 320, 240, 2000000},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 6000000},
+        });
+        return prepareParamList(exhaustiveArgsList);
     }
-    public void testVideoEdit720p() throws Throwable {
-        setParameters(1280, 720, 6000000);
+
+    public DecodeEditEncodeTest(String encoder, String decoder, String mimeType, int width,
+            int height, int bitRate) {
+        if ((width % 16) != 0 || (height % 16) != 0) {
+            Log.w(TAG, "WARNING: width or height not multiple of 16");
+        }
+        mEncoderName = encoder;
+        mDecoderName = decoder;
+        mMediaType = mimeType;
+        mWidth = width;
+        mHeight = height;
+        mBitRate = bitRate;
+    }
+
+    @Test
+    public void testVideoEdit() throws Throwable {
         VideoEditWrapper.runTest(this);
     }
 
@@ -151,18 +213,6 @@
     }
 
     /**
-     * Sets the desired frame size and bit rate.
-     */
-    private void setParameters(int width, int height, int bitRate) {
-        if ((width % 16) != 0 || (height % 16) != 0) {
-            Log.w(TAG, "WARNING: width or height not multiple of 16");
-        }
-        mWidth = width;
-        mHeight = height;
-        mBitRate = bitRate;
-    }
-
-    /**
      * Tests editing of a video file with GL.
      */
     private void videoEditTest()
@@ -177,7 +227,8 @@
         if (DEBUG_SAVE_FILE) {
             // Save a copy to a file.  We call it ".mp4", but it's actually just an elementary
             // stream, so not all video players will know what to do with it.
-            String dirName = getContext().getFilesDir().getAbsolutePath();
+            Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+            String dirName = context.getFilesDir().getAbsolutePath();
             String fileName = "vedit1_" + mWidth + "x" + mHeight + ".mp4";
             sourceChunks.saveToFile(new File(dirName, fileName));
         }
@@ -185,7 +236,8 @@
         VideoChunks destChunks = editVideoFile(sourceChunks);
 
         if (DEBUG_SAVE_FILE) {
-            String dirName = getContext().getFilesDir().getAbsolutePath();
+            Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+            String dirName = context.getFilesDir().getAbsolutePath();
             String fileName = "vedit2_" + mWidth + "x" + mHeight + ".mp4";
             destChunks.saveToFile(new File(dirName, fileName));
         }
@@ -208,15 +260,7 @@
         try {
             // We avoid the device-specific limitations on width and height by using values that
             // are multiples of 16, which all tested devices seem to be able to handle.
-            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
-
-            String codecName = selectCodec(format);
-            if (codecName == null) {
-                // Don't fail CTS if they don't have an AVC codec (not here, anyway).
-                Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
-                return false;
-            }
-            if (VERBOSE) Log.d(TAG, "found codec: " + codecName);
+            MediaFormat format = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
 
             // Set some properties.  Failing to specify some of these can cause the MediaCodec
             // configure() call to throw an unhelpful exception.
@@ -230,7 +274,7 @@
 
             // Create a MediaCodec for the desired codec, then configure it as an encoder with
             // our desired properties.
-            encoder = MediaCodec.createByCodecName(codecName);
+            encoder = MediaCodec.createByCodecName(mEncoderName);
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             inputSurface = new InputSurface(encoder.createInputSurface());
             inputSurface.makeCurrent();
@@ -253,15 +297,6 @@
     }
 
     /**
-     * Returns the first codec capable of encoding the specified MIME type, or null if no
-     * match was found.
-     */
-    private static String selectCodec(MediaFormat format) {
-        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-        return mcl.findEncoderForFormat(format);
-    }
-
-    /**
      * Generates video frames, feeds them into the encoder, and writes the output to the
      * VideoChunks instance.
      */
@@ -411,7 +446,7 @@
 
             // Create an encoder format that matches the input format.  (Might be able to just
             // re-use the format used to generate the video, since we want it to be the same.)
-            MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
+            MediaFormat outputFormat = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
             outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                     MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
             outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,
@@ -423,14 +458,14 @@
 
             outputData.setMediaFormat(outputFormat);
 
-            encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+            encoder = MediaCodec.createByCodecName(mEncoderName);
             encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             inputSurface = new InputSurface(encoder.createInputSurface());
             inputSurface.makeCurrent();
             encoder.start();
 
             // OutputSurface uses the EGL context created by InputSurface.
-            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
+            decoder = MediaCodec.createByCodecName(mDecoderName);
             outputSurface = new OutputSurface();
             outputSurface.changeFragmentShader(FRAGMENT_SHADER);
             // do not allow frame drops
@@ -639,7 +674,7 @@
             surface = new OutputSurface(mWidth, mHeight);
 
             MediaFormat format = inputData.getMediaFormat();
-            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
+            decoder = MediaCodec.createByCodecName(mDecoderName);
             format.setInteger(KEY_ALLOW_FRAME_DROP, 0);
             decoder.configure(format, surface.getSurface(), null, 0);
             decoder.start();
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
index 9250141..5ef9e7f 100755
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -47,6 +47,7 @@
 import android.widget.ImageView;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 import com.android.compatibility.common.util.MediaUtils;
@@ -55,8 +56,19 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Tests connecting a virtual display to the input of a MediaCodec encoder.
@@ -77,36 +89,24 @@
 @Presubmit
 @SmallTest
 @RequiresDevice
-public class EncodeVirtualDisplayTest extends AndroidTestCase {
+@RunWith(Parameterized.class)
+public class EncodeVirtualDisplayTest {
     private static final String TAG = "EncodeVirtualTest";
     private static final boolean VERBOSE = false;           // lots of logging
     private static final boolean DEBUG_SAVE_FILE = false;   // save copy of encoded movie
     private static final String DEBUG_FILE_NAME_BASE = "/sdcard/test.";
-
-    // Encoder parameters table, sort by encoder level from high to low.
-    private static final int[][] ENCODER_PARAM_TABLE = {
-        // width,  height,  bitrate,    framerate  /* level */
-        { 1280,     720,    14000000,   30 },  /* AVCLevel31 */
-        {  720,     480,    10000000,   30 },  /* AVCLevel3  */
-        {  720,     480,    4000000,    15 },  /* AVCLevel22 */
-        {  352,     576,    4000000,    25 },  /* AVCLevel21 */
-    };
+    private static final String CODEC_PREFIX_KEY = "codec-prefix";
+    private static String mCodecPrefix;
 
     // Virtual display characteristics.  Scaled down from full display size because not all
     // devices can encode at the resolution of their own display.
     private static final String NAME = TAG;
-    private static int sWidth = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][0];
-    private static int sHeight = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][1];
     private static final int DENSITY = DisplayMetrics.DENSITY_HIGH;
     private static final int UI_TIMEOUT_MS = 2000;
     private static final int UI_RENDER_PAUSE_MS = 400;
 
-    // Encoder parameters.  We use the same width/height as the virtual display.
-    private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
-    private static int sFrameRate = 15;               // 15fps
     // 100 days between I-frames
     private static final int IFRAME_INTERVAL = 60 * 60 * 24 * 100;
-    private static int sBitRate = 6000000;            // 6Mbps
 
     // Colors to test (RGB).  These must convert cleanly to and from BT.601 YUV.
     private static final int TEST_COLORS[] = {
@@ -123,6 +123,14 @@
     private Handler mUiHandler;                             // Handler on main Looper
     private DisplayManager mDisplayManager;
     volatile boolean mInputDone;
+    private Context mContext;
+    private String mEncoderName;
+    private String mMediaType;
+    private int mWidth;
+    private int mHeight;
+    private int mBitRate;
+    private int mFrameRate;
+    private MediaFormat mFormat;
 
     /* TEST_COLORS static initialization; need ARGB for ColorDrawable */
     private static int makeColor(int red, int green, int blue) {
@@ -132,13 +140,57 @@
     private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
     private static boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    public EncodeVirtualDisplayTest(String encodername, String mediaType, int width, int height,
+            int bitrate, int framerate, @SuppressWarnings("unused") String level) {
+        mEncoderName = encodername;
+        mMediaType = mediaType;
+        mWidth = width;
+        mHeight = height;
+        mBitRate = bitrate;
+        mFrameRate = framerate;
+    }
 
+    @Before
+    public void setUp() throws Exception {
         mUiHandler = new Handler(Looper.getMainLooper());
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
         mDisplayManager = (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
-        setupEncoderParameters();
+    }
+
+    static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+        final List<Object[]> argsList = new ArrayList<>();
+        int argLength = exhaustiveArgsList.get(0).length;
+        for (Object[] arg : exhaustiveArgsList) {
+            String[] componentNames = MediaUtils.getEncoderNamesForMime((String)arg[0]);
+            for (String name : componentNames) {
+                if (mCodecPrefix != null && !name.startsWith(mCodecPrefix)) {
+                    continue;
+                }
+                Object[] testArgs = new Object[argLength + 1];
+                // Add codec name as first argument and then copy all other arguments passed
+                testArgs[0] = name;
+                System.arraycopy(arg, 0, testArgs, 1, argLength);
+                argsList.add(testArgs);
+            }
+        }
+        return argsList;
+    }
+
+    static {
+        android.os.Bundle args = InstrumentationRegistry.getArguments();
+        mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+    }
+
+    @Parameterized.Parameters(name = "{index}({0}:{6})")
+    public static Collection<Object[]> input() {
+        final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+                // mediaType, width, height,  bitrate, framerate, level
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 14000000, 30, "AVCLevel31"},
+                {MediaFormat.MIMETYPE_VIDEO_AVC,  720, 480, 10000000, 30, "AVCLevel3"},
+                {MediaFormat.MIMETYPE_VIDEO_AVC,  720, 480,  4000000, 15, "AVCLevel22"},
+                {MediaFormat.MIMETYPE_VIDEO_AVC,  352, 576,  4000000, 25, "AVCLevel21"},
+        });
+        return prepareParamList(exhaustiveArgsList);
     }
 
     /**
@@ -146,9 +198,21 @@
      *
      * @throws Exception
      */
+    @Test
     public void testEncodeVirtualDisplay() throws Throwable {
-
         if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
+        // Encoded video resolution matches virtual display.
+        mFormat = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
+        mFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
+        mFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+        mFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
+        mFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+        mFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
+        mFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT601_PAL);
+        mFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
+        assumeTrue(mEncoderName + " doesn't support format " + mFormat,
+                MediaUtils.supports(mEncoderName, mFormat));
 
         EncodeVirtualWrapper.runTest(this);
     }
@@ -188,41 +252,6 @@
     }
 
     /**
-     * Returns true if the encoder level, specified in the ENCODER_PARAM_TABLE, can be supported.
-     */
-    private static boolean verifySupportForEncoderLevel(int i) {
-        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-        MediaFormat format = MediaFormat.createVideoFormat(
-                MIME_TYPE, ENCODER_PARAM_TABLE[i][0], ENCODER_PARAM_TABLE[i][1]);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, ENCODER_PARAM_TABLE[i][2]);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, ENCODER_PARAM_TABLE[i][3]);
-        return mcl.findEncoderForFormat(format) != null;
-    }
-
-    /**
-     * Initialize the encoder parameters according to the device capability.
-     */
-    private static void setupEncoderParameters() {
-
-        // Loop over each tabel entry until a proper encoder setting is found.
-        for (int i = 0; i < ENCODER_PARAM_TABLE.length; i++) {
-
-            // Check if we can support it?
-            if (verifySupportForEncoderLevel(i)) {
-
-                sWidth = ENCODER_PARAM_TABLE[i][0];
-                sHeight = ENCODER_PARAM_TABLE[i][1];
-                sBitRate = ENCODER_PARAM_TABLE[i][2];
-                sFrameRate = ENCODER_PARAM_TABLE[i][3];
-
-                Log.d(TAG, "encoder parameters changed: width = " + sWidth + ", height = " + sHeight
-                    + ", bitrate = " + sBitRate + ", framerate = " + sFrameRate);
-                break;
-            }
-        }
-    }
-
-    /**
      * Prepares the encoder, decoder, and virtual display.
      */
     private void encodeVirtualDisplayTest() throws IOException {
@@ -230,52 +259,40 @@
         MediaCodec decoder = null;
         OutputSurface outputSurface = null;
         VirtualDisplay virtualDisplay = null;
+        ColorSlideShow slideShow = null;
 
         try {
-            // Encoded video resolution matches virtual display.
-            MediaFormat encoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
-            encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
-            encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, sBitRate);
-            encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, sFrameRate);
-            encoderFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
-            encoderFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
-            encoderFormat.setInteger(MediaFormat.KEY_COLOR_STANDARD, MediaFormat.COLOR_STANDARD_BT601_PAL);
-            encoderFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
-
-            MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
-            String codec = mcl.findEncoderForFormat(encoderFormat);
-            if (codec == null) {
-                // Don't run the test if the codec isn't present.
-                Log.i(TAG, "SKIPPING test: no support for " + encoderFormat);
-                return;
-            }
-
-            encoder = MediaCodec.createByCodecName(codec);
-            encoder.configure(encoderFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+            encoder = MediaCodec.createByCodecName(mEncoderName);
+            encoder.configure(mFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             Surface inputSurface = encoder.createInputSurface();
             encoder.start();
 
             // Create a virtual display that will output to our encoder.
             virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
-                    sWidth, sHeight, DENSITY, inputSurface, 0);
+                    mWidth, mHeight, DENSITY, inputSurface, 0);
 
             // We also need a decoder to check the output of the encoder.
-            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
-            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
-            outputSurface = new OutputSurface(sWidth, sHeight);
+            decoder = MediaCodec.createDecoderByType(mMediaType);
+            MediaFormat decoderFormat = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
+            outputSurface = new OutputSurface(mWidth, mHeight);
             decoder.configure(decoderFormat, outputSurface.getSurface(), null, 0);
             decoder.start();
 
             // Run the color slide show on a separate thread.
             mInputDone = false;
-            new ColorSlideShow(virtualDisplay.getDisplay()).start();
+            slideShow = new ColorSlideShow(virtualDisplay.getDisplay());
+            slideShow.start();
 
             // Record everything we can and check the results.
             doTestEncodeVirtual(encoder, decoder, outputSurface);
 
         } finally {
             if (VERBOSE) Log.d(TAG, "releasing codecs, surfaces, and virtual display");
+            if (slideShow != null) {
+                try {
+                    slideShow.join();
+                } catch (InterruptedException ignore) {}
+            }
             if (virtualDisplay != null) {
                 virtualDisplay.release();
             }
@@ -311,7 +328,7 @@
         MediaMuxer muxer = null;
         int trackIndex = -1;
         if (DEBUG_SAVE_FILE) {
-            String fileName = DEBUG_FILE_NAME_BASE + sWidth + "x" + sHeight + ".mp4";
+            String fileName = DEBUG_FILE_NAME_BASE + mWidth + "x" + mHeight + ".mp4";
             try {
                 muxer = new MediaMuxer(fileName, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
                 Log.d(TAG, "encoded output will be saved as " + fileName);
@@ -497,8 +514,8 @@
 
         // Read a pixel from the center of the surface.  Might want to read from multiple points
         // and average them together.
-        int x = sWidth / 2;
-        int y = sHeight / 2;
+        int x = mWidth / 2;
+        int y = mHeight / 2;
         GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
         int r = mPixelBuf.get(0) & 0xff;
         int g = mPixelBuf.get(1) & 0xff;
@@ -556,7 +573,7 @@
                 runOnUiThread(() -> {
                     // Want to create presentation on UI thread so it finds the right Looper
                     // when setting up the Dialog.
-                    presentation[0] = new TestPresentation(getContext(), mDisplay, color);
+                    presentation[0] = new TestPresentation(mContext, mDisplay, color);
                     if (VERBOSE) Log.d(TAG, "showing color=0x" + Integer.toHexString(color));
                     presentation[0].show();
                     latch.countDown();
@@ -619,7 +636,7 @@
             setTitle("Encode Virtual Test");
 
             // Create a solid color image to use as the content of the presentation.
-            ImageView view = new ImageView(getContext());
+            ImageView view = new ImageView(mContext);
             view.setImageDrawable(new ColorDrawable(mColor));
             view.setLayoutParams(new LayoutParams(
                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
index eec4568..b2fbc6c 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -524,8 +524,11 @@
                         int expectedSampleRate = OUTPUT_AUDIO_SAMPLE_RATE_HZ;
 
                         // SBR mode halves the sample rate in the format.
-                        if (OUTPUT_AUDIO_AAC_PROFILE ==
-                                MediaCodecInfo.CodecProfileLevel.AACObjectHE) {
+                        // Query output profile. KEY_PROFILE gets precedence over KEY_AAC_PROFILE
+                        int aac_profile = trackFormat.getInteger(MediaFormat.KEY_AAC_PROFILE, -1);
+                        int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE, aac_profile);
+
+                        if (profile == MediaCodecInfo.CodecProfileLevel.AACObjectHE) {
                             expectedSampleRate /= 2;
                         }
                         assertEquals("sample rates should match", expectedSampleRate,
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
index cbe3966..b4d4b31 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
@@ -16,7 +16,6 @@
 
 package android.media.codec.cts;
 
-import android.content.res.Resources;
 import android.media.MediaCodec;
 import android.media.MediaCodec.CodecException;
 import android.media.MediaCodecInfo;
@@ -34,10 +33,11 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 
-import androidx.test.platform.app.InstrumentationRegistry;
-
 import com.android.compatibility.common.util.MediaUtils;
 
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -48,9 +48,6 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
 /**
  * Verification test for video encoder and decoder.
  *
@@ -269,10 +266,11 @@
         public ArrayList<MediaCodec.BufferInfo> bufferInfo;
         public EncodingStatisticsInfo encStat;
 
-        VideoEncodeOutput(ArrayList<MediaCodec.BufferInfo> bufferInfo,
-            EncodingStatisticsInfo encStat) {
-            bufferInfo = bufferInfo;
-            encStat = encStat;
+        VideoEncodeOutput(
+                ArrayList<MediaCodec.BufferInfo> bufferInfo,
+                EncodingStatisticsInfo encStat) {
+            this.bufferInfo = bufferInfo;
+            this.encStat = encStat;
         }
     }
 
@@ -346,6 +344,7 @@
                 params.runInLooperThread = true;
             }
             outputParameters.add(params);
+            params.encodingStatisticsLevel = MediaFormat.VIDEO_ENCODING_STATISTICS_LEVEL_NONE;
         }
         return outputParameters;
     }
@@ -1042,10 +1041,6 @@
                     out.inPresentationTimeUs = mInPresentationTimeUs;
                     out.outPresentationTimeUs = mOutPresentationTimeUs;
                 }
-                mCodec.releaseOutputBuffer(index, false);
-
-                out.flags = info.flags;
-                out.outputGenerated = true;
 
                 MediaFormat format = codec.getOutputFormat(index);
                 if (format.containsKey(MediaFormat.KEY_VIDEO_QP_AVERAGE)) {
@@ -1054,6 +1049,11 @@
                     mHelper.saveAvgQp(avgQp);
                 }
 
+                mCodec.releaseOutputBuffer(index, false);
+
+                out.flags = info.flags;
+                out.outputGenerated = true;
+
                 if (mHelper.saveOutputFrame(out)) {
                     // output EOS
                     signalCompletion();
@@ -1092,6 +1092,17 @@
         @Override
         public void run() {
             Looper.prepare();
+            setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread t, Throwable e) {
+                    Log.e(TAG, "thread " + t + " exception " + e);
+                    try {
+                        deleteCodec();
+                    } catch (Exception ex) {
+                        Log.e(TAG, "exception from deleteCodec " + e);
+                    }
+                }
+            });
             synchronized (mThreadEvent) {
                 mHandler = new Handler();
                 mThreadEvent.notify();
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
index 10a18dd..ff38e6c 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
@@ -193,7 +193,7 @@
                 }
                 double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
                 double differenceAvgQp = avgSeqQp[i] - avgSeqQp[j];
-                if (differenceBitrate * differenceAvgQp > 0) {
+                if (differenceBitrate * differenceAvgQp >= 0) {
                     throw new RuntimeException("Target bitrates: " +
                             TEST_BITRATES_SET[j] + ", " + TEST_BITRATES_SET[i] +
                             ". Average QP: "
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
index 4c729ea..0f3281c 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
@@ -32,14 +32,20 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.MediaUtils;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.FileOutputStream;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -63,6 +69,7 @@
     private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
     private static final int OFFSET = 10;
     private static final long PER_TEST_TIMEOUT_MS = 60000;
+    private static final String CODEC_PREFIX_KEY = "codec-prefix";
     private static final String[] VIDEO_FILES = {
         // 144p
         "video_decode_accuracy_and_capability-h264_256x108_30fps.mp4",
@@ -141,13 +148,29 @@
         "video_decode_with_cropping-vp9_520x360_30fps.webm"
     };
 
+    private static final String INP_PREFIX = WorkDir.getMediaDirString() +
+            "assets/decode_accuracy/";
+    private static String mCodecPrefix;
+
     private View videoView;
     private VideoViewFactory videoViewFactory;
-    private String fileName;
     private String testName;
+    private String fileName;
+    private String decoderName;
     private String methodName;
     private SimplePlayer player;
 
+    static {
+        android.os.Bundle args = InstrumentationRegistry.getArguments();
+        mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+    }
+
+    public DecodeAccuracyTest(String decoderName, String fileName, String testName) {
+        this.testName = testName;
+        this.fileName = fileName;
+        this.decoderName = decoderName;
+    }
+
     @After
     @Override
     public void tearDown() throws Exception {
@@ -163,64 +186,76 @@
         super.tearDown();
     }
 
-    @Parameters
-    public static Collection<Object[]> data() {
+    @Parameters(name = "{index}({0}_{2})")
+    public static Collection<Object[]> input() throws IOException {
         final List<Object[]> testParams = new ArrayList<>();
-        for (int i = 0; i < VIDEO_FILES.length; i++) {
-            final String file = VIDEO_FILES[i];
+        for (String file : VIDEO_FILES) {
             Pattern regex = Pattern.compile("^\\w+-(\\w+)_\\d+fps\\.\\w+");
             Matcher matcher = regex.matcher(file);
             String testName = "";
             if (matcher.matches()) {
                 testName = matcher.group(1);
             }
-            testParams.add(new Object[] { testName, file });
+            MediaFormat mediaFormat =
+                    MediaUtils.getTrackFormatForResource(INP_PREFIX + file, "video");
+            String mediaType = mediaFormat.getString(MediaFormat.KEY_MIME);
+            String[] componentNames = MediaUtils.getDecoderNamesForMime(mediaType);
+            for (String componentName : componentNames) {
+                if (mCodecPrefix != null && !componentName.startsWith(mCodecPrefix)) {
+                    continue;
+                }
+                if (MediaUtils.supports(componentName, mediaFormat)) {
+                    testParams.add(new Object[] {componentName, file, testName});
+                    // Test only the first decoder that supports given format.
+                    // Remove the following break statement to test all decoders on the device.
+                    break;
+                }
+            }
         }
         return testParams;
     }
 
-    public DecodeAccuracyTest(String testName, String fileName) {
-        this.fileName = fileName;
-        this.testName = testName;
-    }
-
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewDecodeAccuracy() throws Exception {
         this.methodName = "testGLViewDecodeAccuracy";
-        runTest(new GLSurfaceViewFactory(), new VideoFormat(fileName));
+        runTest(new GLSurfaceViewFactory(), new VideoFormat(fileName), decoderName);
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerHeightDecodeAccuracy() throws Exception {
         this.methodName = "testGLViewLargerHeightDecodeAccuracy";
-        runTest(new GLSurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
+        runTest(new GLSurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)),
+            decoderName);
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testGLViewLargerWidthDecodeAccuracy() throws Exception {
         this.methodName = "testGLViewLargerWidthDecodeAccuracy";
-        runTest(new GLSurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
+        runTest(new GLSurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)),
+            decoderName);
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewVideoDecodeAccuracy() throws Exception {
         this.methodName = "testSurfaceViewVideoDecodeAccuracy";
-        runTest(new SurfaceViewFactory(), new VideoFormat(fileName));
+        runTest(new SurfaceViewFactory(), new VideoFormat(fileName), decoderName);
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerHeightDecodeAccuracy() throws Exception {
         this.methodName = "testSurfaceViewLargerHeightDecodeAccuracy";
-        runTest(new SurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)));
+        runTest(new SurfaceViewFactory(), getLargerHeightVideoFormat(new VideoFormat(fileName)),
+            decoderName);
     }
 
     @Test(timeout = PER_TEST_TIMEOUT_MS)
     public void testSurfaceViewLargerWidthDecodeAccuracy() throws Exception {
         this.methodName = "testSurfaceViewLargerWidthDecodeAccuracy";
-        runTest(new SurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)));
+        runTest(new SurfaceViewFactory(), getLargerWidthVideoFormat(new VideoFormat(fileName)),
+            decoderName);
     }
 
-    private void runTest(VideoViewFactory videoViewFactory, VideoFormat vf) {
+    private void runTest(VideoViewFactory videoViewFactory, VideoFormat vf, String decoderName) {
         Log.i(TAG, "Running test for " + vf.toPrettyString());
         if (!MediaUtils.canDecodeVideo(vf.getMimeType(), vf.getWidth(), vf.getHeight(), 30)) {
             MediaUtils.skipTest(TAG, "No supported codec is found.");
@@ -249,12 +284,13 @@
         }
         final int golden = getGoldenId(vf.getDescription(), vf.getOriginalSize());
         assertTrue("No golden found.", golden != 0);
-        decodeVideo(vf, videoViewFactory);
+        decodeVideo(vf, videoViewFactory, decoderName);
         validateResult(vf, videoViewFactory.getVideoViewSnapshot(), golden);
     }
 
-    private void decodeVideo(VideoFormat videoFormat, VideoViewFactory videoViewFactory) {
-        this.player = new SimplePlayer(getHelper().getContext());
+    private void decodeVideo(VideoFormat videoFormat, VideoViewFactory videoViewFactory,
+            String decoderName) {
+        this.player = new SimplePlayer(getHelper().getContext(), decoderName);
         final SimplePlayer.PlayerResult playerResult = player.decodeVideoFrames(
                 videoViewFactory.getSurface(), videoFormat, 10);
         assertTrue(playerResult.getFailureMessage(), playerResult.isSuccess());
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
index 893c437c..0c79713 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderConformanceTest.java
@@ -16,8 +16,6 @@
 
 package android.media.decoder.cts;
 
-import static org.junit.Assert.fail;
-
 import android.content.res.AssetFileDescriptor;
 import android.media.decoder.cts.R;
 import android.media.MediaCodec;
@@ -31,6 +29,7 @@
 import android.util.Log;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.DeviceReportLog;
 import com.android.compatibility.common.util.MediaUtils;
@@ -39,8 +38,9 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -49,9 +49,13 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.HashMap;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 /**
  * Conformance test for decoders on the device.
@@ -62,7 +66,7 @@
  * based on the YUV 420 plannar format.
  */
 @AppModeFull(reason = "There should be no instant apps specific behavior related to conformance")
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class DecoderConformanceTest extends MediaTestBase {
     private enum Status {
         FAIL,
@@ -73,14 +77,51 @@
     private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
     private static final String TAG = "DecoderConformanceTest";
     private static final String CONFORMANCE_SUBDIR = "conformance_vectors/";
-    private DeviceReportLog mReportLog;
-    private MediaCodec mDecoder;
-    private MediaExtractor mExtractor;
-    static final String mInpPrefix = WorkDir.getMediaDirString() + CONFORMANCE_SUBDIR;
-
-    private static final Map<String, String> MIMETYPE_TO_TAG = new HashMap <String, String>() {{
+    private static final String CODEC_PREFIX_KEY = "codec-prefix";
+    private static final String mInpPrefix = WorkDir.getMediaDirString() + CONFORMANCE_SUBDIR;
+    private static final Map<String, String> MIMETYPE_TO_TAG = new HashMap<String, String>() {{
         put(MediaFormat.MIMETYPE_VIDEO_VP9, "vp9");
     }};
+    private static String mCodecPrefix;
+
+    private final String mDecoderName;
+    private final String mMediaType;
+    private final String mTestVector;
+
+    private MediaCodec mDecoder;
+    private MediaExtractor mExtractor;
+
+    private DeviceReportLog mReportLog;
+
+    static {
+        android.os.Bundle args = InstrumentationRegistry.getArguments();
+        mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+    }
+
+    @Parameterized.Parameters(name = "{index}({0})")
+    public static Collection<Object[]> input() throws Exception {
+        final String[] mediaTypeList = new String[] {MediaFormat.MIMETYPE_VIDEO_VP9};
+        final List<Object[]> argsList = new ArrayList<>();
+        for (String mediaType : mediaTypeList) {
+            String[] componentNames = MediaUtils.getDecoderNamesForMime(mediaType);
+            List<String> testVectors = readCodecTestVectors(mediaType);
+            for (String testVector : testVectors) {
+                for (String name : componentNames) {
+                    if (mCodecPrefix != null && !name.startsWith(mCodecPrefix)) {
+                        continue;
+                    }
+                    argsList.add(new Object[] {name, mediaType, testVector});
+                }
+            }
+        }
+        return argsList;
+    }
+
+    public DecoderConformanceTest(String decodername, String mediaType, String testvector) {
+        mDecoderName = decodername;
+        mMediaType = mediaType;
+        mTestVector = testvector;
+    }
 
     @Before
     @Override
@@ -94,24 +135,7 @@
         super.tearDown();
     }
 
-    /**
-     * Test VP9 decoders from vendor.
-     */
-    @Test
-    public void testVP9Other() throws Exception {
-        decodeTestVectors(MediaFormat.MIMETYPE_VIDEO_VP9, false /* isGoog */);
-    }
-
-    /**
-     * Test Google's VP9 decoder from libvpx.
-     */
-    @Test
-    public void testVP9Goog() throws Exception {
-        decodeTestVectors(MediaFormat.MIMETYPE_VIDEO_VP9, true /* isGoog */);
-    }
-
-    private List<String> readResourceLines(String fileName) throws Exception {
-        Preconditions.assertTestFileExists(mInpPrefix + fileName);
+    private static List<String> readResourceLines(String fileName) throws Exception {
         InputStream is = new FileInputStream(mInpPrefix + fileName);
         BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
 
@@ -128,7 +152,7 @@
         return lines;
     }
 
-    private List<String> readCodecTestVectors(String mime) throws Exception {
+    private static List<String> readCodecTestVectors(String mime) throws Exception {
         String tag = MIMETYPE_TO_TAG.get(mime);
         String testVectorFileName = tag + "_test_vectors";
         return readResourceLines(testVectorFileName);
@@ -202,44 +226,26 @@
         }
     }
 
-    void decodeTestVectors(String mime, boolean isGoog) throws Exception {
-        MediaFormat format = new MediaFormat();
-        format.setString(MediaFormat.KEY_MIME, mime);
-        String[] decoderNames = MediaUtils.getDecoderNames(isGoog, format);
-        for (String decoderName: decoderNames) {
-            List<String> testVectors = readCodecTestVectors(mime);
-            for (String vectorName: testVectors) {
-                boolean pass = false;
-                Log.d(TAG, "Decode vector " + vectorName + " with " + decoderName);
-                try {
-                    Status stat = decodeTestVector(mime, decoderName, vectorName);
-                    if (stat == Status.PASS) {
-                        pass = true;
-                    } else if (stat == Status.SKIP) {
-                        release();
-                        continue;
-                    }
-                } catch (Exception e) {
-                    Log.e(TAG, "Decode " + vectorName + " fail");
-                    fail("Received exception " + e);
-                }
-
-                String streamName = "decoder_conformance_test";
-                mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
-                mReportLog.addValue("mime", mime, ResultType.NEUTRAL, ResultUnit.NONE);
-                mReportLog.addValue("is_goog", isGoog, ResultType.NEUTRAL, ResultUnit.NONE);
-                mReportLog.addValue("pass", pass, ResultType.NEUTRAL, ResultUnit.NONE);
-                mReportLog.addValue("vector_name", vectorName, ResultType.NEUTRAL, ResultUnit.NONE);
-                mReportLog.addValue("decode_name", decoderName, ResultType.NEUTRAL,
-                        ResultUnit.NONE);
-                mReportLog.submit(getInstrumentation());
-
-                if (!pass) {
-                    // Release mediacodec in failure or exception cases.
-                    release();
-                }
-            }
-
+    @Test
+    public void testDecoderConformance() {
+        Log.d(TAG, "Decode vector " + mTestVector + " with " + mDecoderName);
+        Status stat = Status.PASS;
+        try {
+            stat = decodeTestVector(mMediaType, mDecoderName, mTestVector);
+        } catch (Exception e) {
+            Log.e(TAG, "Decode " + mTestVector + " fail");
+            fail("Received exception " + e);
+        } finally {
+            release();
         }
+        String streamName = "decoder_conformance_test";
+        mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+        mReportLog.addValue("mime", mMediaType, ResultType.NEUTRAL, ResultUnit.NONE);
+        mReportLog.addValue("pass", stat != Status.FAIL, ResultType.NEUTRAL, ResultUnit.NONE);
+        mReportLog.addValue("vector_name", mTestVector, ResultType.NEUTRAL, ResultUnit.NONE);
+        mReportLog.addValue("decode_name", mDecoderName, ResultType.NEUTRAL, ResultUnit.NONE);
+        mReportLog.submit(InstrumentationRegistry.getInstrumentation());
+        assumeTrue(mDecoderName + " failed for " + mTestVector, stat != Status.FAIL);
+        assumeTrue(mDecoderName + " skipped for " + mTestVector, stat != Status.SKIP);
     }
 }
diff --git a/tests/tests/media/drmframework/AndroidTest.xml b/tests/tests/media/drmframework/AndroidTest.xml
index 01639e5..c6e311d 100644
--- a/tests/tests/media/drmframework/AndroidTest.xml
+++ b/tests/tests/media/drmframework/AndroidTest.xml
@@ -35,10 +35,6 @@
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMediaDrmFrameworkTestCases.apk" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
-        <option name="run-command" value="pm revoke android.media.drmframework.cts android.permission.SYSTEM_ALERT_WINDOW"/>
-    </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
         <option name="target" value="device" />
         <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
diff --git a/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
index 40584b6..630c7f6 100644
--- a/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
@@ -27,7 +27,6 @@
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
 #include <sys/stat.h>
-
 #include <android/native_window_jni.h>
 
 #include "AMediaObjects.h"
@@ -1041,6 +1040,17 @@
             return JNI_FALSE;
     }
 
+    // Check service availability
+    const char *outValue = NULL;
+    status = AMediaDrm_getPropertyString(aMediaObjects.getDrm(),
+            "aidlVersion", &outValue);
+    if (status != AMEDIA_OK) {
+        // Drm service not using aidl interface, skip checking default url value
+        return JNI_TRUE;
+    }
+
+    ALOGD("aidlVersion is [%s]", outValue);
+
     ALOGD("kDefaultUrl [%s], length %d, defaultUrl [%s], length %d",
         kDefaultUrl,
         (int)strlen(kDefaultUrl),
diff --git a/tests/tests/media/extractor/AndroidTest.xml b/tests/tests/media/extractor/AndroidTest.xml
index 09c79fc..007a65b 100644
--- a/tests/tests/media/extractor/AndroidTest.xml
+++ b/tests/tests/media/extractor/AndroidTest.xml
@@ -47,10 +47,6 @@
         <option name="config-filename" value="CtsMediaExtractorTestCases" />
         <option name="version" value="1.0"/>
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
-        <option name="run-command" value="pm revoke android.media.extractor.cts android.permission.SYSTEM_ALERT_WINDOW"/>
-    </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.media.extractor.cts" />
         <!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/misc/res/raw/a_4.ogg b/tests/tests/media/misc/res/raw/a_4.ogg
deleted file mode 100644
index 155e790..0000000
--- a/tests/tests/media/misc/res/raw/a_4.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/a_4_aac.mp4 b/tests/tests/media/misc/res/raw/a_4_aac.mp4
deleted file mode 100644
index 05a776f..0000000
--- a/tests/tests/media/misc/res/raw/a_4_aac.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/a_4_haptic.ogg b/tests/tests/media/misc/res/raw/a_4_haptic.ogg
deleted file mode 100644
index 3c94c8d..0000000
--- a/tests/tests/media/misc/res/raw/a_4_haptic.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/b_5.ogg b/tests/tests/media/misc/res/raw/b_5.ogg
deleted file mode 100644
index c64e508..0000000
--- a/tests/tests/media/misc/res/raw/b_5.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/b_5_aac.mp4 b/tests/tests/media/misc/res/raw/b_5_aac.mp4
deleted file mode 100644
index 9bce44d..0000000
--- a/tests/tests/media/misc/res/raw/b_5_aac.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/b_5_haptic.ogg b/tests/tests/media/misc/res/raw/b_5_haptic.ogg
deleted file mode 100644
index 90ab939..0000000
--- a/tests/tests/media/misc/res/raw/b_5_haptic.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/c_sharp_5.ogg b/tests/tests/media/misc/res/raw/c_sharp_5.ogg
deleted file mode 100644
index 18900f9..0000000
--- a/tests/tests/media/misc/res/raw/c_sharp_5.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/c_sharp_5_aac.mp4 b/tests/tests/media/misc/res/raw/c_sharp_5_aac.mp4
deleted file mode 100644
index 1e7f988..0000000
--- a/tests/tests/media/misc/res/raw/c_sharp_5_aac.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/c_sharp_5_haptic.ogg b/tests/tests/media/misc/res/raw/c_sharp_5_haptic.ogg
deleted file mode 100644
index 57c46ea..0000000
--- a/tests/tests/media/misc/res/raw/c_sharp_5_haptic.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/e_5.ogg b/tests/tests/media/misc/res/raw/e_5.ogg
deleted file mode 100644
index 2597e75..0000000
--- a/tests/tests/media/misc/res/raw/e_5.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/e_5_aac.mp4 b/tests/tests/media/misc/res/raw/e_5_aac.mp4
deleted file mode 100644
index 95bad2a..0000000
--- a/tests/tests/media/misc/res/raw/e_5_aac.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/e_5_haptic.ogg b/tests/tests/media/misc/res/raw/e_5_haptic.ogg
deleted file mode 100644
index 98289dc..0000000
--- a/tests/tests/media/misc/res/raw/e_5_haptic.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/g_sharp_5.ogg b/tests/tests/media/misc/res/raw/g_sharp_5.ogg
deleted file mode 100644
index 02e8112..0000000
--- a/tests/tests/media/misc/res/raw/g_sharp_5.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/g_sharp_5_aac.mp4 b/tests/tests/media/misc/res/raw/g_sharp_5_aac.mp4
deleted file mode 100644
index a357912..0000000
--- a/tests/tests/media/misc/res/raw/g_sharp_5_aac.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/g_sharp_5_haptic.ogg b/tests/tests/media/misc/res/raw/g_sharp_5_haptic.ogg
deleted file mode 100644
index 6fb7388..0000000
--- a/tests/tests/media/misc/res/raw/g_sharp_5_haptic.ogg
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/midi_a.mid b/tests/tests/media/misc/res/raw/midi_a.mid
deleted file mode 100644
index 941885f..0000000
--- a/tests/tests/media/misc/res/raw/midi_a.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/midi_b.mid b/tests/tests/media/misc/res/raw/midi_b.mid
deleted file mode 100644
index 424c960..0000000
--- a/tests/tests/media/misc/res/raw/midi_b.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/midi_cs.mid b/tests/tests/media/misc/res/raw/midi_cs.mid
deleted file mode 100644
index ee9cb23..0000000
--- a/tests/tests/media/misc/res/raw/midi_cs.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/midi_e.mid b/tests/tests/media/misc/res/raw/midi_e.mid
deleted file mode 100644
index dac820d..0000000
--- a/tests/tests/media/misc/res/raw/midi_e.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/midi_gs.mid b/tests/tests/media/misc/res/raw/midi_gs.mid
deleted file mode 100644
index 1d43841..0000000
--- a/tests/tests/media/misc/res/raw/midi_gs.mid
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/sine1khzm40db.wav b/tests/tests/media/misc/res/raw/sine1khzm40db.wav
deleted file mode 100644
index b653a77..0000000
--- a/tests/tests/media/misc/res/raw/sine1khzm40db.wav
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/sine1khzs40dblong.mp3 b/tests/tests/media/misc/res/raw/sine1khzs40dblong.mp3
deleted file mode 100644
index 29bc683..0000000
--- a/tests/tests/media/misc/res/raw/sine1khzs40dblong.mp3
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/test1m1s.mp3 b/tests/tests/media/misc/res/raw/test1m1s.mp3
deleted file mode 100644
index d54a9df..0000000
--- a/tests/tests/media/misc/res/raw/test1m1s.mp3
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/testopus.opus b/tests/tests/media/misc/res/raw/testopus.opus
deleted file mode 100644
index f2d598a..0000000
--- a/tests/tests/media/misc/res/raw/testopus.opus
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/res/raw/testwav_16bit_44100hz.wav b/tests/tests/media/misc/res/raw/testwav_16bit_44100hz.wav
deleted file mode 100644
index f57ee85..0000000
--- a/tests/tests/media/misc/res/raw/testwav_16bit_44100hz.wav
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
index f1e140f..d38f767 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
@@ -198,7 +198,7 @@
     public void testAllowedPackages() throws Exception {
         RouteDiscoveryPreference preference =
                 new RouteDiscoveryPreference.Builder(FEATURES_ALL, true)
-                        .setAllowedPackages(List.of("android.media.cts"))
+                        .setAllowedPackages(List.of("android.media.misc.cts"))
                         .build();
         Map<String, MediaRoute2Info> routes = waitAndGetRoutes(preference);
 
diff --git a/tests/tests/media/muxer/AndroidTest.xml b/tests/tests/media/muxer/AndroidTest.xml
index aa4110b..502f2ca 100644
--- a/tests/tests/media/muxer/AndroidTest.xml
+++ b/tests/tests/media/muxer/AndroidTest.xml
@@ -47,10 +47,6 @@
         <option name="config-filename" value="CtsMediaMuxerTestCases" />
         <option name="version" value="1.0"/>
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
-        <option name="run-command" value="pm revoke android.media.muxer.cts android.permission.SYSTEM_ALERT_WINDOW"/>
-    </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.media.muxer.cts" />
         <!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/media/player/AndroidTest.xml b/tests/tests/media/player/AndroidTest.xml
index 7b92b12..e3e8b02 100644
--- a/tests/tests/media/player/AndroidTest.xml
+++ b/tests/tests/media/player/AndroidTest.xml
@@ -47,10 +47,6 @@
         <option name="config-filename" value="CtsMediaPlayerTestCases" />
         <option name="version" value="1.0"/>
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
-        <option name="run-command" value="pm revoke android.media.player.cts android.permission.SYSTEM_ALERT_WINDOW"/>
-    </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.media.player.cts" />
         <!-- setup can be expensive so limit the number of shards -->
diff --git a/tests/tests/multiuser/src/android/multiuser/cts/UserManagerTest.java b/tests/tests/multiuser/src/android/multiuser/cts/UserManagerTest.java
index 8aa4e7f..1b3e627 100644
--- a/tests/tests/multiuser/src/android/multiuser/cts/UserManagerTest.java
+++ b/tests/tests/multiuser/src/android/multiuser/cts/UserManagerTest.java
@@ -139,7 +139,7 @@
                     userHandle);
             final UserManager cloneUserManager = userContext.getSystemService(UserManager.class);
             assertThat(cloneUserManager.isMediaSharedWithParent()).isTrue();
-            assertThat(cloneUserManager.isCredentialSharedWithParent()).isTrue();
+            assertThat(cloneUserManager.isCredentialSharableWithParent()).isTrue();
             assertThat(cloneUserManager.isCloneProfile()).isTrue();
 
             final List<UserInfo> list = mUserManager.getUsers(true, true, true);
diff --git a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
index 4fb4917..e4ba869 100644
--- a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
+++ b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
@@ -184,27 +184,25 @@
     public void testSuspendPackage() throws Exception {
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
-        Thread.sleep(500); // wait for listener to be allowed
+        Thread.sleep(1000); // wait for listener to be allowed
 
         mListener = TestNotificationListener.getInstance();
         Assert.assertNotNull(mListener);
 
         sendNotification(1, R.drawable.icon_black);
-        Thread.sleep(500); // wait for notification listener to receive notification
-        assertEquals(1, mListener.mPosted.size());
+        assertTrue(pollForPostedNotifications(1));
         mListener.resetData();
 
         // suspend package, listener receives onRemoved
         suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                 true);
-        Thread.sleep(500); // wait for notification listener to get response
-        assertEquals(1, mListener.mRemoved.size());
+        Thread.sleep(1000); // wait for notification listener to get response
+        assertTrue(pollForRemovedNotifications(1));
 
         // unsuspend package, listener receives onPosted
         suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                 false);
-        Thread.sleep(500); // wait for notification listener to get response
-        assertEquals(1, mListener.mPosted.size());
+        assertTrue(pollForPostedNotifications(1));
 
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), false);
@@ -227,14 +225,13 @@
         Thread.sleep(500); // wait for notification listener to get response
 
         sendNotification(1, R.drawable.icon_black);
-        Thread.sleep(500); // wait for notification listener in case it receives notification
+        Thread.sleep(1000); // wait for notification listener in case it receives notification
         assertEquals(0, mListener.mPosted.size()); // shouldn't see any notifications posted
 
         // unsuspend package, listener should receive onPosted
         suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                 false);
-        Thread.sleep(500); // wait for notification listener to get response
-        assertEquals(1, mListener.mPosted.size());
+        assertTrue(pollForPostedNotifications(1));
 
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), false);
@@ -324,13 +321,13 @@
         assertEquals(Build.VERSION_CODES.O_MR1, mContext.getApplicationInfo().targetSdkVersion);
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
-        Thread.sleep(500); // wait for listener to be allowed
+        Thread.sleep(1000); // wait for listener to be allowed
         mListener = TestNotificationListener.getInstance();
 
         sendNotification(566, R.drawable.icon_black);
 
-        Thread.sleep(500); // wait for notification listener to receive notification
-        assertEquals(1, mListener.mPosted.size());
+        // wait for notification listener to receive notification
+        assertTrue(pollForPostedNotifications(1));
         String key = mListener.mPosted.get(0).getKey();
 
         mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
@@ -363,6 +360,36 @@
         mNotificationManager.notify(id, notification);
     }
 
+    // Wait for the listener to have received the specified number of posted notifications.
+    private boolean pollForPostedNotifications(int expected) {
+        for (int tries = 5; tries-- > 0; ) {
+            if (mListener.mPosted.size() >= expected) {
+                return true;
+            }
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+        return false;
+    }
+
+    // Wait for the listener to have received the specified number of removed notifications.
+    private boolean pollForRemovedNotifications(int expected) {
+        for (int tries = 5; tries-- > 0; ) {
+            if (mListener.mRemoved.size() >= expected) {
+                return true;
+            }
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+        return false;
+    }
+
     private int getCancellationReason(String key) {
         for (int tries = 3; tries-- > 0; ) {
             if (mListener.mRemoved.containsKey(key)) {
diff --git a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
index a35ff16..8c17a72f 100644
--- a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
+++ b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
@@ -23,13 +23,17 @@
 #include <poll.h>
 #include <pthread.h>
 #include <stdio.h>
+#include <string.h>
 #include <syscall.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/utsname.h>
+#include <sys/xattr.h>
 #include <unistd.h>
 
+#define SELINUX_CTXT_LEN 255
+
 static void* userfault_handler_thread(void* arg) {
   struct uffd_msg msg;
   struct uffdio_copy uffdio_copy;
@@ -95,6 +99,17 @@
   pthread_exit(reinterpret_cast<void*>(ret));
 }
 
+int64_t uffd_api_ioctl(int fd, uint64_t features) {
+  struct uffdio_api api;
+  std::memset(&api, '\0', sizeof api);
+  api.api = UFFD_API;
+  api.features = features;
+  if (ioctl(fd, UFFDIO_API, &api) < 0) {
+    return -1;
+  }
+  return api.features;
+}
+
 extern "C"
 JNIEXPORT bool JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_confirmKernelVersion(JNIEnv*) {
 #if defined(__linux__)
@@ -150,10 +165,7 @@
     goto out_close_both;
   }
 
-  struct uffdio_api api;
-  std::memset(&api, '\0', sizeof api);
-  api.api = UFFD_API;
-  if (ioctl(uffd, UFFDIO_API, &api) < 0) {
+  if (uffd_api_ioctl(uffd, /*features*/ 0) == -1) {
     ret = errno;
     goto out_unmap;
   }
@@ -227,25 +239,51 @@
 
 extern "C"
 JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMinorUffd(JNIEnv*) {
-  uint64_t req_features;
+  uint64_t req_features = UFFD_FEATURE_MINOR_SHMEM;
+  int64_t available_features = 0;
   int ret = 0;
   int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
   if (uffd < 0) {
     ret = errno;
     goto out;
   }
-  struct uffdio_api api;
-  std::memset(&api, '\0', sizeof api);
-  api.api = UFFD_API;
-  req_features = UFFD_FEATURE_MINOR_SHMEM;
-  api.features = req_features;
-  if (ioctl(uffd, UFFDIO_API, &api) < 0) {
+  available_features = uffd_api_ioctl(uffd, req_features);
+  if (available_features == -1) {
     ret = errno;
+  } else if ((available_features & req_features) != req_features) {
+    // Minor feature is not supported by this kernel.
+    ret = EINVAL;
   }
-  // Minor feature is not supported by this kernel.
-  if ((api.features & req_features) != req_features) {
-    ret = -EINVAL;
+  close(uffd);
+out:
+  return ret;
+}
+
+extern "C"
+JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_checkGetattr(JNIEnv*) {
+  ssize_t attr_ret = 0;
+  char selinux_ctxt[SELINUX_CTXT_LEN + 1];
+  int ret = 0;
+  int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
+  if (uffd < 0) {
+    ret = errno;
+    goto out;
   }
+  if (uffd_api_ioctl(uffd, /*features*/ 0) == -1) {
+    ret = errno;
+    goto out_close;
+  }
+  attr_ret = fgetxattr(uffd, XATTR_NAME_SELINUX, selinux_ctxt, SELINUX_CTXT_LEN);
+  if (attr_ret == -1) {
+    ret = errno;
+    goto out_close;
+  }
+  // We should never reach here as the call to fgetxattr must return EACCES.
+  selinux_ctxt[attr_ret] = 0;
+  if (strstr(selinux_ctxt, "userfaultfd") == nullptr) {
+    ret = -1;
+  }
+out_close:
   close(uffd);
 out:
   return ret;
diff --git a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
index 5ebe92c..fc4df13 100644
--- a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
+++ b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java
@@ -74,9 +74,18 @@
     assertEquals(0, performMinorUffd());
   }
 
+  // Confirms if userfaultfd is controlled by selinux or not.
+  // We don't allow getattr operation in our selinux policy.
+  @Test
+  public void selinuxEnabled() {
+    // Expect the return value to be EACCES (13).
+    assertEquals(13, checkGetattr());
+  }
+
   private native boolean confirmKernelVersion();
   private native int performKernelSpaceUffd();
   private native int uffdWithoutUserModeOnly();
   private native int performMremapDontUnmap();
   private native int performMinorUffd();
+  private native int checkGetattr();
 }
diff --git a/tests/tests/os/src/android/os/cts/BundleTest.java b/tests/tests/os/src/android/os/cts/BundleTest.java
index 27d5643..380cf23 100644
--- a/tests/tests/os/src/android/os/cts/BundleTest.java
+++ b/tests/tests/os/src/android/os/cts/BundleTest.java
@@ -671,6 +671,28 @@
     }
 
     @Test
+    public void testGetParcelableArrayListTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull() {
+        final ArrayList<CustomParcelable> originalObjects = new ArrayList<>();
+        originalObjects.add(new CustomParcelable(42, "don't panic"));
+        mBundle.putParcelableArrayList(KEY1, originalObjects);
+        roundtrip();
+        ArrayList<Parcelable> result = mBundle.getParcelableArrayList(KEY1, Intent.class);
+        assertNull(result);
+        assertFalse(CustomParcelable.sDeserialized);
+    }
+
+    @Test
+    public void testGetParcelableArrayListTypeSafe_withMatchingTypeAndDifferentReturnType__returnsObject() {
+        final ArrayList<CustomParcelable> original = new ArrayList<>();
+        original.add(new CustomParcelable(42, "don't panic"));
+        original.add(new CustomParcelable(1961, "off we go"));
+        mBundle.putParcelableArrayList(KEY1, original);
+        roundtrip();
+        ArrayList<Parcelable> result = mBundle.getParcelableArrayList(KEY1, CustomParcelable.class);
+        assertEquals(original, result);
+    }
+
+    @Test
     public void testGetParcelableArrayListTypeSafe_withBaseType_returnsObject() {
         final ArrayList<CustomParcelable> original = new ArrayList<>();
         original.add(new CustomParcelable(42, "don't panic"));
@@ -826,6 +848,29 @@
     }
 
     @Test
+    public void testGetSparseParcelableArrayTypeSafe_withMismatchingTypeAndDifferentReturnType_returnsNull() {
+        final SparseArray<CustomParcelable> originalObjects = new SparseArray<>();
+        originalObjects.put(42, new CustomParcelable(42, "don't panic"));
+        mBundle.putSparseParcelableArray(KEY1, originalObjects);
+        roundtrip();
+        SparseArray<Parcelable> result = mBundle.getSparseParcelableArray(KEY1, Intent.class);
+        assertNull(result);
+        assertFalse(CustomParcelable.sDeserialized);
+    }
+
+    @Test
+    public void testGetSparseParcelableArrayTypeSafe_withMatchingTypeAndDifferentReturnType_returnsObject() {
+        final SparseArray<CustomParcelable> original = new SparseArray<>();
+        original.put(42, new CustomParcelable(42, "don't panic"));
+        original.put(1961, new CustomParcelable(1961, "off we go"));
+        mBundle.putSparseParcelableArray(KEY1, original);
+        roundtrip();
+        SparseArray<Parcelable> result = mBundle.getSparseParcelableArray(KEY1,
+                CustomParcelable.class);
+        assertTrue(original.contentEquals(result));
+    }
+
+    @Test
     public void testGetSparseParcelableArrayTypeSafe_withBaseType_returnsObject() {
         final SparseArray<CustomParcelable> original = new SparseArray<>();
         original.put(42, new CustomParcelable(42, "don't panic"));
diff --git a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java b/tests/tests/os/src/android/os/cts/IpcDataCacheTest.java
similarity index 86%
rename from tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
rename to tests/tests/os/src/android/os/cts/IpcDataCacheTest.java
index 98b1bca..89c647d 100644
--- a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
+++ b/tests/tests/os/src/android/os/cts/IpcDataCacheTest.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package android.app.cts;
+package android.os.cts;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 
-import android.app.PropertyInvalidatedCache;
+import android.os.IpcDataCache;
 
 import androidx.test.filters.SmallTest;
 
@@ -28,19 +28,19 @@
 import org.junit.Test;
 
 /**
- * Test for verifying the behavior of {@link PropertyInvalidatedCache}.  This test does
+ * Test for verifying the behavior of {@link IpcDataCache}.  This test does
  * not use any actual binder calls - it is entirely self-contained.  This test also relies
- * on the test mode of {@link PropertyInvalidatedCache} because Android SELinux rules do
+ * on the test mode of {@link IpcDataCache} because Android SELinux rules do
  * not grant test processes the permission to set system properties.
  * <p>
  * Build/Install/Run:
- *  atest FrameworksCoreTests:PropertyInvalidatedCacheTests
+ *  atest CtsOsTestCases:IpcDataCacheTest
  */
 @SmallTest
-public class PropertyInvalidatedCacheTests {
+public class IpcDataCacheTest {
 
     // Configuration for creating caches
-    private static final String MODULE = PropertyInvalidatedCache.MODULE_TEST;
+    private static final String MODULE = IpcDataCache.MODULE_TEST;
     private static final String API = "testApi";
 
     // This class is a proxy for binder calls.  It contains a counter that increments
@@ -68,7 +68,7 @@
 
     // The functions for querying the server.
     private static class ServerQuery
-            extends PropertyInvalidatedCache.QueryHandler<Integer, Boolean> {
+            extends IpcDataCache.QueryHandler<Integer, Boolean> {
         private final ServerProxy mServer;
 
         ServerQuery(ServerProxy server) {
@@ -89,7 +89,7 @@
     // tests. This also resets the test property map.
     @After
     public void tearDown() throws Exception {
-        PropertyInvalidatedCache.setTestMode(false);
+        IpcDataCache.setTestMode(false);
     }
 
     // This test is disabled pending an sepolicy change that allows any app to set the
@@ -102,11 +102,11 @@
         ServerProxy tester = new ServerProxy();
 
         // Create a cache that uses simple arithmetic to computer its values.
-        PropertyInvalidatedCache<Integer, Boolean> testCache =
-                new PropertyInvalidatedCache<>(4, MODULE, API, "testCache1",
+        IpcDataCache<Integer, Boolean> testCache =
+                new IpcDataCache<>(4, MODULE, API, "testCache1",
                         new ServerQuery(tester));
 
-        PropertyInvalidatedCache.setTestMode(true);
+        IpcDataCache.setTestMode(true);
         testCache.testPropertyName();
 
         tester.verify(0);
@@ -148,14 +148,14 @@
         ServerProxy tester = new ServerProxy();
 
         // Three caches, all using the same system property but one uses a different name.
-        PropertyInvalidatedCache<Integer, Boolean> cache1 =
-                new PropertyInvalidatedCache<>(4, MODULE, API, "cacheA",
+        IpcDataCache<Integer, Boolean> cache1 =
+                new IpcDataCache<>(4, MODULE, API, "cacheA",
                         new ServerQuery(tester));
-        PropertyInvalidatedCache<Integer, Boolean> cache2 =
-                new PropertyInvalidatedCache<>(4, MODULE, API, "cacheA",
+        IpcDataCache<Integer, Boolean> cache2 =
+                new IpcDataCache<>(4, MODULE, API, "cacheA",
                         new ServerQuery(tester));
-        PropertyInvalidatedCache<Integer, Boolean> cache3 =
-                new PropertyInvalidatedCache<>(4, MODULE, API, "cacheB",
+        IpcDataCache<Integer, Boolean> cache3 =
+                new IpcDataCache<>(4, MODULE, API, "cacheB",
                         new ServerQuery(tester));
 
         // Caches are enabled upon creation.
@@ -177,7 +177,7 @@
         assertEquals(false, cache3.getDisabledState());
 
         // Create a new cache1.  Verify that the new instance is disabled.
-        cache1 = new PropertyInvalidatedCache<>(4, MODULE, API, "cacheA",
+        cache1 = new IpcDataCache<>(4, MODULE, API, "cacheA",
                 new ServerQuery(tester));
         assertEquals(true, cache1.getDisabledState());
 
@@ -188,13 +188,13 @@
         assertEquals(false, cache3.getDisabledState());
 
         // Create a new cache1.  Verify that the new instance is not disabled.
-        cache1 = new PropertyInvalidatedCache<>(4, MODULE, API, "cacheA",
+        cache1 = new IpcDataCache<>(4, MODULE, API, "cacheA",
                 new ServerQuery(tester));
         assertEquals(false, cache1.getDisabledState());
     }
 
     private static class TestQuery
-            extends PropertyInvalidatedCache.QueryHandler<Integer, String> {
+            extends IpcDataCache.QueryHandler<Integer, String> {
 
         private int mRecomputeCount = 0;
 
@@ -209,7 +209,7 @@
         }
     }
 
-    private static class TestCache extends PropertyInvalidatedCache<Integer, String> {
+    private static class TestCache extends IpcDataCache<Integer, String> {
         private final TestQuery mQuery;
 
         TestCache() {
@@ -248,7 +248,7 @@
         assertEquals("foo5", cache.query(5));
         assertEquals(3, cache.getRecomputeCount());
         // Invalidate the cache with a direct call to the property.
-        PropertyInvalidatedCache.invalidateCache(MODULE, API);
+        IpcDataCache.invalidateCache(MODULE, API);
         assertEquals("foo5", cache.query(5));
         assertEquals("foo5", cache.query(5));
         assertEquals(4, cache.getRecomputeCount());
diff --git a/tests/tests/os/src/android/os/cts/ProcessTest.java b/tests/tests/os/src/android/os/cts/ProcessTest.java
index 8ca7811..f72cd01 100644
--- a/tests/tests/os/src/android/os/cts/ProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ProcessTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -26,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
 import android.os.IBinder;
 import android.os.Process;
 import android.util.Log;
@@ -242,11 +244,23 @@
     @Test
     public void testSdkSandboxUids() {
         assertEquals(SANDBOX_SDK_UID, Process.toSdkSandboxUid(APP_UID));
-        assertEquals(APP_UID, Process.sdkSandboxToAppUid(SANDBOX_SDK_UID));
+        assertEquals(APP_UID, Process.getAppUidForSdkSandboxUid(SANDBOX_SDK_UID));
 
         assertFalse(Process.isSdkSandboxUid(APP_UID));
         assertTrue(Process.isSdkSandboxUid(SANDBOX_SDK_UID));
 
         assertFalse(Process.isSdkSandbox());
     }
+
+    /**
+     * Tests that the reserved UID is not taken by an actual package.
+     */
+    @Test
+    public void testReservedVirtualUid() {
+        PackageManager pm = mContext.getPackageManager();
+        final String name = pm.getNameForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
+        assertNull(name);
+        final String[] packages = pm.getPackagesForUid(Process.SDK_SANDBOX_VIRTUAL_UID);
+        assertNull(packages);
+    }
 }
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/Android.bp b/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
index 40f85c4..62a44fc 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
+++ b/tests/tests/packageinstaller/adminpackageinstaller/Android.bp
@@ -25,6 +25,7 @@
         "ub-uiautomator",
         "androidx.test.rules",
         "androidx.legacy_legacy-support-v4",
+        "cts-install-lib",
     ],
     libs: ["android.test.base"],
     sdk_version: "test_current",
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
index 5deef30..4ef431c 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
+++ b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
@@ -29,7 +29,9 @@
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="mkdir -p /data/local/tmp/cts/packageinstaller/" />
+        <option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+        <option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
     </target_preparer>
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
index 8d8d19e..6ebd026 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
+++ b/tests/tests/packageinstaller/adminpackageinstaller/src/android/packageinstaller/admin/cts/SessionCommitBroadcastTest.java
@@ -28,6 +28,11 @@
 import android.os.UserManager;
 import android.text.TextUtils;
 
+import com.android.cts.install.lib.Install;
+import com.android.cts.install.lib.InstallUtils;
+import com.android.cts.install.lib.TestApp;
+import com.android.cts.install.lib.Uninstall;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -54,6 +59,7 @@
     @Override
     protected void tearDown() throws Exception {
         mContext.unregisterReceiver(mReceiver);
+        Uninstall.packages(TestApp.A);
     }
 
     public void testBroadcastNotReceivedForDifferentLauncher() throws Exception {
@@ -91,6 +97,36 @@
         assertEquals(TEST_APP_PKG, info.getAppPackageName());
     }
 
+    public void testBroadcastNotReceivedForUpdateInstall() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        try {
+            setLauncher(mThisAppLauncher.flattenToString());
+
+            int sessionId = Install.single(TestApp.A1).commit();
+            assertEquals(1, InstallUtils.getInstalledVersion(TestApp.A));
+            // Check the broadcast is received for a new install and session id matches
+            Intent intent = mReceiver.blockingGetIntent();
+            PackageInstaller.SessionInfo info =
+                    intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
+            assertEquals(sessionId, info.getSessionId());
+
+            mContext.unregisterReceiver(mReceiver);
+            mReceiver = new SessionCommitReceiver();
+            Install.single(TestApp.A2).commit();
+            assertEquals(2, InstallUtils.getInstalledVersion(TestApp.A));
+
+            // Check no broadcast is received for an update install
+            intent = mReceiver.blockingGetIntent();
+            assertNull(intent);
+        } finally {
+            // Revert to default launcher
+            setLauncher(mDefaultLauncher.flattenToString());
+        }
+    }
+
     public void testBroadcastReceivedForNewInstall() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index 3176050..6f9b07a 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -91,6 +91,7 @@
         <option name="push" value="CtsStorageEscalationApp28.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp28.apk" />
         <option name="push" value="CtsStorageEscalationApp29Full.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Full.apk" />
         <option name="push" value="CtsStorageEscalationApp29Scoped.apk->/data/local/tmp/cts/permissions/CtsStorageEscalationApp29Scoped.apk" />
+        <option name="push" value="CtsAppThatHasNotificationListener.apk->/data/local/tmp/cts/permissions/CtsAppThatHasNotificationListener.apk" />
     </target_preparer>
 
     <!-- Remove additional apps if installed -->
@@ -102,6 +103,7 @@
         <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.userapp" />
         <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.runtimepermissiondefinerapp" />
         <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.runtimepermissionuserapp" />
+        <option name="teardown-command" value="pm uninstall android.permission.cts.appthathasnotificationlistener" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/permission/AppThatHasNotificationListener/Android.bp b/tests/tests/permission/AppThatHasNotificationListener/Android.bp
new file mode 100644
index 0000000..419ab5d
--- /dev/null
+++ b/tests/tests/permission/AppThatHasNotificationListener/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: "CtsAppThatHasNotificationListener",
+    defaults: [
+        "cts_defaults",
+        "mts-target-sdk-version-current",
+    ],
+    sdk_version: "current",
+    min_sdk_version: "30",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+        "sts",
+        "mts-permission",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+}
diff --git a/tests/tests/permission/AppThatHasNotificationListener/AndroidManifest.xml b/tests/tests/permission/AppThatHasNotificationListener/AndroidManifest.xml
new file mode 100644
index 0000000..03d23df
--- /dev/null
+++ b/tests/tests/permission/AppThatHasNotificationListener/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.permission.cts.appthathasnotificationlistener"
+          android:versionCode="1">
+
+    <application android:label="CtsNotificationListener">
+        <service
+            android:name=".CtsNotificationListenerService"
+            android:label="CtsNotificationListener"
+            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.service.notification.NotificationListenerService"/>
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
diff --git a/tests/tests/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java b/tests/tests/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java
new file mode 100644
index 0000000..2bd423e
--- /dev/null
+++ b/tests/tests/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission.cts.appthathasnotificationlistener;
+
+import android.service.notification.NotificationListenerService;
+
+public class CtsNotificationListenerService extends NotificationListenerService {}
diff --git a/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
new file mode 100644
index 0000000..d7c71b9
--- /dev/null
+++ b/tests/tests/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission.cts;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+/** Common test utilities */
+public class TestUtils {
+    private static final String LOG_TAG = TestUtils.class.getSimpleName();
+
+    /**
+     * A {@link java.util.concurrent.Callable} that can throw a {@link Throwable}
+     */
+    public interface ThrowingCallable<T> {
+        T call() throws Throwable;
+    }
+
+    /**
+     * A {@link Runnable} that can throw a {@link Throwable}
+     */
+    public interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+
+    /**
+     * Make sure that a {@link ThrowingRunnable} eventually finishes without throwing a {@link
+     * Exception}.
+     *
+     * @param r       The {@link ThrowingRunnable} to run.
+     * @param timeout the maximum time to wait
+     */
+    public static void eventually(@NonNull ThrowingRunnable r, long timeout) throws Throwable {
+        eventually(() -> {
+            r.run();
+            return 0;
+        }, timeout);
+    }
+
+    /**
+     * Make sure that a {@link ThrowingCallable} eventually finishes without throwing a {@link
+     * Exception}.
+     *
+     * @param r       The {@link ThrowingCallable} to run.
+     * @param timeout the maximum time to wait
+     * @return the return value from the callable
+     * @throws NullPointerException If the return value never becomes non-null
+     */
+    public static <T> T eventually(@NonNull ThrowingCallable<T> r, long timeout) throws Throwable {
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                T res = r.call();
+                if (res == null) {
+                    throw new NullPointerException("No result");
+                }
+
+                return res;
+            } catch (Throwable e) {
+                if (System.currentTimeMillis() - start < timeout) {
+                    Log.d(LOG_TAG, "Ignoring exception, occurred within valid wait time", e);
+
+                    Thread.sleep(500);
+                } else {
+                    throw e;
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
new file mode 100644
index 0000000..8d58bee
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.permission.cts;
+
+import static android.content.Intent.ACTION_BOOT_COMPLETED;
+import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
+import static android.os.Process.myUserHandle;
+import static android.permission.cts.PermissionUtils.clearAppState;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+import static android.permission.cts.TestUtils.eventually;
+
+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 org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+
+import static java.lang.Math.max;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.app.NotificationManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.DeviceConfig;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.DeviceConfigStateHelper;
+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.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;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tests the {@code NotificationListenerCheck} in permission controller.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot set system settings as instant app. Also we never show a notification"
+        + " listener check notification for instant apps.")
+public class NotificationListenerCheckTest {
+    private static final String LOG_TAG = NotificationListenerCheckTest.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private static final String TEST_APP_PKG =
+            "android.permission.cts.appthathasnotificationlistener";
+    private static final String TEST_APP_LABEL = "CtsLocationAccess";
+    private static final String TEST_APP_NOTIFICATION_SERVICE =
+            TEST_APP_PKG + ".CtsNotificationListenerService";
+    private static final String TEST_APP_NOTIFICATION_LISTENER_APK =
+            "/data/local/tmp/cts/permissions/CtsAppThatHasNotificationListener.apk";
+
+    private static final int NOTIFICATION_LISTENER_CHECK_JOB_ID = 4;
+
+    /**
+     * Device config property for whether notification listener check is enabled on the device
+     */
+    private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED =
+            "notification_listener_check_enabled";
+
+    /**
+     * Device config property for time period in milliseconds after which current enabled
+     * notification
+     * listeners are queried
+     */
+    private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
+            "notification_listener_check_interval_millis";
+
+    private static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
+            SECONDS.toMillis(1);
+
+    /**
+     * Device config property for time period in milliseconds after which a followup notification
+     * can be
+     * posted for an enabled notification listener
+     */
+    private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_PACKAGE_INTERVAL_MILLIS =
+            "notification_listener_check_pkg_interval_millis";
+
+    /**
+     * ID for notification shown by
+     * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}.
+     */
+    public static final int NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID = 3;
+
+    private static final long UNEXPECTED_TIMEOUT_MILLIS = 10000;
+    private static final long EXPECTED_TIMEOUT_MILLIS = 15000;
+
+    private static final Context sContext = InstrumentationRegistry.getTargetContext();
+    private static final PackageManager sPackageManager = sContext.getPackageManager();
+    private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation()
+            .getUiAutomation();
+
+    private static final String PERMISSION_CONTROLLER_PKG = sContext.getPackageManager()
+            .getPermissionControllerPackageName();
+
+    private static DeviceConfigStateHelper sPrivacyDeviceConfig =
+            new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_PRIVACY);
+    private static DeviceConfigStateHelper sJobSchedulerDeviceConfig =
+            new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
+
+    private static List<ComponentName> sPreviouslyEnabledNotificationListeners;
+
+    /**
+     * Enable notification listener check
+     */
+    private static void enableNotificationListenerCheckFeature() {
+        sPrivacyDeviceConfig.set(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+                String.valueOf(true));
+    }
+
+    /**
+     * Disable notification listener check
+     */
+    private static void disableNotificationListenerCheckFeature() {
+        sPrivacyDeviceConfig.set(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+                String.valueOf(false));
+    }
+
+    private static void setNotificationListenerCheckInterval(long intervalMs) {
+        // Override general notification interval
+        sPrivacyDeviceConfig.set(PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS,
+                Long.toString(intervalMs));
+    }
+
+    private static void setNotificationListenerCheckPackageInterval(long intervalMs) {
+        // Override package notification interval
+        sPrivacyDeviceConfig.set(PROPERTY_NOTIFICATION_LISTENER_CHECK_PACKAGE_INTERVAL_MILLIS,
+                Long.toString(intervalMs));
+    }
+
+    /**
+     * Allow or disallow a {@link NotificationListenerService} component for the current user
+     *
+     * @param listenerComponent {@link NotificationListenerService} component to allow or disallow
+     */
+    private static void setNotificationListenerServiceAllowed(ComponentName listenerComponent,
+            boolean allowed) {
+        String command = " cmd notification " + (allowed ? "allow_listener " : "disallow_listener ")
+                + listenerComponent.flattenToString();
+        runShellCommand(command);
+    }
+
+    private void allowTestAppNotificationListenerService() {
+        setNotificationListenerServiceAllowed(
+                new ComponentName(TEST_APP_PKG, TEST_APP_NOTIFICATION_SERVICE), true);
+    }
+
+    private void disallowTestAppNotificationListenerService() {
+        setNotificationListenerServiceAllowed(
+                new ComponentName(TEST_APP_PKG, TEST_APP_NOTIFICATION_SERVICE), false);
+    }
+
+    /**
+     * 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.
+     */
+    private static void runNotificationListenerCheck() throws Throwable {
+        // Sleep a little to make sure we don't have overlap in timing
+        Thread.sleep(1000);
+
+        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);
+        }, 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 = getLastJobTime(STOP_PERIODIC_JOB);
+            assertTrue(stopTime + " !> " + beforeJob, stopTime > beforeJob);
+        }, EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    /**
+     * Get a notifications thrown by the permission controller that are currently visible.
+     *
+     * @return {@link java.util.List} of {@link StatusBarNotification}
+     */
+    private List<StatusBarNotification> getPermissionControllerNotifications() throws Exception {
+        NotificationListenerService notificationService = NotificationListener.getInstance();
+        List<StatusBarNotification> permissionControllerNotifications = new ArrayList<>();
+
+        for (StatusBarNotification notification : notificationService.getActiveNotifications()) {
+            if (notification.getPackageName().equals(PERMISSION_CONTROLLER_PKG)) {
+                permissionControllerNotifications.add(notification);
+            }
+        }
+
+        return permissionControllerNotifications;
+    }
+
+    /**
+     * Get a notification listener notification that is currently visible.
+     *
+     * @param cancelNotification if {@code true} the notification is canceled inside this method
+     * @return The notification or {@code null} if there is none
+     */
+    private StatusBarNotification getNotification(boolean cancelNotification) throws Throwable {
+        NotificationListenerService notificationService = NotificationListener.getInstance();
+
+        List<StatusBarNotification> notifications = getPermissionControllerNotifications();
+        if (notifications.isEmpty()) {
+            return null;
+        }
+
+        for (StatusBarNotification notification : notifications) {
+            // There may be multiple notification listeners on device that are already allowed. Just
+            // check for a notification posted from the NotificationListenerCheck
+            if (notification.getId() == NOTIFICATION_LISTENER_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;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Clears all permission controller notifications that are currently visible.
+     */
+    private void clearPermissionControllerNotifications() throws Throwable {
+        NotificationListenerService notificationService = NotificationListener.getInstance();
+
+        List<StatusBarNotification> notifications = getPermissionControllerNotifications();
+        if (notifications.isEmpty()) {
+            return;
+        }
+
+        for (StatusBarNotification notification : notifications) {
+            notificationService.cancelNotification(notification.getKey());
+
+            // Wait for notification to get canceled
+            eventually(() -> assertFalse(
+                    Arrays.asList(notificationService.getActiveNotifications()).contains(
+                            notification)), UNEXPECTED_TIMEOUT_MILLIS);
+        }
+    }
+
+    @BeforeClass
+    public static void beforeClassSetup() {
+        // Disallow any OEM enabled NLS
+        disallowPreexistingNotificationListeners();
+
+        // Allow NLS used to verify notifications sent
+        setNotificationListenerServiceAllowed(
+                new ComponentName(sContext, NotificationListener.class), true);
+
+        reduceDelays();
+    }
+
+    @AfterClass
+    public static void afterClassTearDown() throws Throwable {
+        resetJobSchedulerConfig();
+        resetPermissionControllerConfig();
+
+        // Disallow NLS used to verify notifications sent
+        setNotificationListenerServiceAllowed(
+                new ComponentName(sContext, NotificationListener.class), false);
+
+        // Reallow any previously OEM allowed NLS
+        reallowPreexistingNotificationListeners();
+    }
+
+    private static void disallowPreexistingNotificationListeners() {
+        runWithShellPermissionIdentity(() -> {
+            NotificationManager notificationManager =
+                    sContext.getSystemService(NotificationManager.class);
+            sPreviouslyEnabledNotificationListeners =
+                    notificationManager.getEnabledNotificationListeners();
+        });
+        if (DEBUG) {
+            Log.d(LOG_TAG, "Found " + sPreviouslyEnabledNotificationListeners.size()
+                    + " previously allowed notification listeners. Disabling before test run.");
+        }
+        for (ComponentName listener : sPreviouslyEnabledNotificationListeners) {
+            setNotificationListenerServiceAllowed(listener, false);
+        }
+    }
+
+    private static void reallowPreexistingNotificationListeners() {
+        if (DEBUG) {
+            Log.d(LOG_TAG, "Re-allowing " + sPreviouslyEnabledNotificationListeners.size()
+                    + " previously allowed notification listeners found before test run.");
+        }
+        for (ComponentName listener : sPreviouslyEnabledNotificationListeners) {
+            setNotificationListenerServiceAllowed(listener, true);
+        }
+    }
+
+    /**
+     * Change settings so that permission controller can show notification listener notifications
+     * more often.
+     */
+    private static void reduceDelays() {
+        runWithShellPermissionIdentity(() -> {
+            // Override general notification interval from once every day to once ever 1 second
+            setNotificationListenerCheckInterval(
+                    OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS);
+
+            // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
+            sJobSchedulerDeviceConfig.set("qc_max_job_count_per_rate_limiting_window", "3000000");
+            sJobSchedulerDeviceConfig.set("qc_rate_limiting_window_ms", "30000");
+        });
+    }
+
+    /**
+     * Reset job scheduler configs.
+     */
+    private static void resetJobSchedulerConfig() throws Throwable {
+        runWithShellPermissionIdentity(() -> {
+            sJobSchedulerDeviceConfig.restoreOriginalValues();
+        });
+    }
+
+    /**
+     * Reset privacy configs.
+     */
+    private static void resetPermissionControllerConfig() {
+        runWithShellPermissionIdentity(() -> {
+            sPrivacyDeviceConfig.restoreOriginalValues();
+        });
+    }
+
+    @Before
+    public void setup() throws Throwable {
+        assumeNotPlayManaged();
+        wakeUpAndDismissKeyguard();
+        resetPermissionControllerBeforeEachTest();
+
+        // Cts NLS is required to verify sent Notifications, however, we don't want it to show up in
+        // testing
+        showAndDismissCtsNotificationListener();
+
+        clearNotifications();
+
+        // Sleep a little to avoid raciness in time keeping
+        Thread.sleep(1000);
+
+        // Install and allow the app with NLS for testing
+        install(TEST_APP_NOTIFICATION_LISTENER_APK);
+        allowTestAppNotificationListenerService();
+    }
+
+    @After
+    public void tearDown() throws Throwable {
+        // Disallow and uninstall the app with NLS for testing
+        disallowTestAppNotificationListenerService();
+        uninstallApp(TEST_APP_NOTIFICATION_LISTENER_APK);
+
+        clearNotifications();
+    }
+
+    /**
+     * Skip each test for play managed module
+     */
+    private void assumeNotPlayManaged() throws Exception {
+        assumeFalse(ModuleDetector.moduleIsPlayManaged(
+                sContext.getPackageManager(), MainlineModule.PERMISSION_CONTROLLER));
+    }
+
+    private void wakeUpAndDismissKeyguard() {
+        runShellCommand("input keyevent KEYCODE_WAKEUP");
+        runShellCommand("wm dismiss-keyguard");
+    }
+
+    /**
+     * Reset the permission controllers state before each test
+     */
+    private void resetPermissionControllerBeforeEachTest() throws Throwable {
+        // Has to be before resetPermissionController
+        enableNotificationListenerCheckFeature();
+
+        resetPermissionController();
+
+        // ensure no posted notification listener notifications exits
+        eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+
+        // Reset job scheduler stats (to allow more jobs to be run)
+        runShellCommand(
+                "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " "
+                        + PERMISSION_CONTROLLER_PKG);
+    }
+
+    /**
+     * Reset the permission controllers state.
+     */
+    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);
+
+        // Setup up permission controller again (simulate a reboot)
+        Intent permissionControllerSetupIntent = null;
+        for (ResolveInfo ri : sContext.getPackageManager().queryBroadcastReceivers(
+                new Intent(ACTION_BOOT_COMPLETED), 0)) {
+            String pkg = ri.activityInfo.packageName;
+
+            if (pkg.equals(PERMISSION_CONTROLLER_PKG)) {
+                permissionControllerSetupIntent = new Intent()
+                        .setClassName(pkg, ri.activityInfo.name)
+                        .setFlags(FLAG_RECEIVER_FOREGROUND)
+                        .setPackage(PERMISSION_CONTROLLER_PKG);
+
+                sContext.sendBroadcast(permissionControllerSetupIntent);
+            }
+        }
+
+        // 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);
+    }
+
+    /**
+     * Preshow/dismiss cts NotificationListener notification as it negatively affects test results
+     * (can result in unexpected test pass/failures)
+     */
+    private void showAndDismissCtsNotificationListener() throws Throwable {
+        // CtsNotificationListenerService isn't enabled at this point, but NotificationListener
+        // should be. Mark as notified by showing and dismissing
+        runNotificationListenerCheck();
+
+        // Sleep a little to avoid raciness in time keeping
+        Thread.sleep(1000);
+    }
+
+    /**
+     * Clear any notifications related to NotificationListenerCheck to ensure clean test setup
+     */
+    private void clearNotifications() throws Throwable {
+        // Clear notification if present
+        clearPermissionControllerNotifications();
+    }
+
+    @Test
+    public void noNotificationIfFeatureDisabled() throws Throwable {
+        disableNotificationListenerCheckFeature();
+
+        runNotificationListenerCheck();
+
+        assertNull("Expected no notifications", getNotification(false));
+    }
+
+    @Test
+    public void notificationIsShown() throws Throwable {
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull("Expected notification, none found", getNotification(true)),
+                EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void notificationIsShownOnlyOnce() throws Throwable {
+        runNotificationListenerCheck();
+        eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void notificationIsShownAgainAfterClear() throws Throwable {
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+        clearAppState(TEST_APP_PKG);
+
+        // Wait until package is cleared and permission controller has cleared the state
+        Thread.sleep(10000);
+
+        allowTestAppNotificationListenerService();
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void notificationIsShownAgainAfterUninstallAndReinstall() throws Throwable {
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+        uninstallApp(TEST_APP_PKG);
+
+        // Wait until package permission controller has cleared the state
+        Thread.sleep(2000);
+
+        install(TEST_APP_NOTIFICATION_LISTENER_APK);
+
+        allowTestAppNotificationListenerService();
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void removeNotificationOnUninstall() throws Throwable {
+        runNotificationListenerCheck();
+
+        eventually(() -> assertNotNull(getNotification(false)), EXPECTED_TIMEOUT_MILLIS);
+
+        uninstallApp(TEST_APP_PKG);
+
+        // Wait until package permission controller has cleared the state
+        Thread.sleep(2000);
+
+        eventually(() -> assertNull(getNotification(false)), EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void notificationIsNotShownAfterDisableAppNotificationListener() throws Throwable {
+        disallowTestAppNotificationListenerService();
+
+        runNotificationListenerCheck();
+
+        // We don't expect a notification, but try to trigger one anyway
+        eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+    }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java b/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
index 28e5b20..b131462 100755
--- a/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
+++ b/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
@@ -30,7 +30,7 @@
 import static android.Manifest.permission.READ_CONTACTS;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.READ_MEDIA_AUDIO;
-import static android.Manifest.permission.READ_MEDIA_IMAGE;
+import static android.Manifest.permission.READ_MEDIA_IMAGES;
 import static android.Manifest.permission.READ_MEDIA_VIDEO;
 import static android.Manifest.permission.READ_PHONE_STATE;
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
@@ -123,8 +123,8 @@
                         assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_AUDIO);
                     } else if (newPermissions.contains(READ_MEDIA_VIDEO)) {
                         assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_VIDEO);
-                    } else if (newPermissions.contains(READ_MEDIA_IMAGE)) {
-                        assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_IMAGE);
+                    } else if (newPermissions.contains(READ_MEDIA_IMAGES)) {
+                        assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_IMAGES);
                     }
                     break;
                 case READ_PRIVILEGED_PHONE_STATE:
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index fc564ea7..ffd5556 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1023,7 +1023,7 @@
       targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
       must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
      <p>Protection level: dangerous -->
-    <permission android:name="android.permission.READ_MEDIA_IMAGE"
+    <permission android:name="android.permission.READ_MEDIA_IMAGES"
                 android:permissionGroup="android.permission-group.UNDEFINED"
                 android:label="@string/permlab_readMediaImage"
                 android:description="@string/permdesc_readMediaImage"
@@ -1882,13 +1882,23 @@
         android:protectionLevel="normal" />
 
     <!-- Allows applications to enable/disable wifi auto join. This permission
-         is used to let OEMs grant their trusted app access to a subset of privileged wifi APIs
-         to improve wifi performance.
-         <p>Not for use by third-party applications. -->
+     is used to let OEMs grant their trusted app access to a subset of privileged wifi APIs
+     to improve wifi performance.
+     <p>Not for use by third-party applications.
+     @deprecated will be replaced with MANAGE_WIFI_NETWORK_SELECTION -->
     <permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN"
                 android:protectionLevel="signature|privileged|knownSigner"
                 android:knownCerts="@array/wifi_known_signers" />
 
+    <!-- This permission is used to let OEMs grant their trusted app access to a subset of
+     privileged wifi APIs to improve wifi performance. Allows applications to manage
+     Wi-Fi network selection related features such as enable or disable global auto-join,
+     modify connectivity scan intervals, and approve Wi-Fi Direct connections.
+     <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_WIFI_NETWORK_SELECTION"
+                android:protectionLevel="signature|privileged|knownSigner"
+                android:knownCerts="@array/wifi_known_signers" />
+
     <!-- Allows applications to get notified when a Wi-Fi interface request cannot
          be satisfied without tearing down one or more other interfaces, and provide a decision
          whether to approve the request or reject it.
@@ -2928,7 +2938,7 @@
     <!-- @SystemApi @hide Allows an application to set the profile owners and the device owner.
          This permission is not available to third party applications.-->
     <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
-        android:protectionLevel="signature|role|setup"
+        android:protectionLevel="signature|role"
         android:label="@string/permlab_manageProfileAndDeviceOwners"
         android:description="@string/permdesc_manageProfileAndDeviceOwners" />
 
@@ -2937,6 +2947,10 @@
     <permission android:name="android.permission.QUERY_ADMIN_POLICY"
                 android:protectionLevel="signature|role" />
 
+    <!-- @SystemApi @hide Allows an application to set a device owner on retail demo devices.-->
+    <permission android:name="android.permission.PROVISION_DEMO_DEVICE"
+                android:protectionLevel="signature|setup" />
+
     <!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
          periods. -->
     <permission android:name="android.permission.CLEAR_FREEZE_PERIOD"
@@ -3081,7 +3095,7 @@
 
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"
-                android:protectionLevel="signature|recents|role"/>
+                android:protectionLevel="signature|recents|role|installer"/>
 
     <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
          @hide
@@ -3710,13 +3724,20 @@
         android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
-    <!-- Permissions for SupplementalApi -->
+    <!-- Permissions for AdServices -->
     <!-- ========================================= -->
     <eat-comment />
 
-    <!-- TODO(b/213488783): Update with correct names. -->
-    <!-- Allows an application to access SupplementalApis. -->
-    <permission android:name="android.permission.ACCESS_SUPPLEMENTAL_APIS"
+    <!-- Allows an application to access AdServices Topics API. -->
+    <permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS"
+        android:protectionLevel="normal" />
+
+    <!-- Allows an application to access AdServices Attribution APIs. -->
+    <permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION"
+        android:protectionLevel="normal" />
+
+    <!-- Allows an application to access AdServices Custom Audiences APIs. -->
+    <permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCES"
         android:protectionLevel="normal" />
 
     <!-- ==================================== -->
@@ -6137,7 +6158,7 @@
     <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
          window to the window where the touch currently is on top of.  @hide -->
     <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
-                android:protectionLevel="signature|recents" />
+                android:protectionLevel="signature|privileged|recents|role" />
     <!--  Allows the caller to change the associations between input devices and displays.
         Very dangerous! @hide -->
     <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
@@ -6376,6 +6397,12 @@
     <permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an UID to be visible to the application based on an interaction between the
+         two apps. This permission is not intended to be held by apps.
+         @hide @TestApi  -->
+    <permission android:name="android.permission.MAKE_UID_VISIBLE"
+                android:protectionLevel="signature" />
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
diff --git a/tests/tests/permission3/Android.bp b/tests/tests/permission3/Android.bp
index d3f2721..36d24af 100644
--- a/tests/tests/permission3/Android.bp
+++ b/tests/tests/permission3/Android.bp
@@ -58,6 +58,7 @@
         ":CtsHelperAppOverlay",
         ":CtsCreateNotificationChannelsApp31",
         ":CtsCreateNotificationChannelsApp33",
+        ":CtsDifferentPkgNameApp",
     ],
     test_suites: [
         "cts",
diff --git a/tests/tests/permission3/AndroidTest.xml b/tests/tests/permission3/AndroidTest.xml
index 129cb4d..9e54fc6 100644
--- a/tests/tests/permission3/AndroidTest.xml
+++ b/tests/tests/permission3/AndroidTest.xml
@@ -63,6 +63,7 @@
         <option name="push" value="CtsHelperAppOverlay.apk->/data/local/tmp/cts/permission3/CtsHelperAppOverlay.apk" />
         <option name="push" value="CtsCreateNotificationChannelsApp31.apk->/data/local/tmp/cts/permission3/CtsCreateNotificationChannelsApp31.apk" />
         <option name="push" value="CtsCreateNotificationChannelsApp33.apk->/data/local/tmp/cts/permission3/CtsCreateNotificationChannelsApp33.apk" />
+        <option name="push" value="CtsDifferentPkgNameApp.apk->/data/local/tmp/cts/permission3/CtsDifferentPkgNameApp.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
index 457549f..9264c6c 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
+++ b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
@@ -31,26 +31,35 @@
 const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
 const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
 const val EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
-const val CHANNEL_ID = "channel_id"
+const val EXTRA_START_SECOND_ACTIVITY = "extra_start_second_activity"
+const val EXTRA_START_SECOND_APP = "extra_start_second_app"
+const val SECONDARY_APP_INTENT = "emptyactivity.main"
+const val SECONDARY_APP_PKG = "android.permission3.cts.usepermissionother"
+const val CHANNEL_ID_31 = "test_channel_id"
 const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
 const val DELAY_MS = 1000L
+const val LONG_DELAY_MS = 5000L
 
 class CreateNotificationChannelsActivity : Activity() {
     lateinit var notificationManager: NotificationManager
     override fun onStart() {
         val handler = Handler(Looper.getMainLooper())
         notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
-        if (intent.getBooleanExtra(EXTRA_CREATE_CHANNELS, false)) {
-            if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
-                notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID,
-                    "Foreground Services", NotificationManager.IMPORTANCE_HIGH))
-            }
+        if (intent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
+            handler.postDelayed({
+                val intent2 = Intent(SECONDARY_APP_INTENT)
+                intent2.`package` = SECONDARY_APP_PKG
+                intent2.addCategory(Intent.CATEGORY_DEFAULT)
+                handler.postDelayed({
+                    createChannel()
+                }, DELAY_MS)
+                startActivity(intent2)
+            }, LONG_DELAY_MS)
+        } else if (intent.getBooleanExtra(EXTRA_CREATE_CHANNELS, false)) {
+            createChannel()
         } else if (intent.getBooleanExtra(EXTRA_CREATE_CHANNELS_DELAYED, false)) {
             handler.postDelayed({
-                if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
-                    notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID,
-                        "Foreground Services", NotificationManager.IMPORTANCE_HIGH))
-                }
+                createChannel()
             }, DELAY_MS)
         }
 
@@ -65,12 +74,29 @@
         if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
             requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
         }
+        if (intent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)) {
+            handler.postDelayed({
+                val intent2 = Intent(Intent.ACTION_MAIN)
+                intent2.`package` = packageName
+                intent2.addCategory(Intent.CATEGORY_DEFAULT)
+                intent2.putExtra(EXTRA_CREATE_CHANNELS_DELAYED, true)
+                startActivity(intent2)
+            }, LONG_DELAY_MS)
+        }
+
         super.onStart()
     }
 
+    private fun createChannel() {
+        if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
+            notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
+                "Foreground Services", NotificationManager.IMPORTANCE_HIGH))
+        }
+    }
+
     override fun onPause() {
         if (intent.getBooleanExtra(EXTRA_DELETE_CHANNELS_ON_CLOSE, false)) {
-            notificationManager.deleteNotificationChannel(CHANNEL_ID)
+            notificationManager.deleteNotificationChannel(CHANNEL_ID_31)
         }
         super.onPause()
     }
diff --git a/tests/tests/permission3/DifferentPkgNameApp/Android.bp b/tests/tests/permission3/DifferentPkgNameApp/Android.bp
new file mode 100644
index 0000000..3db3c30
--- /dev/null
+++ b/tests/tests/permission3/DifferentPkgNameApp/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsDifferentPkgNameApp",
+    defaults: ["mts-target-sdk-version-current"],
+    min_sdk_version: "31",
+
+    static_libs: [
+        "kotlin-stdlib",
+    ],
+
+    srcs: [
+        "src/**/*.kt",
+    ],
+}
diff --git a/tests/tests/permission3/DifferentPkgNameApp/AndroidManifest.xml b/tests/tests/permission3/DifferentPkgNameApp/AndroidManifest.xml
new file mode 100644
index 0000000..77c45ba
--- /dev/null
+++ b/tests/tests/permission3/DifferentPkgNameApp/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.permission3.cts.usepermissionother"
+          android:versionCode="1">
+
+    <uses-sdk android:minSdkVersion="31" android:targetSdkVersion="31" />
+
+    <application android:label="EmptyActivity">
+        <activity android:name=".EmptyActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="emptyactivity.main" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/permission3/DifferentPkgNameApp/src/android/permission3/cts/usepermissionother/EmptyActivity.kt b/tests/tests/permission3/DifferentPkgNameApp/src/android/permission3/cts/usepermissionother/EmptyActivity.kt
new file mode 100644
index 0000000..e60466e
--- /dev/null
+++ b/tests/tests/permission3/DifferentPkgNameApp/src/android/permission3/cts/usepermissionother/EmptyActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.permission3.cts.usepermissionother
+
+import android.app.Activity
+
+class EmptyActivity : Activity()
\ No newline at end of file
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index ebdc507..c611d3890 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -67,7 +67,10 @@
             "$APK_DIRECTORY/CtsCreateNotificationChannelsApp31.apk"
         const val APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33 =
             "$APK_DIRECTORY/CtsCreateNotificationChannelsApp33.apk"
+        const val APP_APK_PATH_OTHER_APP =
+            "$APK_DIRECTORY/CtsDifferentPkgNameApp.apk"
         const val APP_PACKAGE_NAME = "android.permission3.cts.usepermission"
+        const val OTHER_APP_PACKAGE_NAME = "android.permission3.cts.usepermissionother"
 
         const val ALLOW_BUTTON =
                 "com.android.permissioncontroller:id/permission_allow_button"
@@ -110,7 +113,7 @@
             android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
             android.Manifest.permission.ACCESS_MEDIA_LOCATION,
             android.Manifest.permission.READ_MEDIA_AUDIO,
-            android.Manifest.permission.READ_MEDIA_IMAGE,
+            android.Manifest.permission.READ_MEDIA_IMAGES,
             android.Manifest.permission.READ_MEDIA_VIDEO
         )
     }
@@ -182,7 +185,7 @@
             android.Manifest.permission.READ_MEDIA_AUDIO to
                 "@android:string/permgrouplab_readMediaAural",
             // Visual
-            android.Manifest.permission.READ_MEDIA_IMAGE to
+            android.Manifest.permission.READ_MEDIA_IMAGES to
                 "@android:string/permgrouplab_readMediaVisual",
             android.Manifest.permission.READ_MEDIA_VIDEO to
                 "@android:string/permgrouplab_readMediaVisual"
@@ -322,11 +325,11 @@
         block
     )
 
-    protected fun clickPermissionRequestAllowButton() {
+    protected fun clickPermissionRequestAllowButton(timeoutMillis: Long = 20000) {
         if (isAutomotive) {
-            click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+            click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)), timeoutMillis)
         } else {
-            click(By.res(ALLOW_BUTTON))
+            click(By.res(ALLOW_BUTTON), timeoutMillis)
         }
     }
 
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index 2e5baf5..dc9d177 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -48,14 +48,18 @@
 const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
 const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
 const val EXTRA_REQUEST_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
+const val EXTRA_START_SECOND_ACTIVITY = "extra_start_second_activity"
+const val EXTRA_START_SECOND_APP = "extra_start_second_app"
 const val ACTIVITY_NAME = "CreateNotificationChannelsActivity"
 const val ACTIVITY_LABEL = "CreateNotif"
+const val SECOND_ACTIVITY_LABEL = "EmptyActivity"
 const val ALLOW = "to send you"
 const val CONTINUE_ALLOW = "to continue sending you"
 const val INTENT_ACTION = "usepermission.createchannels.MAIN"
 const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
 const val NOTIFICATION_PERMISSION_ENABLED = "notification_permission_enabled"
 const val DELAY_MS = 5000L
+const val DELAY_MS_SHORT = 500L
 
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
 class NotificationPermissionTest : BaseUsePermissionTest() {
@@ -153,54 +157,48 @@
     }
 
     @Test
-    fun notificationPromptDoesNotShowForLegacyAppWithNoNotificationChannels() {
+    fun notificationPromptDoesNotShowForLegacyAppWithNoNotificationChannels_onLaunch() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
-        setReviewRequired()
         launchApp(createChannels = false)
-        try {
-            clickPermissionRequestAllowButton()
-            Assert.fail("Expected not to find permission request dialog")
-        } catch (expected: RuntimeException) {
-            // Do nothing
-        }
+        assertDialogNotShowing()
+    }
+    @Test
+    fun notificationPromptDoesNotShowForNonLauncherIntentCategoryLaunches_onChannelCreate() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(launcherCategory = false)
+        assertDialogNotShowing()
     }
 
     @Test
-    fun notificationPromptDoesNotShowForNonLauncherIntentCategoryLaunches() {
+    fun notificationPromptDoesNotShowForNonLauncherIntentCategoryLaunches_onLaunch() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
-        setReviewRequired()
         // create channels, then leave the app
         launchApp()
         killTestApp()
         launchApp(launcherCategory = false)
-        try {
-            clickPermissionRequestAllowButton()
-            Assert.fail("Expected not to find permission request dialog")
-        } catch (expected: RuntimeException) {
-            // Do nothing
-        }
+        assertDialogNotShowing()
     }
 
     @Test
-    fun notificationPromptDoesNotShowForNonMainIntentActionLaunches() {
+    fun notificationPromptDoesNotShowForNonMainIntentActionLaunches_onLaunch() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
-        setReviewRequired()
         // create channels, then leave the app
         launchApp()
         killTestApp()
         launchApp(mainIntent = false)
-        try {
-            clickPermissionRequestAllowButton()
-            Assert.fail("Expected not to find permission request dialog")
-        } catch (expected: RuntimeException) {
-            // Do nothing
-        }
+        assertDialogNotShowing()
+    }
+
+    @Test
+    fun notificationPromptDoesNotShowForNonMainIntentActionLaunches_onChannelCreate() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(mainIntent = false)
+        assertDialogNotShowing()
     }
 
     @Test
     fun notificationPromptShowsIfActivityOptionSet() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
-        setReviewRequired()
         // create channels, then leave the app
         launchApp()
         killTestApp()
@@ -209,6 +207,55 @@
     }
 
     @Test
+    fun notificationPromptShownForSubsequentStartsIfTaskStartWasLauncher() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(startSecondActivity = true)
+        pressBack()
+        assertDialogNotShowing(DELAY_MS_SHORT)
+        Thread.sleep(DELAY_MS)
+        clickPermissionRequestAllowButton()
+    }
+
+    @Test
+    fun notificationPromptNotShownForSubsequentStartsIfTaskStartWasNotLauncher() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(mainIntent = false, startSecondActivity = true)
+        Thread.sleep(DELAY_MS)
+        assertDialogNotShowing()
+    }
+
+    @Test
+    fun notificationPromptShownForChannelCreateInSecondActivityIfTaskStartWasLauncher() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(startSecondActivity = true, createChannels = false)
+        Thread.sleep(DELAY_MS)
+        clickPermissionRequestAllowButton()
+    }
+
+    @Test
+    fun notificationPromptNotShownForChannelCreateInSecondActivityIfTaskStartWasntLauncher() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(mainIntent = false, startSecondActivity = true, createChannels = false)
+        Thread.sleep(DELAY_MS)
+        assertDialogNotShowing()
+    }
+
+    @Test
+    fun notificationPromptNotShownForSubsequentStartsIfSubsequentIsDifferentPkg() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        installPackage(APP_APK_PATH_OTHER_APP, expectSuccess = true)
+        // perform a launcher start, then start a secondary app
+        launchApp(startSecondaryAppAndCreateChannelsAfterSecondStart = true)
+        Thread.sleep(DELAY_MS)
+        try {
+            waitFindObject(By.textContains(SECOND_ACTIVITY_LABEL))
+            assertDialogNotShowing()
+        } finally {
+            uninstallPackage(OTHER_APP_PACKAGE_NAME)
+        }
+    }
+
+    @Test
     fun reviewRequiredNotClearedOnNonLauncherIntentCategoryLaunches() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_33, expectSuccess = true)
         setReviewRequired()
@@ -389,7 +436,9 @@
         requestPermissionsDelayed: Boolean = false,
         launcherCategory: Boolean = true,
         mainIntent: Boolean = true,
-        isEligibleForPromptOption: Boolean = false
+        isEligibleForPromptOption: Boolean = false,
+        startSecondActivity: Boolean = false,
+        startSecondaryAppAndCreateChannelsAfterSecondStart: Boolean = false
     ) {
         val intent = if (mainIntent && launcherCategory) {
             packageManager.getLaunchIntentForPackage(APP_PACKAGE_NAME)!!
@@ -410,6 +459,8 @@
             intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, requestPermissionsDelayed)
         }
         intent.putExtra(EXTRA_REQUEST_NOTIF_PERMISSION, requestNotificationPermission)
+        intent.putExtra(EXTRA_START_SECOND_ACTIVITY, startSecondActivity)
+        intent.putExtra(EXTRA_START_SECOND_APP, startSecondaryAppAndCreateChannelsAfterSecondStart)
         intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
 
         val options = ActivityOptions.makeBasic()
@@ -429,4 +480,13 @@
         }
         waitForIdle()
     }
+
+    private fun assertDialogNotShowing(timeoutMillis: Long = DELAY_MS) {
+        try {
+            clickPermissionRequestAllowButton(timeoutMillis)
+            Assert.fail("Expected not to find permission request dialog")
+        } catch (expected: RuntimeException) {
+            // Do nothing
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index ae71cd9..5355fdc 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -108,6 +108,7 @@
     }
 
     @Test
+    @Ignore
     fun testToggleSystemApps() {
         // I had some hard time mocking a system app.
         // Hence here I am only testing if the toggle is there.
@@ -158,6 +159,7 @@
     }
 
     @Test
+    @Ignore
     fun testToggleFrom24HoursTo7DaysInTimeline() {
         // Auto doesn't support the 7 day view
         assumeFalse(isAutomotive)
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 72f1de1..d39fb9c 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -33,7 +33,6 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Test
 
 /**
@@ -119,7 +118,6 @@
     }
 
     @Test
-    @Ignore
     fun testLocationCardDisplayed() {
         runSensorTest(LOCATION)
     }
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java b/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
index 49a33ad..da7f0fb 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStoreUtils.java
@@ -27,16 +27,16 @@
 import android.provider.MediaStore.MediaColumns;
 import android.text.format.DateUtils;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.filters.SdkSuppress;
+
 import org.junit.Test;
 
 import java.io.FileNotFoundException;
 import java.io.OutputStream;
 import java.util.Objects;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.SdkSuppress;
-
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
 public class MediaStoreUtils {
     @Test
@@ -118,6 +118,10 @@
             }
         }
 
+        public void setIsFavorite(@Nullable Boolean isFavorite) {
+            this.insertValues.put(MediaColumns.IS_FAVORITE, isFavorite);
+        }
+
         /**
          * Optionally set the Uri from where the file has been downloaded. This is used
          * for files being added to {@link Downloads} table.
diff --git a/tests/tests/safetycenter/Android.bp b/tests/tests/safetycenter/Android.bp
deleted file mode 100644
index f3b9716..0000000
--- a/tests/tests/safetycenter/Android.bp
+++ /dev/null
@@ -1,49 +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: "CtsSafetyCenterTestCases",
-    defaults: ["mts-target-sdk-version-current"],
-    sdk_version: "test_current",
-    min_sdk_version: "30",
-    srcs: [
-        "src/**/*.kt",
-    ],
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.ext.junit",
-        "androidx.test.rules",
-        "androidx.test.runner",
-        "androidx.test.uiautomator_uiautomator",
-        "compatibility-device-util-axt",
-        "ctstestrunner-axt",
-        "kotlin-stdlib",
-        "kotlinx-coroutines-android",
-        "kotlin-test",
-        "modules-utils-build_system",
-        "safety-center-resources-lib",
-        "truth-prebuilt",
-    ],
-    test_suites: [
-        "cts",
-        "general-tests",
-        "mts-permission",
-    ],
-}
diff --git a/tests/tests/safetycenter/AndroidManifest.xml b/tests/tests/safetycenter/AndroidManifest.xml
deleted file mode 100644
index cfa22f7..0000000
--- a/tests/tests/safetycenter/AndroidManifest.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2021 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.safetycenter.cts">
-
-    <application>
-        <uses-library android:name="android.test.runner"/>
-
-        <receiver android:name=".SafetySourceBroadcastReceiver" android:exported="false">
-            <intent-filter>
-                <action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
-            </intent-filter>
-        </receiver>
-    </application>
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:label="CTS tests for SafetyCenter"
-                     android:targetPackage="android.safetycenter.cts">
-        <meta-data android:name="listener"
-                   android:value="com.android.cts.runner.CtsTestRunListener"/>
-    </instrumentation>
-
-    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
-
-    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
-</manifest>
diff --git a/tests/tests/safetycenter/AndroidTest.xml b/tests/tests/safetycenter/AndroidTest.xml
deleted file mode 100644
index fc74c4a..0000000
--- a/tests/tests/safetycenter/AndroidTest.xml
+++ /dev/null
@@ -1,50 +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 SafetyCenter test cases">
-
-    <!-- TODO(b/207111503): Use Sdk33ModuleController once available, and remove @SdkSuppress
-         annotations -->
-    <object
-        class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"
-        type="module_controller"/>
-
-    <option name="config-descriptor:metadata" key="component" value="framework"/>
-    <option name="config-descriptor:metadata" key="parameter"
-            value="not_instant_app"/>
-    <option name="config-descriptor:metadata" key="parameter"
-            value="not_multi_abi"/>
-    <option name="config-descriptor:metadata" key="parameter"
-            value="secondary_user"/>
-
-    <option name="test-suite-tag" value="cts"/>
-
-    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
-        <option name="force-skip-system-props"
-                value="true"/> <!-- avoid restarting device -->
-    </target_preparer>
-
-    <target_preparer
-        class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true"/>
-        <option name="test-file-name" value="CtsSafetyCenterTestCases.apk"/>
-    </target_preparer>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
-        <option name="package" value="android.safetycenter.cts"/>
-        <option name="runtime-hint" value="5m"/>
-    </test>
-</configuration>
diff --git a/tests/tests/safetycenter/OWNERS b/tests/tests/safetycenter/OWNERS
deleted file mode 100644
index 026d342..0000000
--- a/tests/tests/safetycenter/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1026964
-
-include platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/tests/tests/safetycenter/res/values/strings.xml b/tests/tests/safetycenter/res/values/strings.xml
deleted file mode 100644
index 8ba7f04..0000000
--- a/tests/tests/safetycenter/res/values/strings.xml
+++ /dev/null
@@ -1,20 +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.
-  -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Test reference -->
-    <string name="reference" translatable="false">Reference</string>
-</resources>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_disabled_no_work.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_disabled_no_work.xml
deleted file mode 100644
index b2594c7..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_disabled_no_work.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="all_profiles"
-                initialDisplayState="disabled"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_no_work.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_no_work.xml
deleted file mode 100644
index e582e04..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_all_no_work.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="all_profiles"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_summary.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_summary.xml
deleted file mode 100644
index 6d06599..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_summary.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                initialDisplayState="disabled"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_title.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_title.xml
deleted file mode 100644
index 6d53576..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_disabled_no_title.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                initialDisplayState="disabled"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_duplicate_key.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_duplicate_key.xml
deleted file mode 100644
index be7114d..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_duplicate_key.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id1"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="id2"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_intent.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_intent.xml
deleted file mode 100644
index b30a6d9..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_intent.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                intentAction="intent"
-                profile="primary_profile_only"
-                initialDisplayState="hidden"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_summary.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_summary.xml
deleted file mode 100644
index c0fd181..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_summary.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                summary="@string/reference"
-                profile="primary_profile_only"
-                initialDisplayState="hidden"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_title.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_title.xml
deleted file mode 100644
index 190fcdc..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_hidden_with_title.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                profile="primary_profile_only"
-                initialDisplayState="hidden"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_display.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_display.xml
deleted file mode 100644
index 4c1d00a..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_display.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                initialDisplayState="invalid"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_profile.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_profile.xml
deleted file mode 100644
index 303415b..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_invalid_profile.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="invalid"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_id.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_id.xml
deleted file mode 100644
index 8ace4ea..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_id.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_intent.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_intent.xml
deleted file mode 100644
index 6119e4a..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_intent.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_package.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_package.xml
deleted file mode 100644
index 2b40602..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_package.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_profile.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_profile.xml
deleted file mode 100644
index f54d940..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_profile.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_summary.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_summary.xml
deleted file mode 100644
index 0683f16..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_summary.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_title.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_title.xml
deleted file mode 100644
index 84f90e5..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_no_title.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_hidden_with_work.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_hidden_with_work.xml
deleted file mode 100644
index ad7add5..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_hidden_with_work.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                titleForWork="@string/reference"
-                profile="primary_profile_only"
-                initialDisplayState="hidden"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_with_work.xml b/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_with_work.xml
deleted file mode 100644
index 3ecf802..0000000
--- a/tests/tests/safetycenter/res/xml/config_dynamic_safety_source_primary_with_work.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                titleForWork="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_duplicate_key.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_duplicate_key.xml
deleted file mode 100644
index 9c00d57..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_duplicate_key.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"/>
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_invalid_profile.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_invalid_profile.xml
deleted file mode 100644
index dd85d55..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_invalid_profile.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="invalid"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_id.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_id.xml
deleted file mode 100644
index d57db8e..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_id.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                packageName="package"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_package.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_package.xml
deleted file mode 100644
index d68b557..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_package.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_profile.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_profile.xml
deleted file mode 100644
index 7e7b6ef..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_no_profile.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_display.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_display.xml
deleted file mode 100644
index 1fab839..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_display.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"
-                initialDisplayState="disabled"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_intent.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_intent.xml
deleted file mode 100644
index 9a7fa6b..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_intent.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"
-                intentAction="intent"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_search.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_search.xml
deleted file mode 100644
index b065a38..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_search.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"
-                searchTerms="@string/reference"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_summary.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_summary.xml
deleted file mode 100644
index 7d01001..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_summary.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"
-                summary="@string/reference"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_title.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_title.xml
deleted file mode 100644
index 3b46eea..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_title.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="primary_profile_only"
-                title="@string/reference"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_work.xml b/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_work.xml
deleted file mode 100644
index e501490..0000000
--- a/tests/tests/safetycenter/res/xml/config_issue_only_safety_source_with_work.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id">
-            <issue-only-safety-source
-                id="id"
-                packageName="package"
-                profile="all_profiles"
-                titleForWork="@string/reference"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_mixed_safety_source_duplicate_key.xml b/tests/tests/safetycenter/res/xml/config_mixed_safety_source_duplicate_key.xml
deleted file mode 100644
index e939a9c..0000000
--- a/tests/tests/safetycenter/res/xml/config_mixed_safety_source_duplicate_key.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id1"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="id2"
-            title="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_reference_invalid.xml b/tests/tests/safetycenter/res/xml/config_reference_invalid.xml
deleted file mode 100644
index 7431729..0000000
--- a/tests/tests/safetycenter/res/xml/config_reference_invalid.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="title"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="1"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_center_config_missing.xml b/tests/tests/safetycenter/res/xml/config_safety_center_config_missing.xml
deleted file mode 100644
index 4757916..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_center_config_missing.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<other-root>
-</other-root>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_config_empty.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_config_empty.xml
deleted file mode 100644
index b26ffc0..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_config_empty.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_config_missing.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_config_missing.xml
deleted file mode 100644
index 1254575..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_config_missing.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<safety-center-config>
-    <other-internal-config>
-    </other-internal-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_group_duplicate_id.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_group_duplicate_id.xml
deleted file mode 100644
index 0ce7337..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_group_duplicate_id.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id1"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id2"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_group_empty.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_group_empty.xml
deleted file mode 100644
index a395152..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_group_empty.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_group_invalid_icon.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_group_invalid_icon.xml
deleted file mode 100644
index 42b4c47..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_group_invalid_icon.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference"
-            statelessIconType="invalid">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_id.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_id.xml
deleted file mode 100644
index eaee673..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_id.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_title.xml b/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_title.xml
deleted file mode 100644
index de3ce82..0000000
--- a/tests/tests/safetycenter/res/xml/config_safety_sources_group_no_title.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            summary="@string/reference">
-            <dynamic-safety-source
-                id="id"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_duplicate_key.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_duplicate_key.xml
deleted file mode 100644
index 4fe5e1e..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_duplicate_key.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id1"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="id2"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_invalid_profile.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_invalid_profile.xml
deleted file mode 100644
index 7c135e7..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_invalid_profile.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="invalid"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_id.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_no_id.xml
deleted file mode 100644
index 7b91934..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_id.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_intent.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_no_intent.xml
deleted file mode 100644
index 9e97efb..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_intent.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_profile.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_no_profile.xml
deleted file mode 100644
index 32d23c7..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_profile.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_summary.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_no_summary.xml
deleted file mode 100644
index fa92f0bd..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_summary.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_title.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_no_title.xml
deleted file mode 100644
index 654a486..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_no_title.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml
deleted file mode 100644
index 090bd57..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_broadcast.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                broadcastReceiverClassName="broadcast"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_display.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_display.xml
deleted file mode 100644
index 69c9ca2..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_display.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                initialDisplayState="disabled"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
deleted file mode 100644
index 090554b..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                loggingAllowed="false"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_package.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_package.xml
deleted file mode 100644
index 2a982b4..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_package.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                packageName="package"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_primary_and_work.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_primary_and_work.xml
deleted file mode 100644
index 296e2bc..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_primary_and_work.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                titleForWork="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
deleted file mode 100644
index caaeee6..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                refreshOnPageOpenAllowed="true"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_severity.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_severity.xml
deleted file mode 100644
index a9f5d9b..0000000
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_severity.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="id"
-            title="@string/reference"
-            summary="@string/reference">
-            <static-safety-source
-                id="id"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"
-                maxSeverityLevel="300"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_valid.xml b/tests/tests/safetycenter/res/xml/config_valid.xml
deleted file mode 100644
index e2f9e77..0000000
--- a/tests/tests/safetycenter/res/xml/config_valid.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<safety-center-config>
-    <safety-sources-config>
-        <safety-sources-group
-            id="dynamic"
-            title="@string/reference"
-            summary="@string/reference"
-            statelessIconType="privacy">
-            <dynamic-safety-source
-                id="dynamic_barebone"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-            <dynamic-safety-source
-                id="dynamic_all_optional"
-                packageName="package"
-                title="@string/reference"
-                titleForWork="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="all_profiles"
-                initialDisplayState="disabled"
-                maxSeverityLevel="300"
-                searchTerms="@string/reference"
-                broadcastReceiverClassName="broadcast"
-                loggingAllowed="false"
-                refreshOnPageOpenAllowed="true"/>
-            <dynamic-safety-source
-                id="dynamic_disabled"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                profile="primary_profile_only"
-                initialDisplayState="disabled"/>
-            <dynamic-safety-source
-                id="dynamic_hidden"
-                packageName="package"
-                profile="all_profiles"
-                initialDisplayState="hidden"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="static"
-            title="@string/reference">
-            <static-safety-source
-                id="static_barebone"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-            <static-safety-source
-                id="static_all_optional"
-                title="@string/reference"
-                titleForWork="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="all_profiles"
-                searchTerms="@string/reference"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="issue_only">
-            <issue-only-safety-source
-                id="issue_only_barebone"
-                packageName="package"
-                profile="primary_profile_only"/>
-            <issue-only-safety-source
-                id="issue_only_all_optional"
-                packageName="package"
-                profile="all_profiles"
-                maxSeverityLevel="300"
-                broadcastReceiverClassName="broadcast"
-                loggingAllowed="false"
-                refreshOnPageOpenAllowed="true"/>
-        </safety-sources-group>
-        <safety-sources-group
-            id="mixed"
-            title="@string/reference">
-            <dynamic-safety-source
-                id="mixed_dynamic_barebone"
-                packageName="package"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-            <issue-only-safety-source
-                id="mixed_issue_only_barebone"
-                packageName="package"
-                profile="primary_profile_only"/>
-            <static-safety-source
-                id="mixed_static_barebone"
-                title="@string/reference"
-                summary="@string/reference"
-                intentAction="intent"
-                profile="primary_profile_only"/>
-        </safety-sources-group>
-    </safety-sources-config>
-</safety-center-config>
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
deleted file mode 100644
index d276865..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.Context
-import android.safetycenter.config.ParseException
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.cts.R
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runners.Parameterized
-import org.junit.runner.RunWith
-
-@RunWith(Parameterized::class)
-class ParserConfigInvalidTest {
-    private val context: Context = getApplicationContext()
-
-    data class Params(
-        private val testName: String,
-        val configResourceId: Int,
-        val errorMessage: String,
-        val causeErrorMessage: String?
-    ) {
-        override fun toString() = testName
-    }
-
-    @Parameterized.Parameter
-    lateinit var params: Params
-
-    @Test
-    fun invalidConfig_throws() {
-        val parser = context.resources.getXml(params.configResourceId)
-        val thrown = assertThrows(ParseException::class.java) {
-            SafetyCenterConfig.fromXml(parser)
-        }
-        assertThat(thrown).hasMessageThat().isEqualTo(params.errorMessage)
-        if (params.causeErrorMessage != null) {
-            assertThat(thrown.cause).hasMessageThat().isEqualTo(params.causeErrorMessage)
-        }
-    }
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun parameters() = arrayOf(
-            Params(
-                "ConfigDynamicSafetySourceAllDisabledNoWork",
-                R.xml.config_dynamic_safety_source_all_disabled_no_work,
-                "Element dynamic-safety-source invalid",
-                "Required attribute titleForWork missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceAllNoWork",
-                R.xml.config_dynamic_safety_source_all_no_work,
-                "Element dynamic-safety-source invalid",
-                "Required attribute titleForWork missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceDisabledNoSummary",
-                R.xml.config_dynamic_safety_source_disabled_no_summary,
-                "Element dynamic-safety-source invalid",
-                "Required attribute summary missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceDisabledNoTitle",
-                R.xml.config_dynamic_safety_source_disabled_no_title,
-                "Element dynamic-safety-source invalid",
-                "Required attribute title missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceDuplicateKey",
-                R.xml.config_dynamic_safety_source_duplicate_key,
-                "Element safety-sources-config invalid",
-                "Duplicate id id among safety sources"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceHiddenWithIntent",
-                R.xml.config_dynamic_safety_source_hidden_with_intent,
-                "Element dynamic-safety-source invalid",
-                "Prohibited attribute intentAction present"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceHiddenWithSummary",
-                R.xml.config_dynamic_safety_source_hidden_with_summary,
-                "Element dynamic-safety-source invalid",
-                "Prohibited attribute summary present"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceHiddenWithTitle",
-                R.xml.config_dynamic_safety_source_hidden_with_title,
-                "Element dynamic-safety-source invalid",
-                "Prohibited attribute title present"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceInvalidDisplay",
-                R.xml.config_dynamic_safety_source_invalid_display,
-                "Attribute dynamic-safety-source.initialDisplayState invalid",
-                null
-            ),
-            Params(
-                "ConfigDynamicSafetySourceInvalidProfile",
-                R.xml.config_dynamic_safety_source_invalid_profile,
-                "Attribute dynamic-safety-source.profile invalid",
-                null
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoId",
-                R.xml.config_dynamic_safety_source_no_id,
-                "Element dynamic-safety-source invalid",
-                "Required attribute id missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoIntent",
-                R.xml.config_dynamic_safety_source_no_intent,
-                "Element dynamic-safety-source invalid",
-                "Required attribute intentAction missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoPackage",
-                R.xml.config_dynamic_safety_source_no_package,
-                "Element dynamic-safety-source invalid",
-                "Required attribute packageName missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoProfile",
-                R.xml.config_dynamic_safety_source_no_profile,
-                "Element dynamic-safety-source invalid",
-                "Required attribute profile missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoSummary",
-                R.xml.config_dynamic_safety_source_no_summary,
-                "Element dynamic-safety-source invalid",
-                "Required attribute summary missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourceNoTitle",
-                R.xml.config_dynamic_safety_source_no_title,
-                "Element dynamic-safety-source invalid",
-                "Required attribute title missing"
-            ),
-            Params(
-                "ConfigDynamicSafetySourcePrimaryHiddenWithWork",
-                R.xml.config_dynamic_safety_source_primary_hidden_with_work,
-                "Element dynamic-safety-source invalid",
-                "Prohibited attribute titleForWork present"
-            ),
-            Params(
-                "ConfigDynamicSafetySourcePrimaryWithWork",
-                R.xml.config_dynamic_safety_source_primary_with_work,
-                "Element dynamic-safety-source invalid",
-                "Prohibited attribute titleForWork present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceDuplicateKey",
-                R.xml.config_issue_only_safety_source_duplicate_key,
-                "Element safety-sources-config invalid",
-                "Duplicate id id among safety sources"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceInvalidProfile",
-                R.xml.config_issue_only_safety_source_invalid_profile,
-                "Attribute issue-only-safety-source.profile invalid",
-                null
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceNoId",
-                R.xml.config_issue_only_safety_source_no_id,
-                "Element issue-only-safety-source invalid",
-                "Required attribute id missing"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceNoPackage",
-                R.xml.config_issue_only_safety_source_no_package,
-                "Element issue-only-safety-source invalid",
-                "Required attribute packageName missing"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceNoProfile",
-                R.xml.config_issue_only_safety_source_no_profile,
-                "Element issue-only-safety-source invalid",
-                "Required attribute profile missing"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithDisplay",
-                R.xml.config_issue_only_safety_source_with_display,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute initialDisplayState present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithIntent",
-                R.xml.config_issue_only_safety_source_with_intent,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute intentAction present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithSearch",
-                R.xml.config_issue_only_safety_source_with_search,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute searchTerms present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithSummary",
-                R.xml.config_issue_only_safety_source_with_summary,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute summary present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithTitle",
-                R.xml.config_issue_only_safety_source_with_title,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute title present"
-            ),
-            Params(
-                "ConfigIssueOnlySafetySourceWithWork",
-                R.xml.config_issue_only_safety_source_with_work,
-                "Element issue-only-safety-source invalid",
-                "Prohibited attribute titleForWork present"
-            ),
-            Params(
-                "ConfigMixedSafetySourceDuplicateKey",
-                R.xml.config_mixed_safety_source_duplicate_key,
-                "Element safety-sources-config invalid",
-                "Duplicate id id among safety sources"
-            ),
-            Params(
-                "ConfigReferenceInvalid",
-                R.xml.config_reference_invalid,
-                "Reference title in safety-sources-group.title missing or invalid",
-                null
-            ),
-            Params(
-                "ConfigSafetyCenterConfigMissing",
-                R.xml.config_safety_center_config_missing,
-                "Element safety-center-config missing",
-                null
-            ),
-            Params(
-                "ConfigSafetySourcesConfigEmpty",
-                R.xml.config_safety_sources_config_empty,
-                "Element safety-sources-config invalid",
-                "No safety sources groups present"
-            ),
-            Params(
-                "ConfigSafetySourcesConfigMissing",
-                R.xml.config_safety_sources_config_missing,
-                "Element safety-sources-config missing",
-                null
-            ),
-            Params(
-                "ConfigSafetySourcesGroupDuplicateId",
-                R.xml.config_safety_sources_group_duplicate_id,
-                "Element safety-sources-config invalid",
-                "Duplicate id id among safety sources groups"
-            ),
-            Params(
-                "ConfigSafetySourcesGroupEmpty",
-                R.xml.config_safety_sources_group_empty,
-                "Element safety-sources-group invalid",
-                "Safety sources group empty"
-            ),
-            Params(
-                "ConfigSafetySourcesGroupInvalidIcon",
-                R.xml.config_safety_sources_group_invalid_icon,
-                "Attribute safety-sources-group.statelessIconType invalid",
-                null
-            ),
-            Params(
-                "ConfigSafetySourcesGroupNoId",
-                R.xml.config_safety_sources_group_no_id,
-                "Element safety-sources-group invalid",
-                "Required attribute id missing"
-            ),
-            Params(
-                "ConfigSafetySourcesGroupNoTitle",
-                R.xml.config_safety_sources_group_no_title,
-                "Element safety-sources-group invalid",
-                "Required attribute title missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceDuplicateKey",
-                R.xml.config_static_safety_source_duplicate_key,
-                "Element safety-sources-config invalid",
-                "Duplicate id id among safety sources"
-            ),
-            Params(
-                "ConfigStaticSafetySourceInvalidProfile",
-                R.xml.config_static_safety_source_invalid_profile,
-                "Attribute static-safety-source.profile invalid",
-                null
-            ),
-            Params(
-                "ConfigStaticSafetySourceNoId",
-                R.xml.config_static_safety_source_no_id,
-                "Element static-safety-source invalid",
-                "Required attribute id missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceNoIntent",
-                R.xml.config_static_safety_source_no_intent,
-                "Element static-safety-source invalid",
-                "Required attribute intentAction missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceNoProfile",
-                R.xml.config_static_safety_source_no_profile,
-                "Element static-safety-source invalid",
-                "Required attribute profile missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceNoSummary",
-                R.xml.config_static_safety_source_no_summary,
-                "Element static-safety-source invalid",
-                "Required attribute summary missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceNoTitle",
-                R.xml.config_static_safety_source_no_title,
-                "Element static-safety-source invalid",
-                "Required attribute title missing"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithBroadcast",
-                R.xml.config_static_safety_source_with_broadcast,
-                "Element static-safety-source invalid",
-                "Prohibited attribute broadcastReceiverClassName present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithDisplay",
-                R.xml.config_static_safety_source_with_display,
-                "Element static-safety-source invalid",
-                "Prohibited attribute initialDisplayState present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithLogging",
-                R.xml.config_static_safety_source_with_logging,
-                "Element static-safety-source invalid",
-                "Prohibited attribute loggingAllowed present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithPackage",
-                R.xml.config_static_safety_source_with_package,
-                "Element static-safety-source invalid",
-                "Prohibited attribute packageName present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithPrimaryAndWork",
-                R.xml.config_static_safety_source_with_primary_and_work,
-                "Element static-safety-source invalid",
-                "Prohibited attribute titleForWork present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithRefresh",
-                R.xml.config_static_safety_source_with_refresh,
-                "Element static-safety-source invalid",
-                "Prohibited attribute refreshOnPageOpenAllowed present"
-            ),
-            Params(
-                "ConfigStaticSafetySourceWithSeverity",
-                R.xml.config_static_safety_source_with_severity,
-                "Element static-safety-source invalid",
-                "Prohibited attribute maxSeverityLevel present"
-            )
-        )
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
deleted file mode 100644
index 9190b6d..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.config.cts
-
-import android.content.Context
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.config.SafetySource
-import android.safetycenter.config.SafetySourcesGroup
-import android.safetycenter.cts.R
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class ParserConfigValidTest {
-    private val context: Context = getApplicationContext()
-
-    @Test
-    fun validConfig_matchesExpected() {
-        val parser = context.resources.getXml(R.xml.config_valid)
-        val expected = SafetyCenterConfig.Builder()
-            .addSafetySourcesGroup(SafetySourcesGroup.Builder()
-                .setId("dynamic")
-                .setTitleResId(R.string.reference)
-                .setSummaryResId(R.string.reference)
-                .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                    .setId("dynamic_barebone")
-                    .setPackageName("package")
-                    .setTitleResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                    .setId("dynamic_all_optional")
-                    .setPackageName("package")
-                    .setTitleResId(R.string.reference)
-                    .setTitleForWorkResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_ALL)
-                    .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-                    .setMaxSeverityLevel(300)
-                    .setSearchTermsResId(R.string.reference)
-                    .setBroadcastReceiverClassName("broadcast")
-                    .setLoggingAllowed(false)
-                    .setRefreshOnPageOpenAllowed(true)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                    .setId("dynamic_disabled")
-                    .setPackageName("package")
-                    .setTitleResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                    .setId("dynamic_hidden")
-                    .setPackageName("package")
-                    .setProfile(SafetySource.PROFILE_ALL)
-                    .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
-                    .build())
-                .build())
-            .addSafetySourcesGroup(SafetySourcesGroup.Builder()
-                .setId("static")
-                .setTitleResId(R.string.reference)
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-                    .setId("static_barebone")
-                    .setTitleResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-                    .setId("static_all_optional")
-                    .setTitleResId(R.string.reference)
-                    .setTitleForWorkResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_ALL)
-                    .setSearchTermsResId(R.string.reference)
-                    .build())
-                .build())
-            .addSafetySourcesGroup(SafetySourcesGroup.Builder()
-                .setId("issue_only")
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-                    .setId("issue_only_barebone")
-                    .setPackageName("package")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-                    .setId("issue_only_all_optional")
-                    .setPackageName("package")
-                    .setProfile(SafetySource.PROFILE_ALL)
-                    .setMaxSeverityLevel(300)
-                    .setBroadcastReceiverClassName("broadcast")
-                    .setLoggingAllowed(false)
-                    .setRefreshOnPageOpenAllowed(true)
-                    .build())
-                .build())
-            .addSafetySourcesGroup(SafetySourcesGroup.Builder()
-                .setId("mixed")
-                .setTitleResId(R.string.reference)
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                    .setId("mixed_dynamic_barebone")
-                    .setPackageName("package")
-                    .setTitleResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-                    .setId("mixed_issue_only_barebone")
-                    .setPackageName("package")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-                    .setId("mixed_static_barebone")
-                    .setTitleResId(R.string.reference)
-                    .setSummaryResId(R.string.reference)
-                    .setIntentAction("intent")
-                    .setProfile(SafetySource.PROFILE_PRIMARY)
-                    .build())
-                .build())
-            .build()
-        assertEquals(expected, SafetyCenterConfig.fromXml(parser))
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt
deleted file mode 100644
index 4c57233..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetyCenterConfigTest.kt
+++ /dev/null
@@ -1,82 +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.safetycenter.config.cts
-
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.testers.AnyTester
-import android.safetycenter.testers.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetyCenterConfig]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterConfigTest {
-    @Test
-    fun getSafetySources_returnsSafetySources() {
-        assertThat(BASE.safetySourcesGroups)
-            .containsExactly(
-                SafetySourcesGroupTest.RIGID,
-                SafetySourcesGroupTest.HIDDEN
-            ).inOrder()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(BASE.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetyCenterConfig() {
-        ParcelableTester.assertThatRoundTripReturnsOriginal(BASE, SafetyCenterConfig.CREATOR)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        AnyTester.assertThatRepresentationsAreEqual(BASE, BASE)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val baseAlt = SafetyCenterConfig.Builder()
-            .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
-            .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
-            .build()
-        AnyTester.assertThatRepresentationsAreEqual(BASE, baseAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSafetySources_areNotEqual() {
-        val baseAlt = SafetyCenterConfig.Builder()
-            .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
-            .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(BASE, baseAlt)
-    }
-
-    companion object {
-        private val BASE = SafetyCenterConfig.Builder()
-            .addSafetySourcesGroup(SafetySourcesGroupTest.RIGID)
-            .addSafetySourcesGroup(SafetySourcesGroupTest.HIDDEN)
-            .build()
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
deleted file mode 100644
index f2a96df..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
+++ /dev/null
@@ -1,699 +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.safetycenter.config.cts
-
-import android.content.res.Resources
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetySource
-import android.safetycenter.testers.AnyTester
-import android.safetycenter.testers.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySource]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourceTest {
-    @Test
-    fun getType_returnsType() {
-        assertThat(DYNAMIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-        assertThat(DYNAMIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-        assertThat(DYNAMIC_HIDDEN.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-        assertThat(DYNAMIC_DISABLED.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-        assertThat(STATIC_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-        assertThat(STATIC_ALL_OPTIONAL.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-        assertThat(ISSUE_ONLY_BAREBONE.type).isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.type)
-            .isEqualTo(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-    }
-
-    @Test
-    fun getId_returnsId() {
-        assertThat(DYNAMIC_BAREBONE.id).isEqualTo(DYNAMIC_BAREBONE_ID)
-        assertThat(DYNAMIC_ALL_OPTIONAL.id).isEqualTo(DYNAMIC_ALL_OPTIONAL_ID)
-        assertThat(DYNAMIC_HIDDEN.id).isEqualTo(DYNAMIC_HIDDEN_ID)
-        assertThat(DYNAMIC_DISABLED.id).isEqualTo(DYNAMIC_DISABLED_ID)
-        assertThat(STATIC_BAREBONE.id).isEqualTo(STATIC_BAREBONE_ID)
-        assertThat(STATIC_ALL_OPTIONAL.id).isEqualTo(STATIC_ALL_OPTIONAL_ID)
-        assertThat(ISSUE_ONLY_BAREBONE.id).isEqualTo(ISSUE_ONLY_BAREBONE_ID)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.id).isEqualTo(ISSUE_ONLY_ALL_OPTIONAL_ID)
-    }
-
-    @Test
-    fun getPackageName_returnsPackageNameOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(DYNAMIC_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(DYNAMIC_HIDDEN.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(DYNAMIC_DISABLED.packageName).isEqualTo(PACKAGE_NAME)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.packageName
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.packageName
-        }
-        assertThat(ISSUE_ONLY_BAREBONE.packageName).isEqualTo(PACKAGE_NAME)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.packageName).isEqualTo(PACKAGE_NAME)
-    }
-
-    @Test
-    fun getTitleResId_returnsTitleResIdOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_DISABLED.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
-        assertThat(STATIC_BAREBONE.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(STATIC_ALL_OPTIONAL.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.titleResId
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.titleResId
-        }
-    }
-
-    @Test
-    fun getTitleForWorkResId_returnsTitleForWorkResIdOrThrows() {
-        assertThrows(UnsupportedOperationException::class.java) {
-            DYNAMIC_BAREBONE.titleForWorkResId
-        }
-        assertThat(DYNAMIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
-        assertThrows(UnsupportedOperationException::class.java) {
-            DYNAMIC_DISABLED.titleForWorkResId
-        }
-        assertThat(DYNAMIC_HIDDEN.titleForWorkResId).isEqualTo(Resources.ID_NULL)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.titleForWorkResId
-        }
-        assertThat(STATIC_ALL_OPTIONAL.titleForWorkResId).isEqualTo(REFERENCE_RES_ID)
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.titleForWorkResId
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.titleForWorkResId
-        }
-    }
-
-    @Test
-    fun getSummaryResId_returnsSummaryResIdOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_DISABLED.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
-        assertThat(STATIC_BAREBONE.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(STATIC_ALL_OPTIONAL.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.summaryResId
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.summaryResId
-        }
-    }
-
-    @Test
-    fun getIntentAction_returnsIntentActionOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
-        assertThat(DYNAMIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
-        assertThat(DYNAMIC_DISABLED.intentAction).isNull()
-        assertThat(DYNAMIC_HIDDEN.intentAction).isNull()
-        assertThat(STATIC_BAREBONE.intentAction).isEqualTo(INTENT_ACTION)
-        assertThat(STATIC_ALL_OPTIONAL.intentAction).isEqualTo(INTENT_ACTION)
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.intentAction
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.intentAction
-        }
-    }
-
-    @Test
-    fun getProfile_returnsProfile() {
-        assertThat(DYNAMIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
-        assertThat(DYNAMIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
-        assertThat(DYNAMIC_DISABLED.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
-        assertThat(DYNAMIC_HIDDEN.profile).isEqualTo(SafetySource.PROFILE_ALL)
-        assertThat(STATIC_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
-        assertThat(STATIC_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
-        assertThat(ISSUE_ONLY_BAREBONE.profile).isEqualTo(SafetySource.PROFILE_PRIMARY)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.profile).isEqualTo(SafetySource.PROFILE_ALL)
-    }
-
-    @Test
-    fun getInitialDisplayState_returnsInitialDisplayStateOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.initialDisplayState)
-            .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
-        assertThat(DYNAMIC_ALL_OPTIONAL.initialDisplayState)
-            .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-        assertThat(DYNAMIC_DISABLED.initialDisplayState)
-            .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-        assertThat(DYNAMIC_HIDDEN.initialDisplayState)
-            .isEqualTo(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.initialDisplayState
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.initialDisplayState
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.initialDisplayState
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.initialDisplayState
-        }
-    }
-
-    @Test
-    fun getMaxSeverityLevel_returnsMaxSeverityLevelOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
-        assertThat(DYNAMIC_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
-        assertThat(DYNAMIC_DISABLED.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
-        assertThat(DYNAMIC_HIDDEN.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.maxSeverityLevel
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.maxSeverityLevel
-        }
-        assertThat(ISSUE_ONLY_BAREBONE.maxSeverityLevel).isEqualTo(Integer.MAX_VALUE)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.maxSeverityLevel).isEqualTo(MAX_SEVERITY_LEVEL)
-    }
-
-    @Test
-    fun getSearchTermsResId_returnsSearchTermsResIdOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
-        assertThat(DYNAMIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(DYNAMIC_DISABLED.searchTermsResId).isEqualTo(Resources.ID_NULL)
-        assertThat(DYNAMIC_HIDDEN.searchTermsResId).isEqualTo(Resources.ID_NULL)
-        assertThat(STATIC_BAREBONE.searchTermsResId).isEqualTo(Resources.ID_NULL)
-        assertThat(STATIC_ALL_OPTIONAL.searchTermsResId).isEqualTo(REFERENCE_RES_ID)
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_BAREBONE.searchTermsResId
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            ISSUE_ONLY_ALL_OPTIONAL.searchTermsResId
-        }
-    }
-
-    @Test
-    fun getBroadcastReceiverClassName_returnsBroadcastReceiverClassNameOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.broadcastReceiverClassName).isNull()
-        assertThat(DYNAMIC_ALL_OPTIONAL.broadcastReceiverClassName)
-            .isEqualTo(BROADCAST_RECEIVER_CLASS_NAME)
-        assertThat(DYNAMIC_DISABLED.broadcastReceiverClassName).isNull()
-        assertThat(DYNAMIC_HIDDEN.broadcastReceiverClassName).isNull()
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.broadcastReceiverClassName
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.broadcastReceiverClassName
-        }
-        assertThat(ISSUE_ONLY_BAREBONE.broadcastReceiverClassName).isNull()
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.broadcastReceiverClassName)
-            .isEqualTo(BROADCAST_RECEIVER_CLASS_NAME)
-    }
-
-    @Test
-    fun isLoggingAllowed_returnsLoggingAllowedOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.isLoggingAllowed).isEqualTo(true)
-        assertThat(DYNAMIC_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
-        assertThat(DYNAMIC_DISABLED.isLoggingAllowed).isEqualTo(true)
-        assertThat(DYNAMIC_HIDDEN.isLoggingAllowed).isEqualTo(true)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.isLoggingAllowed
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.isLoggingAllowed
-        }
-        assertThat(ISSUE_ONLY_BAREBONE.isLoggingAllowed).isEqualTo(true)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
-    }
-
-    @Test
-    fun isRefreshOnPageOpenAllowed_returnsRefreshOnPageOpenAllowedOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
-        assertThat(DYNAMIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
-        assertThat(DYNAMIC_DISABLED.isRefreshOnPageOpenAllowed).isEqualTo(false)
-        assertThat(DYNAMIC_HIDDEN.isRefreshOnPageOpenAllowed).isEqualTo(false)
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.isRefreshOnPageOpenAllowed
-        }
-        assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed
-        }
-        assertThat(ISSUE_ONLY_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(DYNAMIC_BAREBONE.describeContents()).isEqualTo(0)
-        assertThat(DYNAMIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
-        assertThat(DYNAMIC_HIDDEN.describeContents()).isEqualTo(0)
-        assertThat(DYNAMIC_DISABLED.describeContents()).isEqualTo(0)
-        assertThat(STATIC_BAREBONE.describeContents()).isEqualTo(0)
-        assertThat(STATIC_ALL_OPTIONAL.describeContents()).isEqualTo(0)
-        assertThat(ISSUE_ONLY_BAREBONE.describeContents()).isEqualTo(0)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySource() {
-        ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_BAREBONE, SafetySource.CREATOR)
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            DYNAMIC_ALL_OPTIONAL,
-            SafetySource.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_HIDDEN, SafetySource.CREATOR)
-        ParcelableTester.assertThatRoundTripReturnsOriginal(DYNAMIC_DISABLED, SafetySource.CREATOR)
-        ParcelableTester.assertThatRoundTripReturnsOriginal(STATIC_BAREBONE, SafetySource.CREATOR)
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            STATIC_ALL_OPTIONAL,
-            SafetySource.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            ISSUE_ONLY_BAREBONE,
-            SafetySource.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            ISSUE_ONLY_ALL_OPTIONAL,
-            SafetySource.CREATOR
-        )
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_BAREBONE, DYNAMIC_BAREBONE)
-        AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, DYNAMIC_ALL_OPTIONAL)
-        AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_HIDDEN, DYNAMIC_HIDDEN)
-        AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_DISABLED, DYNAMIC_DISABLED)
-        AnyTester.assertThatRepresentationsAreEqual(STATIC_BAREBONE, STATIC_BAREBONE)
-        AnyTester.assertThatRepresentationsAreEqual(STATIC_ALL_OPTIONAL, STATIC_ALL_OPTIONAL)
-        AnyTester.assertThatRepresentationsAreEqual(ISSUE_ONLY_BAREBONE, ISSUE_ONLY_BAREBONE)
-        AnyTester.assertThatRepresentationsAreEqual(
-            ISSUE_ONLY_ALL_OPTIONAL,
-            ISSUE_ONLY_ALL_OPTIONAL
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val dynamicAllOptionalCopy = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalCopy)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTypes_areNotEqual() {
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_BAREBONE, STATIC_BAREBONE)
-        AnyTester.assertThatRepresentationsAreNotEqual(STATIC_BAREBONE, ISSUE_ONLY_BAREBONE)
-        AnyTester.assertThatRepresentationsAreNotEqual(ISSUE_ONLY_BAREBONE, DYNAMIC_BAREBONE)
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, STATIC_ALL_OPTIONAL)
-        AnyTester.assertThatRepresentationsAreNotEqual(STATIC_ALL_OPTIONAL, ISSUE_ONLY_ALL_OPTIONAL)
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            ISSUE_ONLY_ALL_OPTIONAL,
-            DYNAMIC_ALL_OPTIONAL
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId("other")
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentPackageNames_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName("other")
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTitleResIds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(-1)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTitleForWorkResIds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(-1)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSummaryResIds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(-1)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIntentActions_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction("other")
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentProfiles_areNotEqual() {
-        val dynamicHiddenAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_HIDDEN_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setProfile(SafetySource.PROFILE_PRIMARY)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_HIDDEN, dynamicHiddenAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentInitialDisplayStates_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_ENABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentMaxSeverityLevel_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(-1)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSearchTermsResIds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(-1)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentBroadcastReceiverClassNames_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName("other")
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentLoggingAlloweds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(true)
-            .setRefreshOnPageOpenAllowed(true)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentRefreshOnPageOpenAlloweds_areNotEqual() {
-        val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-            .setId(DYNAMIC_ALL_OPTIONAL_ID)
-            .setPackageName(PACKAGE_NAME)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setTitleForWorkResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setIntentAction(INTENT_ACTION)
-            .setProfile(SafetySource.PROFILE_ALL)
-            .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-            .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-            .setSearchTermsResId(REFERENCE_RES_ID)
-            .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setLoggingAllowed(false)
-            .setRefreshOnPageOpenAllowed(false)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
-    }
-
-    companion object {
-        private const val PACKAGE_NAME = "package"
-        private const val REFERENCE_RES_ID = 9999
-        private const val INTENT_ACTION = "intent"
-        private const val BROADCAST_RECEIVER_CLASS_NAME = "broadcast"
-        private const val MAX_SEVERITY_LEVEL = 300
-
-        private const val DYNAMIC_BAREBONE_ID = "dynamic_barebone"
-        private const val DYNAMIC_ALL_OPTIONAL_ID = "dynamic_all_optional"
-        private const val DYNAMIC_DISABLED_ID = "dynamic_disabled"
-        private const val DYNAMIC_HIDDEN_ID = "dynamic_hidden"
-        private const val STATIC_BAREBONE_ID = "static_barebone"
-        private const val STATIC_ALL_OPTIONAL_ID = "static_all_optional"
-        private const val ISSUE_ONLY_BAREBONE_ID = "issue_only_barebone"
-        private const val ISSUE_ONLY_ALL_OPTIONAL_ID = "issue_only_all_optional"
-
-        internal val DYNAMIC_BAREBONE =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                .setId(DYNAMIC_BAREBONE_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setTitleResId(REFERENCE_RES_ID)
-                .setSummaryResId(REFERENCE_RES_ID)
-                .setIntentAction(INTENT_ACTION)
-                .setProfile(SafetySource.PROFILE_PRIMARY)
-                .build()
-
-        private val DYNAMIC_ALL_OPTIONAL =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                .setId(DYNAMIC_ALL_OPTIONAL_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setTitleResId(REFERENCE_RES_ID)
-                .setTitleForWorkResId(REFERENCE_RES_ID)
-                .setSummaryResId(REFERENCE_RES_ID)
-                .setIntentAction(INTENT_ACTION)
-                .setProfile(SafetySource.PROFILE_ALL)
-                .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-                .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-                .setSearchTermsResId(REFERENCE_RES_ID)
-                .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-                .setLoggingAllowed(false)
-                .setRefreshOnPageOpenAllowed(true)
-                .build()
-
-        private val DYNAMIC_DISABLED =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                .setId(DYNAMIC_DISABLED_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setTitleResId(REFERENCE_RES_ID)
-                .setSummaryResId(REFERENCE_RES_ID)
-                .setProfile(SafetySource.PROFILE_PRIMARY)
-                .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_DISABLED)
-                .build()
-
-        private val DYNAMIC_HIDDEN =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                .setId(DYNAMIC_HIDDEN_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setProfile(SafetySource.PROFILE_ALL)
-                .setInitialDisplayState(SafetySource.INITIAL_DISPLAY_STATE_HIDDEN)
-                .build()
-
-        internal val STATIC_BAREBONE =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-                .setId(STATIC_BAREBONE_ID)
-                .setTitleResId(REFERENCE_RES_ID)
-                .setSummaryResId(REFERENCE_RES_ID)
-                .setIntentAction(INTENT_ACTION)
-                .setProfile(SafetySource.PROFILE_PRIMARY)
-                .build()
-
-        private val STATIC_ALL_OPTIONAL =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_STATIC)
-                .setId(STATIC_ALL_OPTIONAL_ID)
-                .setTitleResId(REFERENCE_RES_ID)
-                .setTitleForWorkResId(REFERENCE_RES_ID)
-                .setSummaryResId(REFERENCE_RES_ID)
-                .setIntentAction(INTENT_ACTION)
-                .setProfile(SafetySource.PROFILE_ALL)
-                .setSearchTermsResId(REFERENCE_RES_ID)
-                .build()
-
-        internal val ISSUE_ONLY_BAREBONE =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-                .setId(ISSUE_ONLY_BAREBONE_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setProfile(SafetySource.PROFILE_PRIMARY)
-                .build()
-
-        private val ISSUE_ONLY_ALL_OPTIONAL =
-            SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY)
-                .setId(ISSUE_ONLY_ALL_OPTIONAL_ID)
-                .setPackageName(PACKAGE_NAME)
-                .setProfile(SafetySource.PROFILE_ALL)
-                .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
-                .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-                .setLoggingAllowed(false)
-                .setRefreshOnPageOpenAllowed(true)
-                .build()
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt
deleted file mode 100644
index 2e61411..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourcesGroupTest.kt
+++ /dev/null
@@ -1,285 +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.safetycenter.config.cts
-
-import android.content.res.Resources
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetySourcesGroup
-import android.safetycenter.testers.AnyTester
-import android.safetycenter.testers.ParcelableTester
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourcesGroup]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourcesGroupTest {
-    @Test
-    fun getType_returnsType() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.type)
-            .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
-        assertThat(COLLAPSIBLE_WITH_ICON.type)
-            .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
-        assertThat(COLLAPSIBLE_WITH_BOTH.type)
-            .isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_COLLAPSIBLE)
-        assertThat(RIGID.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_RIGID)
-        assertThat(HIDDEN.type).isEqualTo(SafetySourcesGroup.SAFETY_SOURCES_GROUP_TYPE_HIDDEN)
-    }
-
-    @Test
-    fun getId_returnsId() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.id).isEqualTo(COLLAPSIBLE_WITH_SUMMARY_ID)
-        assertThat(COLLAPSIBLE_WITH_ICON.id).isEqualTo(COLLAPSIBLE_WITH_ICON_ID)
-        assertThat(COLLAPSIBLE_WITH_BOTH.id).isEqualTo(COLLAPSIBLE_WITH_BOTH_ID)
-        assertThat(RIGID.id).isEqualTo(RIGID_ID)
-        assertThat(HIDDEN.id).isEqualTo(HIDDEN_ID)
-    }
-
-    @Test
-    fun getTitleResId_returnsTitleResId() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(COLLAPSIBLE_WITH_ICON.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(COLLAPSIBLE_WITH_BOTH.titleResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(RIGID.titleResId).isEqualTo(REFERENCE_RES_ID)
-        // This is not an enforced invariant, titleResId should just be ignored for hidden groups
-        assertThat(HIDDEN.titleResId).isEqualTo(Resources.ID_NULL)
-    }
-
-    @Test
-    fun getSummaryResId_returnsSummaryResId() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(COLLAPSIBLE_WITH_ICON.summaryResId).isEqualTo(Resources.ID_NULL)
-        assertThat(COLLAPSIBLE_WITH_BOTH.summaryResId).isEqualTo(REFERENCE_RES_ID)
-        assertThat(RIGID.summaryResId).isEqualTo(Resources.ID_NULL)
-        // This is not an enforced invariant, summaryResId should just be ignored for hidden groups
-        assertThat(HIDDEN.summaryResId).isEqualTo(Resources.ID_NULL)
-    }
-
-    @Test
-    fun getStatelessIconType_returnsStatelessIconType() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.statelessIconType)
-            .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
-        assertThat(COLLAPSIBLE_WITH_ICON.statelessIconType)
-            .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-        assertThat(COLLAPSIBLE_WITH_BOTH.statelessIconType)
-            .isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-        assertThat(RIGID.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
-        // This is not an enforced invariant
-        // statelessIconType should just be ignored for hidden groups
-        assertThat(HIDDEN.statelessIconType).isEqualTo(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
-    }
-
-    @Test
-    fun getSafetySources_returnsSafetySources() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.safetySources)
-            .containsExactly(SafetySourceTest.DYNAMIC_BAREBONE)
-        assertThat(COLLAPSIBLE_WITH_ICON.safetySources)
-            .containsExactly(SafetySourceTest.STATIC_BAREBONE)
-        assertThat(COLLAPSIBLE_WITH_BOTH.safetySources)
-            .containsExactly(
-                SafetySourceTest.DYNAMIC_BAREBONE,
-                SafetySourceTest.STATIC_BAREBONE,
-                SafetySourceTest.ISSUE_ONLY_BAREBONE
-            ).inOrder()
-        assertThat(RIGID.safetySources).containsExactly(SafetySourceTest.STATIC_BAREBONE)
-        assertThat(HIDDEN.safetySources).containsExactly(SafetySourceTest.ISSUE_ONLY_BAREBONE)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(COLLAPSIBLE_WITH_SUMMARY.describeContents()).isEqualTo(0)
-        assertThat(COLLAPSIBLE_WITH_ICON.describeContents()).isEqualTo(0)
-        assertThat(COLLAPSIBLE_WITH_BOTH.describeContents()).isEqualTo(0)
-        assertThat(RIGID.describeContents()).isEqualTo(0)
-        assertThat(HIDDEN.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourcesGroup() {
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            COLLAPSIBLE_WITH_SUMMARY,
-            SafetySourcesGroup.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            COLLAPSIBLE_WITH_ICON,
-            SafetySourcesGroup.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(
-            COLLAPSIBLE_WITH_BOTH,
-            SafetySourcesGroup.CREATOR
-        )
-        ParcelableTester.assertThatRoundTripReturnsOriginal(RIGID, SafetySourcesGroup.CREATOR)
-        ParcelableTester.assertThatRoundTripReturnsOriginal(HIDDEN, SafetySourcesGroup.CREATOR)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        AnyTester.assertThatRepresentationsAreEqual(
-            COLLAPSIBLE_WITH_SUMMARY,
-            COLLAPSIBLE_WITH_SUMMARY
-        )
-        AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_ICON, COLLAPSIBLE_WITH_ICON)
-        AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_BOTH, COLLAPSIBLE_WITH_BOTH)
-        AnyTester.assertThatRepresentationsAreEqual(RIGID, RIGID)
-        AnyTester.assertThatRepresentationsAreEqual(HIDDEN, HIDDEN)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val collapsibleWithBothCopy = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
-            .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreEqual(COLLAPSIBLE_WITH_BOTH, collapsibleWithBothCopy)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTypes_areNotEqual() {
-        AnyTester.assertThatRepresentationsAreNotEqual(COLLAPSIBLE_WITH_BOTH, RIGID)
-        AnyTester.assertThatRepresentationsAreNotEqual(RIGID, HIDDEN)
-        AnyTester.assertThatRepresentationsAreNotEqual(HIDDEN, COLLAPSIBLE_WITH_BOTH)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
-        val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
-            .setId("other")
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            COLLAPSIBLE_WITH_BOTH,
-            collapsibleWithBothAlt
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTitleResIds_areNotEqual() {
-        val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(-1)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            COLLAPSIBLE_WITH_BOTH,
-            collapsibleWithBothAlt
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSummaryResIds_areNotEqual() {
-        val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(-1)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            COLLAPSIBLE_WITH_BOTH,
-            collapsibleWithBothAlt
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentInitialDisplayStates_areNotEqual() {
-        val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_NONE)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            COLLAPSIBLE_WITH_BOTH,
-            collapsibleWithBothAlt
-        )
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSafetySources_areNotEqual() {
-        val collapsibleWithBothAlt = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
-            .build()
-        AnyTester.assertThatRepresentationsAreNotEqual(
-            COLLAPSIBLE_WITH_BOTH,
-            collapsibleWithBothAlt
-        )
-    }
-
-    companion object {
-        private const val REFERENCE_RES_ID = 9999
-
-        private const val COLLAPSIBLE_WITH_SUMMARY_ID = "collapsible_with_summary"
-        private const val COLLAPSIBLE_WITH_ICON_ID = "collapsible_with_icon"
-        private const val COLLAPSIBLE_WITH_BOTH_ID = "collapsible_with_both"
-        private const val RIGID_ID = "rigid"
-        private const val HIDDEN_ID = "hidden"
-
-        private val COLLAPSIBLE_WITH_SUMMARY = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_SUMMARY_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .build()
-
-        private val COLLAPSIBLE_WITH_ICON = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_ICON_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
-            .build()
-
-        private val COLLAPSIBLE_WITH_BOTH = SafetySourcesGroup.Builder()
-            .setId(COLLAPSIBLE_WITH_BOTH_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .setSummaryResId(REFERENCE_RES_ID)
-            .setStatelessIconType(SafetySourcesGroup.STATELESS_ICON_TYPE_PRIVACY)
-            .addSafetySource(SafetySourceTest.DYNAMIC_BAREBONE)
-            .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
-            .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
-            .build()
-
-        internal val RIGID = SafetySourcesGroup.Builder()
-            .setId(RIGID_ID)
-            .setTitleResId(REFERENCE_RES_ID)
-            .addSafetySource(SafetySourceTest.STATIC_BAREBONE)
-            .build()
-
-        internal val HIDDEN = SafetySourcesGroup.Builder()
-            .setId(HIDDEN_ID)
-            .addSafetySource(SafetySourceTest.ISSUE_ONLY_BAREBONE)
-            .build()
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt
deleted file mode 100644
index 0adf458..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterActivityTest.kt
+++ /dev/null
@@ -1,45 +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.safetycenter.cts
-
-import android.content.Context
-import android.content.Intent
-import android.content.Intent.ACTION_SAFETY_CENTER
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.support.test.uiautomator.By
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterActivityTest {
-    private val context: Context = getApplicationContext()
-
-    @Test
-    fun launchActivity_showsSecurityAndPrivacyTitle() {
-        context.startActivity(
-            Intent(ACTION_SAFETY_CENTER).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-        )
-
-        // CollapsingToolbar title can't be found by text, so using description instead.
-        waitFindObject(By.desc("Security & Privacy"))
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
deleted file mode 100644
index c3c7e726..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.Manifest.permission.MANAGE_SAFETY_CENTER
-import android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE
-import android.safetycenter.SafetyCenterData
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetyEvent
-import android.safetycenter.config.SafetyCenterConfig
-import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import java.util.concurrent.Executor
-
-/**
- * Call {@link SafetyCenterManager#setSafetySourceData} adopting Shell's
- * {@link SEND_SAFETY_CENTER_UPDATE} permission.
- */
-fun SafetyCenterManager.setSafetySourceDataWithPermission(
-    safetySourceId: String,
-    safetySourceData: SafetySourceData,
-    safetyEvent: SafetyEvent
-) =
-    runWithShellPermissionIdentity({
-        setSafetySourceData(safetySourceId, safetySourceData, safetyEvent)
-    }, SEND_SAFETY_CENTER_UPDATE)
-
-/**
- * Call {@link SafetyCenterManager#getSafetySourceData} adopting Shell's
- * {@link SEND_SAFETY_CENTER_UPDATE} permission.
- */
-fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String): SafetySourceData? =
-    callWithShellPermissionIdentity({
-        getSafetySourceData(id)
-    }, SEND_SAFETY_CENTER_UPDATE)
-
-/**
- * Call {@link SafetyCenterManager#isSafetyCenterEnabled} adopting Shell's
- * {@link SEND_SAFETY_CENTER_UPDATE} permission.
- */
-fun SafetyCenterManager.isSafetyCenterEnabledWithPermission(): Boolean =
-    callWithShellPermissionIdentity({
-        isSafetyCenterEnabled
-    }, SEND_SAFETY_CENTER_UPDATE)
-
-/**
- * Call {@link SafetyCenterManager#refreshSafetySources} adopting Shell's
- * {@link MANAGE_SAFETY_CENTER} permission (required for
- * {@link SafetyCenterManager#refreshSafetySources}).
- */
-fun SafetyCenterManager.refreshSafetySourcesWithPermission(refreshReason: Int) =
-    runWithShellPermissionIdentity({
-        refreshSafetySources(refreshReason)
-    }, MANAGE_SAFETY_CENTER)
-
-fun SafetyCenterManager.getSafetyCenterDataWithPermission(): SafetyCenterData =
-    runWithShellPermissionIdentity(::getSafetyCenterData, MANAGE_SAFETY_CENTER)
-
-fun SafetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
-    executor: Executor,
-    listener: OnSafetyCenterDataChangedListener
-) =
-    runWithShellPermissionIdentity({
-        addOnSafetyCenterDataChangedListener(executor, listener)
-    }, MANAGE_SAFETY_CENTER)
-
-fun SafetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(
-    listener: OnSafetyCenterDataChangedListener
-) =
-    runWithShellPermissionIdentity({
-        removeOnSafetyCenterDataChangedListener(listener)
-    }, MANAGE_SAFETY_CENTER)
-
-/**
- * Call {@link SafetyCenterManager#clearAllSafetySourceData} adopting Shell's
- * {@link MANAGE_SAFETY_CENTER} permission.
- */
-fun SafetyCenterManager.clearAllSafetySourceDataWithPermission() =
-    runWithShellPermissionIdentity({
-        clearAllSafetySourceData()
-    }, MANAGE_SAFETY_CENTER)
-
-fun SafetyCenterManager.setSafetyCenterConfigOverrideWithPermission(
-    safetyCenterConfig: SafetyCenterConfig
-) =
-    runWithShellPermissionIdentity({
-        setSafetyCenterConfigOverride(safetyCenterConfig)
-    }, MANAGE_SAFETY_CENTER)
-
-fun SafetyCenterManager.clearSafetyCenterConfigOverrideWithPermission() =
-    runWithShellPermissionIdentity({
-        clearSafetyCenterConfigOverride()
-    }, MANAGE_SAFETY_CENTER)
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
deleted file mode 100644
index 5d3df89..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
+++ /dev/null
@@ -1,251 +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.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterData
-import android.safetycenter.SafetyCenterEntry
-import android.safetycenter.SafetyCenterEntryGroup
-import android.safetycenter.SafetyCenterEntryOrGroup
-import android.safetycenter.SafetyCenterIssue
-import android.safetycenter.SafetyCenterStaticEntry
-import android.safetycenter.SafetyCenterStaticEntryGroup
-import android.safetycenter.SafetyCenterStatus
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterDataTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    val status1 = SafetyCenterStatus.Builder()
-            .setTitle("This is my title")
-            .setSummary("This is my summary")
-            .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
-            .build()
-    val status2 = SafetyCenterStatus.Builder()
-            .setTitle("This is also my title")
-            .setSummary("This is also my summary")
-            .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-            .build()
-
-    val issue1 = SafetyCenterIssue.Builder("iSsUe_iD_oNe")
-            .setTitle("An issue title")
-            .setSummary("An issue summary")
-            .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
-            .build()
-    val issue2 = SafetyCenterIssue.Builder("iSsUe_iD_tWo")
-            .setTitle("Another issue title")
-            .setSummary("Another issue summary")
-            .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
-            .build()
-
-    val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
-            .setTitle("An entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-            .build()
-    val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
-            .setTitle("Another entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .build()
-
-    val entryGroup1 = SafetyCenterEntryGroup.Builder("eNtRy_gRoUp_iD")
-            .setTitle("An entry group title")
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .setEntries(listOf(entry2))
-            .build()
-
-    val entryOrGroup1 = SafetyCenterEntryOrGroup(entry1)
-    val entryOrGroup2 = SafetyCenterEntryOrGroup(entryGroup1)
-
-    val staticEntry1 = SafetyCenterStaticEntry(
-            "A static entry title",
-            "A static entry summary",
-            pendingIntent)
-    val staticEntry2 = SafetyCenterStaticEntry(
-            "Another static entry title",
-            "Another static entry summary",
-            pendingIntent)
-
-    val staticEntryGroup1 = SafetyCenterStaticEntryGroup(
-            "A static entry group title", listOf(staticEntry1))
-    val staticEntryGroup2 = SafetyCenterStaticEntryGroup(
-            "Another static entry group title", listOf(staticEntry2))
-
-    val data1 = SafetyCenterData(
-            status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-    val data2 = SafetyCenterData(
-            status2, listOf(issue2), listOf(entryOrGroup2), listOf(staticEntryGroup2))
-
-    @Test
-    fun getStatus_returnsStatus() {
-        assertThat(data1.status).isEqualTo(status1)
-        assertThat(data2.status).isEqualTo(status2)
-    }
-
-    @Test
-    fun getIssues_returnsIssues() {
-        assertThat(data1.issues).containsExactly(issue1)
-        assertThat(data2.issues).containsExactly(issue2)
-    }
-
-    @Test
-    fun getIssues_mutationsAreNotReflected() {
-        val mutatedIssues = data1.issues
-        mutatedIssues.add(issue2)
-
-        assertThat(mutatedIssues).containsExactly(issue1, issue2)
-        assertThat(data1.issues).doesNotContain(issue2)
-    }
-
-    @Test
-    fun getEntriesOrGroups_returnsEntriesOrGroups() {
-        assertThat(data1.entriesOrGroups).containsExactly(entryOrGroup1)
-        assertThat(data2.entriesOrGroups).containsExactly(entryOrGroup2)
-    }
-
-    @Test
-    fun getEntriesOrGroups_mutationsAreNotReflected() {
-        val mutatedEntriesOrGroups = data1.entriesOrGroups
-        mutatedEntriesOrGroups.add(entryOrGroup2)
-
-        assertThat(mutatedEntriesOrGroups).containsExactly(entryOrGroup1, entryOrGroup2)
-        assertThat(data1.entriesOrGroups).doesNotContain(entryOrGroup2)
-    }
-
-    @Test
-    fun getStaticEntryGroups_returnsStaticEntryGroups() {
-        assertThat(data1.staticEntryGroups).containsExactly(staticEntryGroup1)
-        assertThat(data2.staticEntryGroups).containsExactly(staticEntryGroup2)
-    }
-
-    @Test
-    fun getStaticEntryGroups_mutationsAreNotReflected() {
-        val mutatedStaticEntryGroups = data1.staticEntryGroups
-        mutatedStaticEntryGroups.add(staticEntryGroup2)
-
-        assertThat(mutatedStaticEntryGroups).containsExactly(staticEntryGroup1, staticEntryGroup2)
-        assertThat(data1.staticEntryGroups).doesNotContain(staticEntryGroup2)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(data1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel: Parcel = Parcel.obtain()
-
-        data1.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterData.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(data1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(data1).isEqualTo(data1)
-        assertThat(data1.hashCode()).isEqualTo(data1.hashCode())
-        assertThat(data1.toString()).isEqualTo(data1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val data = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-        val equivalentData = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
-        assertThat(data).isEqualTo(equivalentData)
-        assertThat(data.hashCode()).isEqualTo(equivalentData.hashCode())
-        assertThat(data.toString()).isEqualTo(equivalentData.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_withEmptyLists_equalByValue_areEqual() {
-        val data = SafetyCenterData(status1, listOf(), listOf(), listOf())
-        val equivalentData = SafetyCenterData(status1, listOf(), listOf(), listOf())
-
-        assertThat(data).isEqualTo(equivalentData)
-        assertThat(data.hashCode()).isEqualTo(equivalentData.hashCode())
-        assertThat(data.toString()).isEqualTo(equivalentData.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentStatuses_areNotEqual() {
-        val data = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-        val differentData = SafetyCenterData(
-                status2, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
-        assertThat(data).isNotEqualTo(differentData)
-        assertThat(data.toString()).isNotEqualTo(differentData.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentIssues_areNotEqual() {
-        val data = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-        val differentData = SafetyCenterData(
-                status1, listOf(issue2), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-
-        assertThat(data).isNotEqualTo(differentData)
-        assertThat(data.toString()).isNotEqualTo(differentData.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEntriesOrGroups_areNotEqual() {
-        val data = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-        val differentData = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup2), listOf(staticEntryGroup1))
-
-        assertThat(data).isNotEqualTo(differentData)
-        assertThat(data.toString()).isNotEqualTo(differentData.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentStaticEntryGroups_areNotEqual() {
-        val data = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup1))
-        val differentData = SafetyCenterData(
-                status1, listOf(issue1), listOf(entryOrGroup1), listOf(staticEntryGroup2))
-
-        assertThat(data).isNotEqualTo(differentData)
-        assertThat(data.toString()).isNotEqualTo(differentData.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt
deleted file mode 100644
index 4140e40..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryGroupTest.kt
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterEntry
-import android.safetycenter.SafetyCenterEntryGroup
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterEntryGroupTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
-            .setTitle("An entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-            .build()
-    val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
-            .setTitle("Another entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .build()
-
-    val groupId1 = "gRoUp_iD_oNe"
-    val groupId2 = "gRoUp_iD_tWo"
-
-    val entryGroup1 = SafetyCenterEntryGroup.Builder(groupId1)
-            .setTitle("A group title")
-            .setSummary("A group summary")
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-            .setEntries(listOf(entry1))
-            .build()
-    val entryGroup2 = SafetyCenterEntryGroup.Builder(groupId2)
-            .setTitle("Another group title")
-            .setSummary("Another group summary")
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .setEntries(listOf(entry2))
-            .build()
-
-    @Test
-    fun getId_returnsId() {
-        assertThat(entryGroup1.id).isEqualTo(groupId1)
-        assertThat(entryGroup2.id).isEqualTo(groupId2)
-    }
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setTitle("title one").build().title)
-                .isEqualTo("title one")
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setTitle("title two").build().title)
-                .isEqualTo("title two")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary("one").build().summary)
-                .isEqualTo("one")
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary("two").build().summary)
-                .isEqualTo("two")
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1).setSummary(null).build().summary)
-                .isNull()
-    }
-
-    @Test
-    fun getSeverityLevel_returnsSeverityLevel() {
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_NONE)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_NONE)
-    }
-
-    @Test
-    fun getSeverityNoneIconType_returnsSeverityNoneIconType() {
-        assertThat(entryGroup1.severityNoneIconType)
-                .isEqualTo(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_NO_ICON)
-        assertThat(SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .build()
-                .severityNoneIconType)
-                .isEqualTo(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-    }
-
-    @Test
-    fun getEntries_returnsEntries() {
-        assertThat(entryGroup1.entries).containsExactly(entry1)
-        assertThat(entryGroup2.entries).containsExactly(entry2)
-    }
-
-    @Test
-    fun getEntries_mutationsAreNotReflected() {
-        val mutatedEntries = entryGroup1.entries
-        mutatedEntries.add(entry2)
-
-        assertThat(mutatedEntries).containsExactly(entry1, entry2)
-        assertThat(entryGroup1.entries).doesNotContain(entry2)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(entryGroup1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        entryGroup1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetyCenterEntryGroup.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(entryGroup1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(entryGroup1).isEqualTo(entryGroup1)
-        assertThat(entryGroup1.hashCode()).isEqualTo(entryGroup1.hashCode())
-        assertThat(entryGroup1.toString()).isEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val entry = SafetyCenterEntryGroup.Builder(groupId1)
-                .setTitle("A group title")
-                .setSummary("A group summary")
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-                .setEntries(listOf(entry1))
-                .build()
-        val equivalentEntry = SafetyCenterEntryGroup.Builder(groupId1)
-                .setTitle("A group title")
-                .setSummary("A group summary")
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-                .setEntries(listOf(entry1))
-                .build()
-
-        assertThat(entry).isEqualTo(equivalentEntry)
-        assertThat(entry.hashCode()).isEqualTo(equivalentEntry.hashCode())
-        assertThat(entry.toString()).isEqualTo(equivalentEntry.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
-        val equivalentToEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1).build()
-
-        assertThat(equivalentToEntryGroup1).isEqualTo(entryGroup1)
-        assertThat(equivalentToEntryGroup1.hashCode()).isEqualTo(entryGroup1.hashCode())
-        assertThat(equivalentToEntryGroup1.toString()).isEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentIds_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setId("different!")
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentTitles_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setTitle("different!")
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSummaries_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSummary("different!")
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSeverityLevels_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSeverityNoneIconTypes_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEntries_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setEntries(listOf(entry2))
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEntries_emptyList_areNotEqual() {
-        val differentFromEntryGroup1 = SafetyCenterEntryGroup.Builder(entryGroup1)
-                .setEntries(listOf())
-                .build()
-
-        assertThat(differentFromEntryGroup1).isNotEqualTo(entryGroup1)
-        assertThat(differentFromEntryGroup1.toString()).isNotEqualTo(entryGroup1.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt
deleted file mode 100644
index 193643b..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryOrGroupTest.kt
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterEntry
-import android.safetycenter.SafetyCenterEntryGroup
-import android.safetycenter.SafetyCenterEntryOrGroup
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterEntryOrGroupTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    val entry1 = SafetyCenterEntry.Builder("eNtRy_iD_OnE")
-            .setTitle("An entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-            .build()
-    val entry2 = SafetyCenterEntry.Builder("eNtRy_iD_TwO")
-            .setTitle("Another entry title")
-            .setPendingIntent(pendingIntent)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .build()
-
-    val entryGroup1 = SafetyCenterEntryGroup.Builder("gRoUp_iD_oNe")
-            .setTitle("A group title")
-            .setSummary("A group summary")
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-            .setEntries(listOf(entry1))
-            .build()
-    val entryGroup2 = SafetyCenterEntryGroup.Builder("gRoUp_iD_tWo")
-            .setTitle("Another group title")
-            .setSummary("Another group summary")
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-            .setEntries(listOf(entry2))
-            .build()
-
-    val entryOrGroupWithEntry = SafetyCenterEntryOrGroup(entry1)
-    val entryOrGroupWithGroup = SafetyCenterEntryOrGroup(entryGroup1)
-
-    @Test
-    fun getEntry_returnsEntry() {
-        assertThat(entryOrGroupWithEntry.entry).isEqualTo(entry1)
-    }
-
-    @Test
-    fun getEntry_returnsEntry_whenNull() {
-        assertThat(entryOrGroupWithGroup.entry).isNull()
-    }
-
-    @Test
-    fun getEntryGroup_returnsEntryGroup() {
-        assertThat(entryOrGroupWithGroup.entryGroup).isEqualTo(entryGroup1)
-    }
-
-    @Test
-    fun getEntryGroup_returnsEntryGroup_whenNull() {
-        assertThat(entryOrGroupWithEntry.entryGroup).isNull()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(entryOrGroupWithEntry.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_withEntry_returnsEquivalentObject() {
-        runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
-                entryOrGroupWithEntry)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_withGroup_returnsEquivalentObject() {
-        runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
-                entryOrGroupWithGroup)
-    }
-
-    fun runCreateFromParcel_withWriteToParcel_withGroup_returnsEquivalentObjectTest(
-        entryOrGroup: SafetyCenterEntryOrGroup
-    ) {
-        val parcel: Parcel = Parcel.obtain()
-
-        entryOrGroup.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterEntryOrGroup.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(entryOrGroup)
-    }
-
-    @Test
-    fun equals_hashCode_toString_whenEqualByReference_areEqual() {
-        assertThat(entryOrGroupWithEntry).isEqualTo(entryOrGroupWithEntry)
-        assertThat(entryOrGroupWithEntry.hashCode()).isEqualTo(entryOrGroupWithEntry.hashCode())
-        assertThat(entryOrGroupWithEntry.toString()).isEqualTo(entryOrGroupWithEntry.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_whenEqualByValue_withEntry_areEqual() {
-        val entryOrGroup = SafetyCenterEntryOrGroup(entry1)
-        val equivalentEntryOrGroup = SafetyCenterEntryOrGroup(entry1)
-
-        assertThat(entryOrGroup).isEqualTo(equivalentEntryOrGroup)
-        assertThat(entryOrGroup.hashCode()).isEqualTo(equivalentEntryOrGroup.hashCode())
-        assertThat(entryOrGroup.toString()).isEqualTo(equivalentEntryOrGroup.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_whenEqualByValue_withGroup_areEqual() {
-        val entryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
-        val equivalentEntryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
-
-        assertThat(entryOrGroup).isEqualTo(equivalentEntryOrGroup)
-        assertThat(entryOrGroup.hashCode()).isEqualTo(equivalentEntryOrGroup.hashCode())
-        assertThat(entryOrGroup.toString()).isEqualTo(equivalentEntryOrGroup.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEntryAndGroup_areNotEqual() {
-        assertThat(entryOrGroupWithEntry).isNotEqualTo(entryOrGroupWithGroup)
-        assertThat(entryOrGroupWithEntry.toString()).isNotEqualTo(entryOrGroupWithGroup.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEntries_areNotEqual() {
-        val entryOrGroup = SafetyCenterEntryOrGroup(entry1)
-        val differentEntryOrGroup = SafetyCenterEntryOrGroup(entry2)
-
-        assertThat(entryOrGroup).isNotEqualTo(differentEntryOrGroup)
-        assertThat(entryOrGroup.toString()).isNotEqualTo(differentEntryOrGroup.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentGroups_areNotEqual() {
-        val entryOrGroup = SafetyCenterEntryOrGroup(entryGroup1)
-        val differentEntryOrGroup = SafetyCenterEntryOrGroup(entryGroup2)
-
-        assertThat(entryOrGroup).isNotEqualTo(differentEntryOrGroup)
-        assertThat(entryOrGroup.toString()).isNotEqualTo(differentEntryOrGroup.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt
deleted file mode 100644
index 94fea00..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterEntryTest.kt
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterEntry
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterEntryTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent1 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-    private val pendingIntent2 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Different Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    private val iconAction1 = SafetyCenterEntry.IconAction(
-            SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-    private val iconAction2 = SafetyCenterEntry.IconAction(
-            SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
-
-    private val entry1 = SafetyCenterEntry.Builder("eNtRy_iD")
-            .setTitle("a title")
-            .setSummary("a summary")
-            .setPendingIntent(pendingIntent1)
-            .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
-            .setIconAction(iconAction1)
-            .build()
-
-    @Test
-    fun getId_returnsId() {
-        assertThat(SafetyCenterEntry.Builder(entry1).setId("id_one").build().id)
-                .isEqualTo("id_one")
-        assertThat(SafetyCenterEntry.Builder(entry1).setId("id_two").build().id)
-                .isEqualTo("id_two")
-    }
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(SafetyCenterEntry.Builder(entry1).setTitle("a title").build().title)
-                .isEqualTo("a title")
-        assertThat(SafetyCenterEntry.Builder(entry1).setTitle("another title").build().title)
-                .isEqualTo("another title")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        assertThat(SafetyCenterEntry.Builder(entry1).setSummary("a summary").build().summary)
-                .isEqualTo("a summary")
-        assertThat(SafetyCenterEntry.Builder(entry1).setSummary("another summary").build().summary)
-                .isEqualTo("another summary")
-        assertThat(SafetyCenterEntry.Builder(entry1).setSummary(null).build().summary)
-                .isNull()
-    }
-
-    @Test
-    fun getSeverityLevel_returnsSeverityLevel() {
-        assertThat(SafetyCenterEntry.Builder(entry1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION)
-        assertThat(SafetyCenterEntry.Builder(entry1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-    }
-
-    @Test
-    fun getSeverityNoneIconType_returnsSeverityNoneIconType() {
-        assertThat(entry1.severityNoneIconType).isEqualTo(
-                SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_NO_ICON)
-        assertThat(SafetyCenterEntry.Builder(entry1)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .build()
-                .severityNoneIconType)
-                .isEqualTo(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-    }
-
-    @Test
-    fun isEnabled_returnsIsEnabled() {
-        assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(true).build().isEnabled)
-                .isTrue()
-        assertThat(SafetyCenterEntry.Builder(entry1).setEnabled(false).build().isEnabled)
-                .isFalse()
-    }
-
-    @Test
-    fun isEnabled_defaultTrue() {
-        assertThat(SafetyCenterEntry.Builder("eNtRy_iD")
-                .setTitle("a title")
-                .setPendingIntent(pendingIntent1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN)
-                .build()
-                .isEnabled)
-                .isTrue()
-    }
-
-    @Test
-    fun getPendingIntent_returnsPendingIntent() {
-        assertThat(SafetyCenterEntry.Builder(entry1)
-                .setPendingIntent(pendingIntent1)
-                .build()
-                .pendingIntent)
-                .isEqualTo(pendingIntent1)
-        assertThat(SafetyCenterEntry.Builder(entry1)
-                .setPendingIntent(pendingIntent2)
-                .build()
-                .pendingIntent)
-                .isEqualTo(pendingIntent2)
-    }
-
-    @Test
-    fun getIconAction_returnsIconAction() {
-        assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(iconAction1).build().iconAction)
-                .isEqualTo(iconAction1)
-        assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(iconAction2).build().iconAction)
-                .isEqualTo(iconAction2)
-        assertThat(SafetyCenterEntry.Builder(entry1).setIconAction(null).build().iconAction)
-                .isNull()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(entry1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        entry1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetyCenterEntry.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(entry1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(entry1).isEqualTo(entry1)
-        assertThat(entry1.hashCode()).isEqualTo(entry1.hashCode())
-        assertThat(entry1.toString()).isEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val entry = SafetyCenterEntry.Builder("id")
-                .setTitle("a title")
-                .setSummary("a summary")
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .setPendingIntent(pendingIntent1)
-                .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
-                .build()
-        val equivalentEntry = SafetyCenterEntry.Builder("id")
-                .setTitle("a title")
-                .setSummary("a summary")
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .setPendingIntent(pendingIntent1)
-                .setIconAction(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent2)
-                .build()
-
-        assertThat(entry).isEqualTo(equivalentEntry)
-        assertThat(entry.hashCode()).isEqualTo(equivalentEntry.hashCode())
-        assertThat(entry.toString()).isEqualTo(equivalentEntry.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
-        val copyOfEntry1 = SafetyCenterEntry.Builder(entry1).build()
-
-        assertThat(copyOfEntry1).isEqualTo(entry1)
-        assertThat(copyOfEntry1.hashCode()).isEqualTo(entry1.hashCode())
-        assertThat(copyOfEntry1.toString()).isEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentIds_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setId("a different id")
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentTitles_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setTitle("a different title")
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSummaries_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setSummary("a different summary")
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSeverityLevels_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setSeverityLevel(SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSeverityNoneIconTypes_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setSeverityNoneIconType(SafetyCenterEntry.SEVERITY_NONE_ICON_TYPE_PRIVACY)
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentEnabledValues_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setEnabled(false)
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentPendingIntents_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setPendingIntent(pendingIntent2)
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentIconActions_areNotEqual() {
-        val differentFromEntry1 = SafetyCenterEntry.Builder(entry1)
-                .setIconAction(iconAction2)
-                .build()
-
-        assertThat(differentFromEntry1).isNotEqualTo(entry1)
-        assertThat(differentFromEntry1.toString()).isNotEqualTo(entry1.toString())
-    }
-
-    @Test
-    fun iconAction_getType_returnsType() {
-        assertThat(SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-                .type)
-                .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR)
-        assertThat(SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent1)
-                .type)
-                .isEqualTo(SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO)
-    }
-
-    @Test
-    fun iconAction_getPendingIntent_returnsPendingIntent() {
-        assertThat(SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-                .pendingIntent)
-                .isEqualTo(pendingIntent1)
-        assertThat(SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent2)
-                .pendingIntent)
-                .isEqualTo(pendingIntent2)
-    }
-
-    @Test
-    fun iconAction_describeContents_returns0() {
-        assertThat(iconAction1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun iconAction_createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        iconAction1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetyCenterEntry.IconAction.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(iconAction1)
-    }
-
-    @Test
-    fun iconAction_equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(iconAction1).isEqualTo(iconAction1)
-        assertThat(iconAction1.hashCode()).isEqualTo(iconAction1.hashCode())
-        assertThat(iconAction1.toString()).isEqualTo(iconAction1.toString())
-    }
-
-    @Test
-    fun iconAction_equals_hashCode_toString_equalByValue_areEqual() {
-        val iconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-        val equivalentIconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-
-        assertThat(iconAction).isEqualTo(equivalentIconAction)
-        assertThat(iconAction.hashCode()).isEqualTo(equivalentIconAction.hashCode())
-        assertThat(iconAction.toString()).isEqualTo(equivalentIconAction.toString())
-    }
-
-    @Test
-    fun iconAction_equals_toString_differentTypes_areNotEqual() {
-        val iconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-        val differentIconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_INFO, pendingIntent1)
-
-        assertThat(iconAction).isNotEqualTo(differentIconAction)
-        assertThat(iconAction.toString()).isNotEqualTo(differentIconAction.toString())
-    }
-
-    @Test
-    fun intentAction_equals_toString_differentPendingIntents_areNotEqual() {
-        val iconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent1)
-        val differentIconAction = SafetyCenterEntry.IconAction(
-                SafetyCenterEntry.IconAction.ICON_ACTION_TYPE_GEAR, pendingIntent2)
-
-        assertThat(iconAction).isNotEqualTo(differentIconAction)
-        assertThat(iconAction.toString()).isNotEqualTo(differentIconAction.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorTest.kt
deleted file mode 100644
index 06fd6d5..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterErrorTest.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.os.Parcel
-import android.safetycenter.SafetyCenterError
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class SafetyCenterErrorTest {
-
-    val error1 = SafetyCenterError("an error message")
-    val error2 = SafetyCenterError("another error message")
-
-    @Test
-    fun getErrorMessage_returnsErrorMessage() {
-        assertThat(error1.errorMessage).isEqualTo("an error message")
-        assertThat(error2.errorMessage).isEqualTo("another error message")
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(error1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        error1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetyCenterError.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(error1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(error1).isEqualTo(error1)
-        assertThat(error1.hashCode()).isEqualTo(error1.hashCode())
-        assertThat(error1.toString()).isEqualTo(error1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val error = SafetyCenterError("an error message")
-        val equivalentError = SafetyCenterError("an error message")
-
-        assertThat(error).isEqualTo(equivalentError)
-        assertThat(error.hashCode()).isEqualTo(equivalentError.hashCode())
-        assertThat(error.toString()).isEqualTo(equivalentError.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentErrorMessages_areNotEqual() {
-        val error = SafetyCenterError("an error message")
-        val differentError = SafetyCenterError("a different error message")
-
-        assertThat(error).isNotEqualTo(differentError)
-        assertThat(error.toString()).isNotEqualTo(differentError.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
deleted file mode 100644
index a842804..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterIssue
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterIssueTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent1 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-    private val pendingIntent2 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Different Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    val action1 = SafetyCenterIssue.Action.Builder("action_id_1")
-            .setLabel("an action")
-            .setPendingIntent(pendingIntent1)
-            .setResolving(true)
-            .setInFlight(true)
-            .setSuccessMessage("a success message")
-            .build()
-    val action2 = SafetyCenterIssue.Action.Builder("action_id_2")
-            .setLabel("another action")
-            .setPendingIntent(pendingIntent2)
-            .setResolving(false)
-            .setInFlight(false)
-            .build()
-
-    val issue1 = SafetyCenterIssue.Builder("issue_id")
-            .setTitle("Everything's good")
-            .setSubtitle("In the neighborhood")
-            .setSummary("Please acknowledge this")
-            .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
-            .setDismissible(true)
-            .setShouldConfirmDismissal(true)
-            .setActions(listOf(action1))
-            .build()
-
-    val issueWithRequiredFieldsOnly = SafetyCenterIssue.Builder("issue_id")
-            .setTitle("Everything's good")
-            .setSummary("Please acknowledge this")
-            .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
-            .build()
-
-    @Test
-    fun getId_returnsId() {
-        assertThat(SafetyCenterIssue.Builder(issue1).setId("an id").build().id)
-                .isEqualTo("an id")
-        assertThat(SafetyCenterIssue.Builder(issue1).setId("another id").build().id)
-                .isEqualTo("another id")
-    }
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(SafetyCenterIssue.Builder(issue1).setTitle("a title").build().title)
-                .isEqualTo("a title")
-        assertThat(SafetyCenterIssue.Builder(issue1).setTitle("another title").build().title)
-                .isEqualTo("another title")
-    }
-
-    @Test
-    fun getSubtitle_returnsSubtitle() {
-        assertThat(SafetyCenterIssue.Builder(issue1).setSubtitle("a subtitle").build().subtitle)
-                .isEqualTo("a subtitle")
-        assertThat(
-                SafetyCenterIssue.Builder(issue1).setSubtitle("another subtitle").build().subtitle)
-                .isEqualTo("another subtitle")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        assertThat(SafetyCenterIssue.Builder(issue1).setSummary("a summary").build().summary)
-                .isEqualTo("a summary")
-        assertThat(SafetyCenterIssue.Builder(issue1).setSummary("another summary").build().summary)
-                .isEqualTo("another summary")
-    }
-
-    @Test
-    fun getSeverityLevel_returnsSeverityLevel() {
-        assertThat(SafetyCenterIssue.Builder(issue1)
-                .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
-        assertThat(SafetyCenterIssue.Builder(issue1)
-                .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
-                .build()
-                .severityLevel)
-                .isEqualTo(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
-    }
-
-    @Test
-    fun isDismissible_returnsIsDismissible() {
-        assertThat(SafetyCenterIssue.Builder(issue1).setDismissible(true).build().isDismissible)
-                .isTrue()
-        assertThat(SafetyCenterIssue.Builder(issue1).setDismissible(false).build().isDismissible)
-                .isFalse()
-    }
-
-    @Test
-    fun isDismissible_defaultsToTrue() {
-        assertThat(issueWithRequiredFieldsOnly.isDismissible).isTrue()
-    }
-
-    @Test
-    fun shouldConfirmDismissal_returnsShouldConfirmDismissal() {
-        assertThat(SafetyCenterIssue.Builder(issue1)
-                .setShouldConfirmDismissal(true)
-                .build()
-                .shouldConfirmDismissal())
-                .isTrue()
-        assertThat(SafetyCenterIssue.Builder(issue1)
-                .setShouldConfirmDismissal(false)
-                .build()
-                .shouldConfirmDismissal())
-                .isFalse()
-    }
-
-    @Test
-    fun shouldConfirmDismissal_defaultsToTrue() {
-        assertThat(issueWithRequiredFieldsOnly.shouldConfirmDismissal()).isTrue()
-    }
-
-    @Test
-    fun getActions_returnsActions() {
-        assertThat(SafetyCenterIssue.Builder(issue1)
-                .setActions(listOf(action1, action2))
-                .build().actions)
-                .containsExactly(action1, action2)
-        assertThat(SafetyCenterIssue.Builder(issue1).setActions(listOf(action2)).build().actions)
-                .containsExactly(action2)
-        assertThat(SafetyCenterIssue.Builder(issue1).setActions(listOf()).build().actions)
-                .isEmpty()
-    }
-
-    @Test
-    fun getActions_mutationsAreNotReflected() {
-        val mutatedActions = issue1.actions
-        mutatedActions.add(action2)
-
-        assertThat(mutatedActions).containsExactly(action1, action2)
-        assertThat(issue1.actions).doesNotContain(action2)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(issue1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        issue1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetyCenterIssue.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(issue1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(issue1).isEqualTo(issue1)
-        assertThat(issue1.hashCode()).isEqualTo(issue1.hashCode())
-        assertThat(issue1.toString()).isEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val issue = SafetyCenterIssue.Builder("an id")
-                .setTitle("a title")
-                .setSubtitle("In the neighborhood")
-                .setSummary("Please acknowledge this")
-                .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
-                .setActions(listOf(action1))
-                .build()
-        val equivalentIssue = SafetyCenterIssue.Builder("an id")
-                .setTitle("a title")
-                .setSubtitle("In the neighborhood")
-                .setSummary("Please acknowledge this")
-                .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK)
-                .setActions(listOf(action1))
-                .build()
-
-        assertThat(issue).isEqualTo(equivalentIssue)
-        assertThat(issue.hashCode()).isEqualTo(equivalentIssue.hashCode())
-        assertThat(issue.toString()).isEqualTo(equivalentIssue.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_fromCopyBuilder() {
-        val copyOfIssue1 = SafetyCenterIssue.Builder(issue1).build()
-
-        assertThat(copyOfIssue1).isEqualTo(issue1)
-        assertThat(copyOfIssue1.hashCode()).isEqualTo(issue1.hashCode())
-        assertThat(copyOfIssue1.toString()).isEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentIds_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setId("a different id")
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentTitles_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setTitle("a different title")
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentSubtitles_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setSubtitle("a different subtitle")
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentSummaries_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setSummary("a different summary")
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentSeverityLevels_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setSeverityLevel(SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentIsDismissibleValues_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setDismissible(false)
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentShouldConfirmDismissalValues_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setShouldConfirmDismissal(false)
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun equals_toString_differentActions_areNotEqual() {
-        val differentFromIssue1 = SafetyCenterIssue.Builder(issue1)
-                .setActions(listOf(action2))
-                .build()
-
-        assertThat(differentFromIssue1).isNotEqualTo(issue1)
-        assertThat(differentFromIssue1.toString()).isNotEqualTo(issue1.toString())
-    }
-
-    @Test
-    fun action_getId_returnsId() {
-        assertThat(action1.id).isEqualTo("action_id_1")
-        assertThat(action2.id).isEqualTo("action_id_2")
-    }
-
-    @Test
-    fun action_getLabel_returnsLabel() {
-        assertThat(action1.label).isEqualTo("an action")
-        assertThat(action2.label).isEqualTo("another action")
-    }
-
-    @Test
-    fun action_getPendingIntent_returnsPendingIntent() {
-        assertThat(action1.pendingIntent).isEqualTo(pendingIntent1)
-        assertThat(action2.pendingIntent).isEqualTo(pendingIntent2)
-    }
-
-    @Test
-    fun action_isResolving_returnsIsResolving() {
-        assertThat(action1.isResolving).isTrue()
-        assertThat(action2.isResolving).isFalse()
-    }
-
-    @Test
-    fun action_isInFlight_returnsIsInFlight() {
-        assertThat(action1.isInFlight).isTrue()
-        assertThat(action2.isInFlight).isFalse()
-    }
-
-    @Test
-    fun action_getSuccessMessage_returnsSuccessMessage() {
-        assertThat(action1.successMessage).isEqualTo("a success message")
-        assertThat(action2.successMessage).isNull()
-    }
-
-    @Test
-    fun action_describeContents_returns0() {
-        assertThat(action1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun action_createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
-
-        action1.writeToParcel(parcel, /* flags= */ 0)
-
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterIssue.Action.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(action1)
-    }
-
-    @Test
-    fun action_equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(action1).isEqualTo(action1)
-        assertThat(action1.hashCode()).isEqualTo(action1.hashCode())
-        assertThat(action1.toString()).isEqualTo(action1.toString())
-    }
-
-    @Test
-    fun action_equals_hashCode_toString_equalByValue_areEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(true)
-                .setInFlight(true)
-                .setSuccessMessage("a success message")
-                .build()
-        val equivalentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(true)
-                .setInFlight(true)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isEqualTo(equivalentAction)
-        assertThat(action.toString()).isEqualTo(equivalentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentIds_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("a_different_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentLabels_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a different label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentPendingIntents_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent2)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentResovlingValues_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(true)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(false)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentInFlightValues_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(true)
-                .setInFlight(true)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setResolving(true)
-                .setInFlight(false)
-                .setSuccessMessage("a success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-
-    @Test
-    fun action_equals_toString_differentSuccessMessages_areNotEqual() {
-        val action = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a success message")
-                .build()
-        val differentAction = SafetyCenterIssue.Action.Builder("an_id")
-                .setLabel("a label")
-                .setPendingIntent(pendingIntent1)
-                .setSuccessMessage("a different success message")
-                .build()
-
-        assertThat(action).isNotEqualTo(differentAction)
-        assertThat(action.toString()).isNotEqualTo(differentAction.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
deleted file mode 100644
index bd58849..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ /dev/null
@@ -1,498 +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.safetycenter.cts
-
-import android.Manifest.permission.MANAGE_SAFETY_CENTER
-import android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.content.Context
-import android.content.Intent
-import android.content.Intent.ACTION_SAFETY_CENTER
-import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
-import android.content.res.Resources
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.provider.DeviceConfig
-import android.safetycenter.SafetyCenterData
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetyCenterManager.REFRESH_REASON_PAGE_OPEN
-import android.safetycenter.SafetyCenterManager.REFRESH_REASON_RESCAN_BUTTON_CLICK
-import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetySourceIssue
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceStatus
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
-import android.safetycenter.config.SafetyCenterConfig
-import android.safetycenter.config.SafetySource
-import android.safetycenter.config.SafetySourcesGroup
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import com.google.common.truth.Truth.assertThat
-import com.google.common.util.concurrent.MoreExecutors.directExecutor
-import kotlinx.coroutines.TimeoutCancellationException
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.time.Duration
-import kotlin.test.assertFailsWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterManagerTest {
-    private val context: Context = getApplicationContext()
-    private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
-    private val somePendingIntent = PendingIntent.getActivity(
-        context, 0 /* requestCode */,
-        Intent(ACTION_SAFETY_CENTER).addFlags(FLAG_ACTIVITY_NEW_TASK),
-        FLAG_IMMUTABLE
-    )
-    private val safetySourceDataOnPageOpen = SafetySourceData.Builder()
-        .setStatus(
-            SafetySourceStatus.Builder(
-                "safetySourceDataOnPageOpen status title",
-                "safetySourceDataOnPageOpen status summary",
-                SafetySourceStatus.STATUS_LEVEL_NONE,
-                somePendingIntent
-            )
-                .build()
-        )
-        .build()
-    private val safetySourceDataOnRescanClick = SafetySourceData.Builder()
-        .setStatus(
-            SafetySourceStatus.Builder(
-                "safetySourceDataOnRescanClick status title",
-                "safetySourceDataOnRescanClick status summary",
-                SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION,
-                somePendingIntent
-            )
-                .build()
-        ).build()
-    private val listenerChannel = Channel<SafetyCenterData>()
-    // The lambda has to be wrapped to the right type because kotlin wraps lambdas in a new Java
-    // functional interface implementation each time they are referenced/cast to a Java interface:
-    // b/215569072.
-    private val listener = OnSafetyCenterDataChangedListener {
-        runBlockingWithTimeout {
-            listenerChannel.send(it)
-        }
-    }
-
-    @Before
-    @After
-    fun clearDataBetweenTest() {
-        safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
-        safetyCenterManager.clearAllSafetySourceDataWithPermission()
-        SafetySourceBroadcastReceiver.reset()
-    }
-
-    @Before
-    fun setSafetyCenterConfigOverrideBeforeTest() {
-        safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
-        // TODO(b/217944317): When the test API impl is finalized to override XML config, only
-        //  override config in select test cases that require it. This is to ensure that we do have
-        //  some test cases running with the XML config.
-        safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_ONLY_CONFIG)
-    }
-
-    @After
-    fun clearSafetyCenterConfigOverrideAfterTest() {
-        safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
-    }
-
-    @Test
-    fun getSafetySourceData_notSet_returnsNull() {
-        val safetySourceData =
-            safetyCenterManager.getSafetySourceDataWithPermission("some_unknown_id")
-
-        assertThat(safetySourceData).isNull()
-    }
-
-    @Test
-    fun setSafetySourceData_getSafetySourceDataReturnsNewValue() {
-        val safetySourceData = SafetySourceData.Builder().build()
-        safetyCenterManager.setSafetySourceDataWithPermission(
-                CTS_SOURCE_ID,
-                safetySourceData,
-                EVENT_SOURCE_STATE_CHANGED
-        )
-
-        val safetySourceDataResult =
-                safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
-
-        assertThat(safetySourceDataResult).isEqualTo(safetySourceData)
-    }
-
-    @Test
-    fun setSafetySourceData_withSameId_replacesValue() {
-        val firstSafetySourceData = SafetySourceData.Builder().build()
-        safetyCenterManager.setSafetySourceDataWithPermission(
-                CTS_SOURCE_ID,
-                firstSafetySourceData,
-                EVENT_SOURCE_STATE_CHANGED
-        )
-
-        val secondSafetySourceData = SafetySourceData.Builder().setStatus(
-            SafetySourceStatus.Builder(
-                "Status title", "Summary of the status", STATUS_LEVEL_CRITICAL_WARNING,
-                somePendingIntent
-            ).build()
-        ).addIssue(
-            SafetySourceIssue.Builder(
-                "Issue id", "Issue title", "Summary of the issue",
-                SEVERITY_LEVEL_CRITICAL_WARNING,
-                "issue_type_id"
-            )
-                .addAction(
-                    SafetySourceIssue.Action.Builder(
-                        "action_id",
-                        "Solve issue",
-                        somePendingIntent
-                    ).build()
-                ).build()
-        ).build()
-        safetyCenterManager.setSafetySourceDataWithPermission(
-                CTS_SOURCE_ID,
-                secondSafetySourceData,
-                EVENT_SOURCE_STATE_CHANGED
-        )
-
-        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
-
-        assertThat(safetySourceData).isEqualTo(secondSafetySourceData)
-    }
-
-    @Test
-    fun isSafetyCenterEnabled_whenConfigEnabled_andFlagEnabled_returnsTrue() {
-        if (!deviceSupportsSafetyCenter()) {
-            return
-        }
-
-        runWithShellPermissionIdentity {
-            DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PRIVACY,
-                PROPERTY_SAFETY_CENTER_ENABLED,
-                /* value = */ true.toString(),
-                /* makeDefault = */ false
-            )
-        }
-
-        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
-
-        assertThat(isSafetyCenterEnabled).isTrue()
-    }
-
-    @Test
-    fun isSafetyCenterEnabled_whenConfigEnabled_andFlagDisabled_returnsFalse() {
-        if (!deviceSupportsSafetyCenter()) {
-            return
-        }
-
-        runWithShellPermissionIdentity {
-            DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PRIVACY,
-                PROPERTY_SAFETY_CENTER_ENABLED,
-                /* value = */ false.toString(),
-                /* makeDefault = */ false
-            )
-        }
-
-        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
-
-        assertThat(isSafetyCenterEnabled).isFalse()
-    }
-
-    @Test
-    fun isSafetyCenterEnabled_whenConfigDisabled_andFlagEnabled_returnsFalse() {
-        if (deviceSupportsSafetyCenter()) {
-            return
-        }
-
-        runWithShellPermissionIdentity {
-            DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PRIVACY,
-                PROPERTY_SAFETY_CENTER_ENABLED,
-                /* value = */ true.toString(),
-                /* makeDefault = */ false
-            )
-        }
-
-        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
-
-        assertThat(isSafetyCenterEnabled).isFalse()
-    }
-
-    @Test
-    fun isSafetyCenterEnabled_whenConfigDisabled_andFlagDisabled_returnsFalse() {
-        if (deviceSupportsSafetyCenter()) {
-            return
-        }
-
-        runWithShellPermissionIdentity {
-            DeviceConfig.setProperty(
-                DeviceConfig.NAMESPACE_PRIVACY,
-                PROPERTY_SAFETY_CENTER_ENABLED,
-                /* value = */ false.toString(),
-                /* makeDefault = */ false
-            )
-        }
-
-        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
-
-        assertThat(isSafetyCenterEnabled).isFalse()
-    }
-
-    @Test
-    fun isSafetyCenterEnabled_whenAppDoesNotHoldPermission_methodThrows() {
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.isSafetyCenterEnabled
-        }
-    }
-
-    @Test
-    fun refreshSafetySources_withoutManageSafetyCenterPermission_throwsSecurityException() {
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.refreshSafetySources(REFRESH_REASON_RESCAN_BUTTON_CLICK)
-        }
-    }
-
-    @Test
-    fun refreshSafetySources_whenReceiverDoesNotHaveSendingPermission_sourceDoesNotSendData() {
-        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
-        SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
-
-        safetyCenterManager.refreshSafetySourcesWithPermission(
-            REFRESH_REASON_RESCAN_BUTTON_CLICK
-        )
-
-        assertFailsWith(TimeoutCancellationException::class) {
-            SafetySourceBroadcastReceiver.waitTillOnReceiveComplete(TIMEOUT_SHORT)
-        }
-        val safetySourceData =
-            safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
-        assertThat(safetySourceData).isNull()
-    }
-
-    @Test
-    fun refreshSafetySources_withRefreshReasonRescanButtonClick_sourceSendsRescanData() {
-        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
-        SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
-
-        safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
-            REFRESH_REASON_RESCAN_BUTTON_CLICK
-        )
-
-        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
-        assertThat(safetySourceData).isEqualTo(safetySourceDataOnRescanClick)
-    }
-
-    @Test
-    fun refreshSafetySources_withRefreshReasonPageOpen_sourceSendsPageOpenData() {
-        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
-        SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
-
-        safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
-            REFRESH_REASON_PAGE_OPEN
-        )
-
-        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
-        assertThat(safetySourceData).isEqualTo(safetySourceDataOnPageOpen)
-    }
-
-    @Test
-    fun refreshSafetySources_withInvalidRefreshSeason_throwsIllegalArgumentException() {
-        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
-        SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
-        SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
-
-        assertFailsWith(IllegalArgumentException::class) {
-            safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(500)
-        }
-    }
-
-    @Test
-    fun getSafetyCenterData_returnsSafetyCenterData() {
-        val safetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
-
-        // TODO(b/218830137): Assert on content.
-        assertThat(safetyCenterData).isNotNull()
-    }
-
-    @Test
-    fun getSafetyCenterData_whenAppDoesNotHoldPermission_methodThrows() {
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.safetyCenterData
-        }
-    }
-
-    @Test
-    fun addOnSafetyCenterDataChangedListener_listenerCalledWithSafetyCenterData() {
-        safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
-            directExecutor(), listener
-        )
-        val safetyCenterDataFromListener = receiveListenerUpdate()
-
-        // TODO(b/218830137): Assert on content.
-        assertThat(safetyCenterDataFromListener).isNotNull()
-    }
-
-    @Test
-    fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetySourceData() {
-        safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
-            directExecutor(), listener
-        )
-        // Receive initial data.
-        receiveListenerUpdate()
-
-        val safetySourceData = SafetySourceData.Builder().build()
-        safetyCenterManager.setSafetySourceDataWithPermission(
-                CTS_SOURCE_ID,
-                safetySourceData,
-                EVENT_SOURCE_STATE_CHANGED
-        )
-        val safetyCenterDataFromListener = receiveListenerUpdate()
-
-        // TODO(b/218830137): Assert on content.
-        assertThat(safetyCenterDataFromListener).isNotNull()
-    }
-
-    @Test
-    fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetySourceData() {
-        safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
-            directExecutor(), listener
-        )
-        // Receive initial data.
-        receiveListenerUpdate()
-
-        safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
-        val safetySourceData = SafetySourceData.Builder().build()
-        safetyCenterManager.setSafetySourceDataWithPermission(
-                CTS_SOURCE_ID,
-                safetySourceData,
-                EVENT_SOURCE_STATE_CHANGED
-        )
-
-        assertFailsWith(TimeoutCancellationException::class) {
-            receiveListenerUpdate(TIMEOUT_SHORT)
-        }
-    }
-
-    @Test
-    fun addOnSafetyCenterDataChangedListener_whenAppDoesNotHoldPermission_methodThrows() {
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.addOnSafetyCenterDataChangedListener(
-                directExecutor(), listener
-            )
-        }
-    }
-
-    @Test
-    fun removeOnSafetyCenterDataChangedListener_whenAppDoesNotHoldPermission_methodThrows() {
-        safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
-            directExecutor(), listener
-        )
-
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.removeOnSafetyCenterDataChangedListener(listener)
-        }
-    }
-
-    @Test
-    fun dismissSafetyIssue_whenAppDoesNotHoldPermission_methodThrows() {
-        assertFailsWith(SecurityException::class) {
-            safetyCenterManager.dismissSafetyIssue("bleh")
-        }
-    }
-
-    private fun deviceSupportsSafetyCenter() =
-        context.resources.getBoolean(
-            Resources.getSystem().getIdentifier(
-                "config_enableSafetyCenter",
-                "bool",
-                "android"
-            )
-        )
-
-    private fun SafetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
-        refreshReason: Int
-    ) {
-        try {
-            runWithShellPermissionIdentity({
-                refreshSafetySources(refreshReason)
-                SafetySourceBroadcastReceiver.waitTillOnReceiveComplete(TIMEOUT_LONG)
-            }, SEND_SAFETY_CENTER_UPDATE, MANAGE_SAFETY_CENTER)
-        } catch (e: RuntimeException) {
-            throw e.cause ?: e
-        }
-    }
-
-    private fun receiveListenerUpdate(timeout: Duration = TIMEOUT_LONG): SafetyCenterData =
-        runBlockingWithTimeout(timeout) {
-            listenerChannel.receive()
-        }
-
-    private fun <T> runBlockingWithTimeout(
-        timeout: Duration = TIMEOUT_LONG,
-        block: suspend () -> T
-    ) =
-        runBlocking {
-            withTimeout(timeout.toMillis()) {
-                block()
-            }
-        }
-
-    companion object {
-        /** Name of the flag that determines whether SafetyCenter is enabled. */
-        private const val PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
-        private const val CTS_PACKAGE_NAME = "android.safetycenter.cts"
-        private const val CTS_BROADCAST_RECEIVER_NAME =
-            "android.safetycenter.cts.SafetySourceBroadcastReceiver"
-        private val TIMEOUT_LONG: Duration = Duration.ofMillis(5000)
-        private val TIMEOUT_SHORT: Duration = Duration.ofMillis(1000)
-        private val EVENT_SOURCE_STATE_CHANGED =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
-        private const val CTS_SOURCE_ID = "cts_source_id"
-        // TODO(b/217944317): Consider moving the following to a file where they can be used by
-        //  other tests.
-        private val CTS_SOURCE = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
-                .setId(CTS_SOURCE_ID)
-                .setPackageName(CTS_PACKAGE_NAME)
-                .setTitleResId(R.string.reference)
-                .setSummaryResId(R.string.reference)
-                .setIntentAction("SafetyCenterManagerTest.INTENT_ACTION")
-                .setBroadcastReceiverClassName(CTS_BROADCAST_RECEIVER_NAME)
-                .setProfile(SafetySource.PROFILE_PRIMARY)
-                .build()
-        private val CTS_SOURCE_GROUP = SafetySourcesGroup.Builder()
-                .setId("cts_source_group")
-                .setTitleResId(R.string.reference)
-                .setSummaryResId(R.string.reference)
-                .addSafetySource(CTS_SOURCE)
-                .build()
-        private val CTS_ONLY_CONFIG = SafetyCenterConfig.Builder()
-                .addSafetySourcesGroup(CTS_SOURCE_GROUP)
-                .build()
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt
deleted file mode 100644
index 9557833..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryGroupTest.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterStaticEntry
-import android.safetycenter.SafetyCenterStaticEntryGroup
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterStaticEntryGroupTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent1 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-    private val pendingIntent2 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Different Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    private val staticEntry1 =
-            SafetyCenterStaticEntry("an entry title", "an entry summary", pendingIntent1)
-    private val staticEntry2 =
-            SafetyCenterStaticEntry("another entry title", "another entry summary", pendingIntent2)
-
-    private val staticEntryGroup =
-            SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1, staticEntry2))
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(SafetyCenterStaticEntryGroup("a title", listOf()).title).isEqualTo("a title")
-        assertThat(SafetyCenterStaticEntryGroup("another title", listOf()).title)
-                .isEqualTo("another title")
-    }
-
-    @Test
-    fun getStaticEntries_returnsStaticEntries() {
-        assertThat(SafetyCenterStaticEntryGroup("", listOf(staticEntry1)).staticEntries)
-                .containsExactly(staticEntry1)
-        assertThat(
-                SafetyCenterStaticEntryGroup("", listOf(staticEntry1, staticEntry2)).staticEntries)
-                .containsExactly(staticEntry1, staticEntry2)
-        assertThat(SafetyCenterStaticEntryGroup("", listOf()).staticEntries).isEmpty()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(staticEntryGroup.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel: Parcel = Parcel.obtain()
-
-        staticEntryGroup.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterStaticEntryGroup.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(staticEntryGroup)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(staticEntryGroup).isEqualTo(staticEntryGroup)
-        assertThat(staticEntryGroup.hashCode()).isEqualTo(staticEntryGroup.hashCode())
-        assertThat(staticEntryGroup.toString()).isEqualTo(staticEntryGroup.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
-        val equivalentGroup = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
-
-        assertThat(group).isEqualTo(equivalentGroup)
-        assertThat(group.hashCode()).isEqualTo(equivalentGroup.hashCode())
-        assertThat(group.toString()).isEqualTo(equivalentGroup.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentTitles_areNotEqual() {
-        val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
-        val differentGroup = SafetyCenterStaticEntryGroup("a different title", listOf(staticEntry1))
-
-        assertThat(group).isNotEqualTo(differentGroup)
-        assertThat(group.toString()).isNotEqualTo(differentGroup.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentStaticEntries_areNotEqual() {
-        val group = SafetyCenterStaticEntryGroup("a title", listOf(staticEntry1))
-        val differentGroup = SafetyCenterStaticEntryGroup("a different title", listOf(staticEntry2))
-
-        assertThat(group).isNotEqualTo(differentGroup)
-        assertThat(group.toString()).isNotEqualTo(differentGroup.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt
deleted file mode 100644
index 8902aeb..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStaticEntryTest.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterStaticEntry
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterStaticEntryTest {
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    private val pendingIntent1 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-    private val pendingIntent2 = PendingIntent.getActivity(
-            context,
-            /* requestCode= */ 0,
-            Intent("Fake Different Data"),
-            PendingIntent.FLAG_IMMUTABLE)
-
-    private val title1 = "a title"
-    private val title2 = "another title"
-
-    private val summary1 = "a summary"
-    private val summary2 = "another summary"
-
-    private val staticEntry1 = SafetyCenterStaticEntry(title1, summary1, pendingIntent1)
-    private val staticEntry2 = SafetyCenterStaticEntry(title2, summary2, pendingIntent2)
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(staticEntry1.title).isEqualTo(title1)
-        assertThat(staticEntry2.title).isEqualTo(title2)
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        assertThat(staticEntry1.summary).isEqualTo(summary1)
-        assertThat(staticEntry2.summary).isEqualTo(summary2)
-        assertThat(SafetyCenterStaticEntry("", null, pendingIntent1).summary).isNull()
-    }
-
-    @Test
-    fun getPendingIntent_returnsPendingIntent() {
-        assertThat(staticEntry1.pendingIntent).isEqualTo(pendingIntent1)
-        assertThat(staticEntry2.pendingIntent).isEqualTo(pendingIntent2)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(staticEntry1.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel: Parcel = Parcel.obtain()
-
-        staticEntry1.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterStaticEntry.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(staticEntry1)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(staticEntry1).isEqualTo(staticEntry1)
-        assertThat(staticEntry1.hashCode()).isEqualTo(staticEntry1.hashCode())
-        assertThat(staticEntry1.toString()).isEqualTo(staticEntry1.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val staticEntry = SafetyCenterStaticEntry("titlee", "sumaree", pendingIntent1)
-        val equivalentStaticEntry = SafetyCenterStaticEntry("titlee", "sumaree", pendingIntent1)
-
-        assertThat(staticEntry).isEqualTo(equivalentStaticEntry)
-        assertThat(staticEntry.hashCode()).isEqualTo(equivalentStaticEntry.hashCode())
-        assertThat(staticEntry.toString()).isEqualTo(equivalentStaticEntry.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentTitles_areNotEqual() {
-        val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
-        val differentStaticEntry =
-                SafetyCenterStaticEntry("a different title", "a summary", pendingIntent1)
-
-        assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
-        assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSummaries_areNotEqual() {
-        val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
-        val differentStaticEntry =
-                SafetyCenterStaticEntry("a title", "a different summary", pendingIntent1)
-
-        assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
-        assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentPendingIntents_areNotEqual() {
-        val staticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent1)
-        val differentStaticEntry = SafetyCenterStaticEntry("a title", "a summary", pendingIntent2)
-
-        assertThat(staticEntry).isNotEqualTo(differentStaticEntry)
-        assertThat(staticEntry.toString()).isNotEqualTo(differentStaticEntry.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt
deleted file mode 100644
index 68edbf3..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterStatusTest.kt
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetyCenterStatus
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetyCenterStatusTest {
-
-    val baseStatus = SafetyCenterStatus.Builder()
-            .setTitle("This is my title")
-            .setSummary("This is my summary")
-            .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
-            .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
-            .build()
-
-    @Test
-    fun getTitle_returnsTitle() {
-        assertThat(SafetyCenterStatus.Builder(baseStatus).setTitle("title").build().title)
-                .isEqualTo("title")
-
-        assertThat(SafetyCenterStatus.Builder(baseStatus).setTitle("different title").build().title)
-                .isEqualTo("different title")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        assertThat(SafetyCenterStatus.Builder(baseStatus).setSummary("summary").build().summary)
-                .isEqualTo("summary")
-
-        assertThat(
-                SafetyCenterStatus.Builder(baseStatus)
-                        .setSummary("different summary")
-                        .build()
-                        .summary)
-                .isEqualTo("different summary")
-    }
-
-    @Test
-    fun getSeverityLevel_returnsSeverityLevel() {
-        assertThat(
-                SafetyCenterStatus.Builder(baseStatus)
-                        .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-                        .build()
-                        .severityLevel)
-                .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-
-        assertThat(
-                SafetyCenterStatus.Builder(baseStatus)
-                        .setSeverityLevel(
-                                SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
-                        .build()
-                        .severityLevel)
-                .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
-    }
-
-    @Test
-    fun getSeverityLevel_defaultUnknown() {
-        assertThat(
-                SafetyCenterStatus.Builder()
-                        .setTitle("This is my title")
-                        .setSummary("This is my summary")
-                        .build()
-                        .severityLevel)
-                .isEqualTo(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN)
-    }
-
-    @Test
-    fun getRefreshStatus_returnsRefreshStatus() {
-        assertThat(
-                SafetyCenterStatus.Builder(baseStatus)
-                        .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
-                        .build()
-                        .refreshStatus)
-                .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
-
-        assertThat(
-                SafetyCenterStatus.Builder(baseStatus)
-                        .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
-                        .build()
-                        .refreshStatus)
-                .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
-    }
-
-    @Test
-    fun getRefreshStatus_defaultNone() {
-        assertThat(
-                SafetyCenterStatus.Builder()
-                        .setTitle("This is my title")
-                        .setSummary("This is my summary")
-                        .build()
-                        .refreshStatus)
-                .isEqualTo(SafetyCenterStatus.REFRESH_STATUS_NONE)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        assertThat(baseStatus.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel: Parcel = Parcel.obtain()
-        baseStatus.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val fromParcel = SafetyCenterStatus.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(baseStatus)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(baseStatus).isEqualTo(baseStatus)
-        assertThat(baseStatus.hashCode()).isEqualTo(baseStatus.hashCode())
-        assertThat(baseStatus.toString()).isEqualTo(baseStatus.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val status = SafetyCenterStatus.Builder()
-                .setTitle("same title")
-                .setSummary("same summary")
-                .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-                .build()
-        val equivalentStatus = SafetyCenterStatus.Builder()
-                .setTitle("same title")
-                .setSummary("same summary")
-                .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-                .build()
-
-        assertThat(status).isEqualTo(equivalentStatus)
-        assertThat(status.hashCode()).isEqualTo(equivalentStatus.hashCode())
-        assertThat(status.toString()).isEqualTo(equivalentStatus.toString())
-    }
-
-    @Test
-    fun equals_hashCode_toString_fromCopyBuilder_areEqual() {
-        val copyOfBaseStatus = SafetyCenterStatus.Builder(baseStatus).build()
-
-        assertThat(copyOfBaseStatus).isEqualTo(baseStatus)
-        assertThat(copyOfBaseStatus.hashCode()).isEqualTo(baseStatus.hashCode())
-        assertThat(copyOfBaseStatus.toString()).isEqualTo(baseStatus.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentTitles_areNotEqual() {
-        val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
-                .setTitle("that's discarsting")
-                .build()
-
-        assertThat(unequalStatus).isNotEqualTo(baseStatus)
-        assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSummaries_areNotEqual() {
-        val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
-                .setSummary("discarsting sheet")
-                .build()
-
-        assertThat(unequalStatus).isNotEqualTo(baseStatus)
-        assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentSeverityLevels_arNotEqual() {
-        val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
-                .setSeverityLevel(SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK)
-                .build()
-
-        assertThat(unequalStatus).isNotEqualTo(baseStatus)
-        assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
-    }
-
-    @Test
-    fun equals_toString_withDifferentRefreshStatuses_areNotEqual() {
-        val unequalStatus = SafetyCenterStatus.Builder(baseStatus)
-                .setRefreshStatus(SafetyCenterStatus.REFRESH_STATUS_NONE)
-                .build()
-
-        assertThat(unequalStatus).isNotEqualTo(baseStatus)
-        assertThat(unequalStatus.toString()).isNotEqualTo(baseStatus.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
deleted file mode 100644
index bc9d538..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.os.Build
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
-import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
-import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
-import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetyEvent]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
-class SafetyEventTest {
-    @Test
-    fun getSafetyEventType_returnsSafetyEventType() {
-        val safetyEvent = SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
-
-        assertThat(safetyEvent.safetyEventType).isEqualTo(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
-    }
-
-    @Test
-    fun getRefreshBroadcastId_returnsRefreshBroadcastId() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
-                        .build()
-
-        assertThat(safetyEvent.refreshBroadcastId).isEqualTo(REFRESH_BROADCAST_ID)
-    }
-
-    @Test
-    fun getSafetySourceIssueId_returnsSafetySourceIssueId() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .build()
-
-        assertThat(safetyEvent.safetySourceIssueId).isEqualTo(SAFETY_SOURCE_ISSUE_ID)
-    }
-
-    @Test
-    fun getSafetySourceIssueActionId_returnsSafetySourceIssueActionId() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-
-        assertThat(safetyEvent.safetySourceIssueActionId).isEqualTo(SAFETY_SOURCE_ISSUE_ACTION_ID)
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-
-        assertThat(safetyEvent.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-
-        assertThatRoundTripReturnsOriginal(safetyEvent, SafetyEvent.CREATOR)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
-                        .build()
-        val otherSafetyEvent = safetyEvent
-
-        assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-        val otherSafetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-
-        assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSafetyEventTypes_areNotEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .build()
-        val otherSafetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED)
-                        .build()
-
-        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentRefreshBroadcastIds_areNotEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
-                        .build()
-        val otherSafetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .setRefreshBroadcastId(OTHER_REFRESH_BROADCAST_ID)
-                        .build()
-
-        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIssueIds_areNotEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .build()
-        val otherSafetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(OTHER_SAFETY_SOURCE_ISSUE_ID)
-                        .build()
-
-        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentActionIds_areNotEqual() {
-        val safetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-        val otherSafetyEvent =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
-                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
-                        .setSafetySourceIssueActionId(OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID)
-                        .build()
-
-        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
-    }
-
-    companion object {
-        const val REFRESH_BROADCAST_ID = "refresh_broadcast_id"
-        const val OTHER_REFRESH_BROADCAST_ID = "other_refresh_broadcast_id"
-        const val SAFETY_SOURCE_ISSUE_ID = "safety_source_issue_id"
-        const val OTHER_SAFETY_SOURCE_ISSUE_ID = "other_safety_source_issue_id"
-        const val SAFETY_SOURCE_ISSUE_ACTION_ID = "safety_source_issue_action_id"
-        const val OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID = "other_safety_source_issue_action_id"
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
deleted file mode 100644
index 5f8e8b8..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES
-import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA
-import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA
-import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
-import android.safetycenter.SafetyCenterManager
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
-import java.time.Duration
-
-/** Broadcast receiver to be used for testing broadcasts sent to safety source apps. */
-class SafetySourceBroadcastReceiver : BroadcastReceiver() {
-    override fun onReceive(context: Context, intent: Intent?) {
-        if (intent == null) {
-            throw IllegalArgumentException("Received null intent")
-        }
-
-        if (intent.action != ACTION_REFRESH_SAFETY_SOURCES) {
-            throw IllegalArgumentException("Received intent with action: ${intent.action}")
-        }
-
-        val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
-
-        when (intent.getIntExtra(EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE, -1)) {
-            EXTRA_REFRESH_REQUEST_TYPE_GET_DATA ->
-                safetyCenterManager.setSafetySourceDataWithPermission(
-                        safetySourceId!!,
-                        safetySourceDataOnPageOpen!!,
-                        EVENT_REFRESH_REQUESTED
-                )
-            EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA ->
-                safetyCenterManager.setSafetySourceDataWithPermission(
-                        safetySourceId!!,
-                        safetySourceDataOnRescanClick!!,
-                        EVENT_REFRESH_REQUESTED
-                )
-        }
-
-        runBlocking {
-            updateChannel.send(Unit)
-        }
-    }
-
-    companion object {
-        private var updateChannel = Channel<Unit>()
-        private val EVENT_REFRESH_REQUESTED =
-                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
-                        .setRefreshBroadcastId("refresh_id")
-                        .build()
-        var safetySourceId: String? = null
-        var safetySourceDataOnPageOpen: SafetySourceData? = null
-        var safetySourceDataOnRescanClick: SafetySourceData? = null
-
-        fun reset() {
-            safetySourceId = null
-            safetySourceDataOnRescanClick = null
-            safetySourceDataOnPageOpen = null
-            updateChannel = Channel()
-        }
-
-        fun waitTillOnReceiveComplete(duration: Duration) {
-            runBlocking {
-                withTimeout(duration.toMillis()) {
-                    updateChannel.receive()
-                }
-            }
-        }
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
deleted file mode 100644
index 76090bf..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
+++ /dev/null
@@ -1,296 +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.safetycenter.cts
-
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetySourceData
-import android.safetycenter.SafetySourceIssue
-import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_ACCOUNT
-import android.safetycenter.SafetySourceStatus
-import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_GEAR
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourceData]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourceDataTest {
-    private val context: Context = getApplicationContext()
-
-    private val status1 = SafetySourceStatus.Builder(
-            "Status title 1",
-            "Status summary 1",
-            SafetySourceStatus.STATUS_LEVEL_NONE,
-            PendingIntent.getActivity(context, 0 /* requestCode= */,
-                    Intent("Status PendingIntent 1"), FLAG_IMMUTABLE))
-            .setEnabled(false)
-            .build()
-    private val status2 = SafetySourceStatus.Builder(
-            "Status title 2",
-            "Status summary 2",
-            SafetySourceStatus.STATUS_LEVEL_RECOMMENDATION,
-            PendingIntent.getActivity(context, 0 /* requestCode= */,
-                    Intent("Status PendingIntent 2"), FLAG_IMMUTABLE))
-            .setIconAction(SafetySourceStatus.IconAction(ICON_TYPE_GEAR,
-                    PendingIntent.getActivity(context, 0 /* requestCode= */,
-                            Intent("IconAction PendingIntent 2"), FLAG_IMMUTABLE)))
-            .build()
-    private val issue1 = SafetySourceIssue.Builder(
-        "Issue id 1",
-        "Issue summary 1",
-        "Issue summary 1",
-        SafetySourceIssue.SEVERITY_LEVEL_INFORMATION, "issue_type_id"
-    )
-        .setSubtitle("Issue subtitle 1")
-        .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-        .addAction(
-            SafetySourceIssue.Action.Builder(
-                "action_id_1",
-                "Action label 1",
-                PendingIntent.getActivity(
-                    context, 0 /* requestCode= */,
-                    Intent("Issue PendingIntent 1"), FLAG_IMMUTABLE
-                )
-            )
-                .build()
-        )
-        .build()
-    private val issue2 = SafetySourceIssue.Builder(
-        "Issue id 2",
-        "Issue title 2",
-        "Issue summary 2",
-        SafetySourceIssue.SEVERITY_LEVEL_RECOMMENDATION, "issue_type_id"
-    )
-        .addAction(
-            SafetySourceIssue.Action.Builder(
-                "action_id_2",
-                "Action label 2",
-                PendingIntent.getService(
-                    context, 0 /* requestCode= */,
-                    Intent("Issue PendingIntent 2"), FLAG_IMMUTABLE
-                )
-            ).build()
-        )
-        .setOnDismissPendingIntent(
-            PendingIntent.getService(
-                context,
-                0 /* requestCode= */,
-                Intent("Issue OnDismissPendingIntent 2"), FLAG_IMMUTABLE
-            )
-        )
-        .build()
-
-    @Test
-    fun getStatus_withDefaultBuilder_returnsNull() {
-        val safetySourceData = SafetySourceData.Builder().build()
-
-        assertThat(safetySourceData.status).isNull()
-    }
-
-    @Test
-    fun getStatus_whenSetExplicitly_returnsStatus() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .build()
-
-        assertThat(safetySourceData.status).isEqualTo(status1)
-    }
-
-    @Test
-    fun getIssues_withDefaultBuilder_returnsEmptyList() {
-        val safetySourceData = SafetySourceData.Builder().build()
-
-        assertThat(safetySourceData.issues).isEmpty()
-    }
-
-    @Test
-    fun getIssues_whenSetExplicitly_returnsIssues() {
-        val safetySourceData = SafetySourceData.Builder()
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-
-        assertThat(safetySourceData.issues).containsExactly(issue1, issue2).inOrder()
-    }
-
-    @Test
-    fun clearIssues_removesAllIssues() {
-        val safetySourceData = SafetySourceData.Builder()
-            .addIssue(issue1)
-            .addIssue(issue2)
-            .clearIssues()
-            .build()
-
-        assertThat(safetySourceData.issues).isEmpty()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-
-        assertThat(safetySourceData.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-
-        val parcel: Parcel = Parcel.obtain()
-        safetySourceData.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val safetySourceDataFromParcel: SafetySourceData =
-                SafetySourceData.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(safetySourceDataFromParcel).isEqualTo(safetySourceData)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_withoutStatusAndIssues_areEqual() {
-        val safetySourceData = SafetySourceData.Builder().build()
-        val otherSafetySourceData = safetySourceData
-
-        assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_withoutIssues_areEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .build()
-        val otherSafetySourceData = safetySourceData
-
-        assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-        val otherSafetySourceData = safetySourceData
-
-        assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-
-        assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIssues_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder()
-                .setStatus(status2)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-
-        assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentStatuses_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .build()
-
-        assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withStatusSetInOneAndNotOther_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder().build()
-
-        assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withIssuesSetInOneAndNotOther_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .addIssue(issue1)
-                .addIssue(issue2)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder()
-                .setStatus(status1)
-                .build()
-
-        assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
deleted file mode 100644
index 0d69f2c..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.os.Build
-import android.safetycenter.SafetyEvent
-import android.safetycenter.SafetySourceError
-import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
-import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
-import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourceError]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
-class SafetySourceErrorTest {
-    @Test
-    fun getSafetyEvent_returnsSafetyEvent() {
-        val safetySourceError = SafetySourceError(SAFETY_EVENT)
-
-        assertThat(safetySourceError.safetyEvent).isEqualTo(SAFETY_EVENT)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val safetySourceError = SafetySourceError(SAFETY_EVENT)
-
-        assertThatRoundTripReturnsOriginal(safetySourceError, SafetySourceError.CREATOR)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByReference_areEqual() {
-        val safetySourceError = SafetySourceError(SAFETY_EVENT)
-
-        assertThatRepresentationsAreEqual(safetySourceError, safetySourceError)
-    }
-
-    @Test
-    fun equals_hashCode_toString_equalByValue_areEqual() {
-        val safetySourceError = SafetySourceError(SAFETY_EVENT)
-        val equivalentSafetySourceError = SafetySourceError(SAFETY_EVENT)
-
-        assertThatRepresentationsAreEqual(safetySourceError, equivalentSafetySourceError)
-    }
-
-    @Test
-    fun equals_toString_withDifferentSafetyEvents_areNotEqual() {
-        val safetySourceError = SafetySourceError(
-                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build())
-        val otherSafetySourceError = SafetySourceError(
-                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build())
-
-        assertThatRepresentationsAreNotEqual(safetySourceError, otherSafetySourceError)
-    }
-
-    companion object {
-        private val SAFETY_EVENT =
-                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
deleted file mode 100644
index ad3e441..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
+++ /dev/null
@@ -1,785 +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.safetycenter.cts
-
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetySourceIssue
-import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_ACCOUNT
-import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_DEVICE
-import android.safetycenter.SafetySourceIssue.ISSUE_CATEGORY_GENERAL
-import android.safetycenter.SafetySourceIssue.Action
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_INFORMATION
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourceIssue]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourceIssueTest {
-    private val context: Context = getApplicationContext()
-
-    private val pendingIntent1: PendingIntent = PendingIntent.getActivity(
-        context,
-        0 /* requestCode= */, Intent("PendingIntent 1"), FLAG_IMMUTABLE
-    )
-    private val action1 = Action.Builder("action_id_1", "Action label 1", pendingIntent1).build()
-    private val pendingIntent2: PendingIntent = PendingIntent.getActivity(
-        context,
-        0 /* requestCode= */, Intent("PendingIntent 2"), FLAG_IMMUTABLE
-    )
-    private val action2 = Action.Builder("action_id_2", "Action label 2", pendingIntent2).build()
-    private val action3 = Action.Builder("action_id_3", "Action label 3", pendingIntent1).build()
-
-    @Test
-    fun action_getId_returnsId() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.id).isEqualTo("action_id")
-    }
-
-    @Test
-    fun action_getLabel_returnsLabel() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.label).isEqualTo("Action label")
-    }
-
-    @Test
-    fun action_isResolving_withDefaultBuilder_returnsFalse() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.isResolving).isFalse()
-    }
-
-    @Test
-    fun action_isResolving_whenSetExplicitly_returnsResolving() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1)
-            .setResolving(true)
-            .build()
-
-        assertThat(action.isResolving).isTrue()
-    }
-
-    @Test
-    fun action_getPendingIntent_returnsPendingIntent() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.pendingIntent).isEqualTo(pendingIntent1)
-    }
-
-    @Test
-    fun action_getSuccessMessage_withDefaultBuilder_returnsNull() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.successMessage).isNull()
-    }
-
-    @Test
-    fun action_getSuccessMessage_whenSetExplicitly_returnsSuccessMessage() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1)
-            .setSuccessMessage("Action successfully completed")
-            .build()
-
-        assertThat(action.successMessage).isEqualTo("Action successfully completed")
-    }
-
-    @Test
-    fun action_describeContents_returns0() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun action_createFromParcel_withWriteToParcel_returnsOriginalAction() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1)
-            .setSuccessMessage("Action successfully completed")
-            .build()
-
-        val parcel: Parcel = Parcel.obtain()
-        action.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val actionFromParcel: Action = Action.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(actionFromParcel).isEqualTo(action)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun action_hashCode_equals_toString_withEqualByReferenceActions_areEqual() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-        val otherAction = action
-
-        assertThat(action.hashCode()).isEqualTo(otherAction.hashCode())
-        assertThat(action).isEqualTo(otherAction)
-        assertThat(action.toString()).isEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-        val otherAction = Action.Builder("action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.hashCode()).isEqualTo(otherAction.hashCode())
-        assertThat(action).isEqualTo(otherAction)
-        assertThat(action.toString()).isEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withDifferentIds_areNotEqual() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-        val otherAction = Action.Builder("other_action_id", "Action label", pendingIntent1).build()
-
-        assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
-        assertThat(action).isNotEqualTo(otherAction)
-        assertThat(action.toString()).isNotEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withDifferentLabels_areNotEqual() {
-        val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
-        val otherAction = Action.Builder("action_id", "Other action label", pendingIntent1).build()
-
-        assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
-        assertThat(action).isNotEqualTo(otherAction)
-        assertThat(action.toString()).isNotEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withDifferentResolving_areNotEqual() {
-        val action =
-            Action.Builder("action_id", "Action label", pendingIntent1).setResolving(false)
-                .build()
-        val otherAction =
-            Action.Builder("action_id", "Action label", pendingIntent1).setResolving(true).build()
-
-        assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
-        assertThat(action).isNotEqualTo(otherAction)
-        assertThat(action.toString()).isNotEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
-        val action = Action.Builder(
-            "action_id",
-            "Action label",
-            PendingIntent.getActivity(
-                context, 0 /* requestCode= */,
-                Intent("Action PendingIntent"), FLAG_IMMUTABLE
-            )
-        )
-            .build()
-        val otherAction = Action.Builder(
-            "action_id",
-            "Action label",
-            PendingIntent.getActivity(
-                context, 0 /* requestCode= */,
-                Intent("Other action PendingIntent"), FLAG_IMMUTABLE
-            )
-        )
-            .build()
-
-        assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
-        assertThat(action).isNotEqualTo(otherAction)
-        assertThat(action.toString()).isNotEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun action_hashCode_equals_toString_withDifferentSuccessMessages_areNotEqual() {
-        val action =
-            Action.Builder("action_id", "Action label", pendingIntent1)
-                .setSuccessMessage("Action successfully completed")
-                .build()
-        val otherAction =
-            Action.Builder("action_id", "Action label", pendingIntent1)
-                .setSuccessMessage("Other action successfully completed")
-                .build()
-
-        assertThat(action.hashCode()).isNotEqualTo(otherAction.hashCode())
-        assertThat(action).isNotEqualTo(otherAction)
-        assertThat(action.toString()).isNotEqualTo(otherAction.toString())
-    }
-
-    @Test
-    fun getId_returnsId() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.id).isEqualTo("Issue id")
-    }
-
-    @Test
-    fun getTitle_returnsTitle() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.title).isEqualTo("Issue title")
-    }
-
-    @Test
-    fun getSubtitle_withDefaultBuilder_returnsNull() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.subtitle).isNull()
-    }
-
-    @Test
-    fun getSubtitle_whenSetExplicitly_returnsSubtitle() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .setSubtitle("Issue subtitle")
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.subtitle).isEqualTo("Issue subtitle")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.summary).isEqualTo("Issue summary")
-    }
-
-    @Test
-    fun getSeverityLevel_returnsSeverityLevel() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.severityLevel).isEqualTo(SEVERITY_LEVEL_INFORMATION)
-    }
-
-    @Test
-    fun getIssueCategory_withDefaultBuilder_returnsGeneralCategory() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.issueCategory).isEqualTo(ISSUE_CATEGORY_GENERAL)
-    }
-
-    @Test
-    fun getIssueCategory_whenSetExplicitly_returnsIssueCategory() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .setIssueCategory(ISSUE_CATEGORY_DEVICE)
-            .build()
-
-        assertThat(safetySourceIssue.issueCategory).isEqualTo(ISSUE_CATEGORY_DEVICE)
-    }
-
-    @Test
-    fun getActions_returnsActions() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .addAction(action2)
-            .build()
-
-        assertThat(safetySourceIssue.actions).containsExactly(action1, action2).inOrder()
-    }
-
-    @Test
-    fun clearActions_removesAllActions() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .addAction(action2)
-            .clearActions()
-            .addAction(action3)
-            .build()
-
-        assertThat(safetySourceIssue.actions).containsExactly(action3)
-    }
-
-    @Test
-    fun getOnDismissPendingIntent_withDefaultBuilder_returnsNull() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.onDismissPendingIntent).isNull()
-    }
-
-    @Test
-    fun getOnDismissPendingIntent_whenSetExplicitly_returnsOnDismissPendingIntent() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-
-        assertThat(safetySourceIssue.onDismissPendingIntent).isEqualTo(pendingIntent1)
-    }
-
-    @Test
-    fun getIssueTypeId_returnsIssueTypeId() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.issueTypeId).isEqualTo("issue_type_id")
-    }
-
-    @Test
-    fun build_withNoActions_throwsIllegalArgumentException() {
-        val safetySourceIssueBuilder = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-        assertThrows(
-            "Safety source issue must contain at least 1 action",
-            IllegalArgumentException::class.java
-        ) { safetySourceIssueBuilder.build() }
-    }
-
-    @Test
-    fun build_withMoreThanTwoActions_throwsIllegalArgumentException() {
-        val safetySourceIssueBuilder = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .addAction(action2)
-            .addAction(action1)
-
-        assertThrows(
-            "Safety source issue must not contain more than 2 actions",
-            IllegalArgumentException::class.java
-        ) { safetySourceIssueBuilder.build() }
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-            .addAction(action1)
-            .addAction(action2)
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-
-        assertThat(safetySourceIssue.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceIssue() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-            .addAction(action1)
-            .addAction(action2)
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-
-        val parcel: Parcel = Parcel.obtain()
-        safetySourceIssue.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val safetySourceIssueFromParcel: SafetySourceIssue =
-            SafetySourceIssue.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(safetySourceIssueFromParcel).isEqualTo(safetySourceIssue)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReferenceSafetySourceIssues_areEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-            .addAction(action1)
-            .addAction(action2)
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-        val otherSafetySourceIssue = safetySourceIssue
-
-        assertThat(safetySourceIssue.hashCode()).isEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-            .addAction(
-                Action.Builder("action_id", "Action label 1", pendingIntent1)
-                    .setResolving(false)
-                    .build()
-            )
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .setIssueCategory(ISSUE_CATEGORY_ACCOUNT)
-            .addAction(
-                Action.Builder("action_id", "Action label 1", pendingIntent1)
-                    .setResolving(false)
-                    .build()
-            )
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Other issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTitles_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Other issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSubtitles_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Issue subtitle")
-            .addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).setSubtitle("Other issue subtitle")
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSummaries_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Other issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSeverityLevels_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_CRITICAL_WARNING,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIssueCategories_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .setIssueCategory(ISSUE_CATEGORY_DEVICE)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        )
-            .addAction(action1)
-            .setIssueCategory(ISSUE_CATEGORY_GENERAL)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentActions_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .addAction(action2)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action2)
-            .addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentOnDismissPendingIntents_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .setOnDismissPendingIntent(pendingIntent1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .setOnDismissPendingIntent(pendingIntent2)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIssueTypeIds_areNotEqual() {
-        val safetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "issue_type_id"
-        ).addAction(action1)
-            .build()
-        val otherSafetySourceIssue = SafetySourceIssue.Builder(
-            "Issue id",
-            "Issue title",
-            "Issue summary",
-            SEVERITY_LEVEL_INFORMATION,
-            "other_issue_type_id"
-        ).addAction(action1)
-            .build()
-
-        assertThat(safetySourceIssue.hashCode()).isNotEqualTo(otherSafetySourceIssue.hashCode())
-        assertThat(safetySourceIssue).isNotEqualTo(otherSafetySourceIssue)
-        assertThat(safetySourceIssue.toString()).isNotEqualTo(otherSafetySourceIssue.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
deleted file mode 100644
index b44f6c5..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
+++ /dev/null
@@ -1,458 +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.safetycenter.cts
-
-import android.app.PendingIntent
-import android.app.PendingIntent.FLAG_IMMUTABLE
-import android.content.Context
-import android.content.Intent
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.os.Parcel
-import android.safetycenter.SafetySourceStatus
-import android.safetycenter.SafetySourceStatus.IconAction
-import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_GEAR
-import android.safetycenter.SafetySourceStatus.IconAction.ICON_TYPE_INFO
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
-import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_OK
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/** CTS tests for [SafetySourceStatus]. */
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class SafetySourceStatusTest {
-    private val context: Context = getApplicationContext()
-
-    private val pendingIntent1: PendingIntent = PendingIntent.getActivity(
-        context,
-        0 /* requestCode= */, Intent("PendingIntent 1"), FLAG_IMMUTABLE
-    )
-    private val iconAction1 = IconAction(ICON_TYPE_INFO, pendingIntent1)
-    private val pendingIntent2: PendingIntent = PendingIntent.getActivity(
-        context,
-        0 /* requestCode= */, Intent("PendingIntent 2"), FLAG_IMMUTABLE
-    )
-    private val iconAction2 = IconAction(ICON_TYPE_GEAR, pendingIntent2)
-
-    @Test
-    fun iconAction_getIconType_returnsIconType() {
-        val iconAction = IconAction(ICON_TYPE_INFO, pendingIntent1)
-
-        assertThat(iconAction.iconType).isEqualTo(ICON_TYPE_INFO)
-    }
-
-    @Test
-    fun iconAction_getPendingIntent_returnsPendingIntent() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
-        assertThat(iconAction.pendingIntent).isEqualTo(pendingIntent1)
-    }
-
-    @Test
-    fun iconAction_describeContents_returns0() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
-        assertThat(iconAction.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun iconAction_createFromParcel_withWriteToParcel_returnsOriginalAction() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
-        val parcel: Parcel = Parcel.obtain()
-        iconAction.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val iconActionFromParcel: IconAction = IconAction.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(iconActionFromParcel).isEqualTo(iconAction)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun iconAction_hashCode_equals_toString_withEqualByReferenceIconActions_areEqual() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-        val otherIconAction = iconAction
-
-        assertThat(iconAction.hashCode()).isEqualTo(otherIconAction.hashCode())
-        assertThat(iconAction).isEqualTo(otherIconAction)
-        assertThat(iconAction.toString()).isEqualTo(otherIconAction.toString())
-    }
-
-    @Test
-    fun iconAction_hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-        val otherIconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-
-        assertThat(iconAction.hashCode()).isEqualTo(otherIconAction.hashCode())
-        assertThat(iconAction).isEqualTo(otherIconAction)
-        assertThat(iconAction.toString()).isEqualTo(otherIconAction.toString())
-    }
-
-    @Test
-    fun iconAction_hashCode_equals_toString_withDifferentIconTypes_areNotEqual() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-        val otherIconAction = IconAction(ICON_TYPE_INFO, pendingIntent1)
-
-        assertThat(iconAction.hashCode()).isNotEqualTo(otherIconAction.hashCode())
-        assertThat(iconAction).isNotEqualTo(otherIconAction)
-        assertThat(iconAction.toString()).isNotEqualTo(otherIconAction.toString())
-    }
-
-    @Test
-    fun iconAction_hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
-        val iconAction = IconAction(ICON_TYPE_GEAR, pendingIntent1)
-        val otherIconAction = IconAction(ICON_TYPE_GEAR, pendingIntent2)
-
-        assertThat(iconAction.hashCode()).isNotEqualTo(otherIconAction.hashCode())
-        assertThat(iconAction).isNotEqualTo(otherIconAction)
-        assertThat(iconAction.toString()).isNotEqualTo(otherIconAction.toString())
-    }
-
-    @Test
-    fun getTitle_returnsTitle() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.title).isEqualTo("Status title")
-    }
-
-    @Test
-    fun getSummary_returnsSummary() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.summary).isEqualTo("Status summary")
-    }
-
-    @Test
-    fun getStatusLevel_returnsStatusLevel() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.statusLevel).isEqualTo(STATUS_LEVEL_OK)
-    }
-
-    @Test
-    fun getPendingIntent_returnsPendingIntent() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.pendingIntent).isEqualTo(pendingIntent1)
-    }
-
-    @Test
-    fun getIconAction_withDefaultBuilder_returnsNull() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.iconAction).isNull()
-    }
-
-    @Test
-    fun getIconAction_whenSetExplicitly_returnsIconAction() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .build()
-
-        assertThat(safetySourceStatus.iconAction).isEqualTo(iconAction1)
-    }
-
-    @Test
-    fun isEnabled_withDefaultBuilder_returnsTrue() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.isEnabled).isTrue()
-    }
-
-    @Test
-    fun isEnabled_whenSetExplicitly_returnsEnabled() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setEnabled(false)
-            .build()
-
-        assertThat(safetySourceStatus.isEnabled).isFalse()
-    }
-
-    @Test
-    fun describeContents_returns0() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .build()
-
-        assertThat(safetySourceStatus.describeContents()).isEqualTo(0)
-    }
-
-    @Test
-    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceStatus() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .setEnabled(true)
-            .build()
-
-        val parcel: Parcel = Parcel.obtain()
-        safetySourceStatus.writeToParcel(parcel, 0 /* flags */)
-        parcel.setDataPosition(0)
-        val safetySourceStatusFromParcel: SafetySourceStatus =
-            SafetySourceStatus.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(safetySourceStatusFromParcel).isEqualTo(safetySourceStatus)
-    }
-
-    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
-    @Test
-    fun hashCode_equals_toString_withEqualByReferenceSafetySourceStatuses_areEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .setEnabled(true)
-            .build()
-        val otherSafetySourceStatus = safetySourceStatus
-
-        assertThat(safetySourceStatus.hashCode()).isEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .setEnabled(true)
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .setEnabled(true)
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentTitles_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Other status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentSummaries_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Other status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentStatusLevels_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            pendingIntent1
-        )
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            pendingIntent1
-        )
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentPendingIntents_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_OK,
-            PendingIntent.getActivity(
-                context, 0 /* requestCode= */,
-                Intent("Status PendingIntent"), FLAG_IMMUTABLE
-            )
-        )
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            PendingIntent.getActivity(
-                context, 0 /* requestCode= */,
-                Intent("Other status PendingIntent"), FLAG_IMMUTABLE
-            )
-        )
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentIconActions_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            pendingIntent1
-        )
-            .setIconAction(iconAction1)
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            pendingIntent1
-        )
-            .setIconAction(iconAction2)
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-
-    @Test
-    fun hashCode_equals_toString_withDifferentEnabled_areNotEqual() {
-        val safetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            pendingIntent1
-        )
-            .setEnabled(true)
-            .build()
-        val otherSafetySourceStatus = SafetySourceStatus.Builder(
-            "Status title",
-            "Status summary",
-            STATUS_LEVEL_CRITICAL_WARNING,
-            pendingIntent1
-        )
-            .setEnabled(false)
-            .build()
-
-        assertThat(safetySourceStatus.hashCode()).isNotEqualTo(otherSafetySourceStatus.hashCode())
-        assertThat(safetySourceStatus).isNotEqualTo(otherSafetySourceStatus)
-        assertThat(safetySourceStatus.toString()).isNotEqualTo(otherSafetySourceStatus.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
deleted file mode 100644
index 9b77e99..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.cts
-
-import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.SafetyCenterConfig
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = TIRAMISU, codeName = "Tiramisu")
-class XmlConfigTest {
-    private val safetyCenterContext = SafetyCenterResourcesContext(getApplicationContext())
-
-    @Test
-    fun safetyCenterConfigResource_validConfig() {
-        // Assert that the parser validates the Safety Center config without throwing any exception
-        assertThat(SafetyCenterConfig.fromXml(safetyCenterContext.safetyCenterConfig!!)).isNotNull()
-    }
-}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/testers/AnyTester.kt b/tests/tests/safetycenter/src/android/safetycenter/testers/AnyTester.kt
deleted file mode 100644
index f3fbf77..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/testers/AnyTester.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.safetycenter.testers
-
-import com.google.common.truth.Truth.assertThat
-
-/** Collection of functions to test generic objects */
-object AnyTester {
-    /**
-     * Asserts that two generic objects are equal and that the values returned by the [hashCode] and
-     * [toString] methods for the two generic objects are also equal.
-     */
-    fun assertThatRepresentationsAreEqual(a: Any, b: Any) {
-        assertThat(a.hashCode()).isEqualTo(b.hashCode())
-        assertThat(a).isEqualTo(b)
-        assertThat(a.toString()).isEqualTo(b.toString())
-    }
-
-    /**
-     * Asserts that two generic objects are not equal and that the values returned by the [hashCode]
-     * and [toString] methods for the two generic objects are also not equal.
-     */
-    fun assertThatRepresentationsAreNotEqual(a: Any, b: Any) {
-        assertThat(a.hashCode()).isNotEqualTo(b.hashCode())
-        assertThat(a).isNotEqualTo(b)
-        assertThat(a.toString()).isNotEqualTo(b.toString())
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/testers/ParcelableTester.kt b/tests/tests/safetycenter/src/android/safetycenter/testers/ParcelableTester.kt
deleted file mode 100644
index f2c2482..0000000
--- a/tests/tests/safetycenter/src/android/safetycenter/testers/ParcelableTester.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package android.safetycenter.testers
-
-import android.os.Parcel
-import android.os.Parcelable
-import com.google.common.truth.Truth.assertThat
-
-/** Collection of functions to test [Parcelable] objects */
-object ParcelableTester {
-    /**
-     * Asserts that writing a [Parcelable] object to a [Parcel] and creating an object from that
-     * [Parcel] returns an object that is equal to the original [Parcelable] object.
-     */
-    fun <T : Parcelable> assertThatRoundTripReturnsOriginal(
-        parcelable: T,
-        creator: Parcelable.Creator<T>
-    ) {
-        val parcel: Parcel = Parcel.obtain()
-        parcelable.writeToParcel(parcel, 0)
-        parcel.setDataPosition(0)
-        val parcelableFromParcel: T = creator.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(parcelableFromParcel).isEqualTo(parcelable)
-    }
-}
\ No newline at end of file
diff --git a/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk b/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
index 53275fd..a53bf88 100644
--- a/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
+++ b/tests/tests/secure_element/omapi/apk/signed-CtsOmapiTestCases.apk
Binary files differ
diff --git a/tests/tests/security/native/encryption/Android.bp b/tests/tests/security/native/encryption/Android.bp
index 35eff99..d95cc83 100644
--- a/tests/tests/security/native/encryption/Android.bp
+++ b/tests/tests/security/native/encryption/Android.bp
@@ -17,6 +17,7 @@
     ],
     static_libs: [
         "libctssecurity_native_test_utils",
+        "libfscrypt",
     ],
     multilib: {
         lib32: {
diff --git a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
index b2274de..a8f87229 100644
--- a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
+++ b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
@@ -14,7 +14,12 @@
  * limitations under the License.
  */
 
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
+#include <cutils/properties.h>
 #include <fcntl.h>
+#include <fscrypt/fscrypt.h>
+#include <gtest/gtest.h>
 #include <linux/fscrypt.h>
 #include <setjmp.h>
 #include <signal.h>
@@ -22,21 +27,12 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
-#include <android-base/unique_fd.h>
-#include <cutils/properties.h>
-#include <gtest/gtest.h>
-
 #include "utils.h"
 
 // Non-upstream encryption modes that are used on some devices.
 #define FSCRYPT_MODE_AES_256_HEH 126
 #define FSCRYPT_MODE_PRIVATE 127
 
-// The relevant Android API levels
-#define Q_API_LEVEL 29
-#define R_API_LEVEL 30
-#define S_API_LEVEL 31
-
 #ifdef __arm__
 // For ARM32, assemble the 'aese.8' instruction as an .inst, since otherwise
 // clang does not accept it.  It would be allowed in a separate file compiled
@@ -179,9 +175,10 @@
 // likely case where this requirement wouldn't be met is a misconfiguration
 // where FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 ("emmc_optimized" in the fstab) is
 // used on a non-eMMC based device.  CTS can test for that, so we do so below.
-static void validateEncryptionFlags(int flags) {
+static void validateEncryptionFlags(int flags, bool is_adoptable_storage) {
     if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
         EXPECT_TRUE(mightBeUsingEmmcStorage());
+        EXPECT_FALSE(is_adoptable_storage);
     }
 }
 
@@ -192,14 +189,53 @@
 // way to configure different directories to use different algorithms...
 #define DIR_TO_CHECK "/data/local/tmp/"
 
-// Test that the device is using appropriate encryption algorithms for
-// file-based encryption.  If this test fails, you should ensure the device's
-// fstab has the correct fileencryption= option for the userdata partition.  See
+static std::string loggedGetProperty(const std::string &name, const std::string &default_value) {
+    auto value = android::base::GetProperty(name, "");
+    if (value == "" && default_value != "") {
+        GTEST_LOG_(INFO) << name << "=\"\" [defaults to \"" << default_value << "\"]";
+        return default_value;
+    }
+    GTEST_LOG_(INFO) << name << "=\"" << value << "\"";
+    return value;
+}
+
+static void validateAdoptableStorageSettings(int first_api_level) {
+    GTEST_LOG_(INFO) << "Validating FBE settings for adoptable storage";
+
+    // Determine the options string being used.  This matches the logic in vold.
+    auto contents_mode = loggedGetProperty("ro.crypto.volume.contents_mode", "");
+    auto filenames_mode =
+            loggedGetProperty("ro.crypto.volume.filenames_mode",
+                              first_api_level > __ANDROID_API_Q__ ? "" : "aes-256-heh");
+    auto options_string =
+            loggedGetProperty("ro.crypto.volume.options", contents_mode + ":" + filenames_mode);
+
+    // Parse the options string.
+    android::fscrypt::EncryptionOptions options;
+    ASSERT_TRUE(android::fscrypt::ParseOptions(options_string, &options));
+
+    // Log the full options for debugging purposes.
+    std::string options_string_full;
+    ASSERT_TRUE(android::fscrypt::OptionsToString(options, &options_string_full));
+    GTEST_LOG_(INFO) << "options_string_full=\"" << options_string_full << "\"";
+
+    // Validate the encryption options.
+    if (first_api_level > __ANDROID_API_Q__) {
+        // CDD 9.9.3/C-1-13 and 9.9.3/C-1-14, same as internal storage.
+        EXPECT_EQ(2, options.version);
+    }
+    validateEncryptionModes(options.contents_mode, options.filenames_mode, options.version == 1);
+    validateEncryptionFlags(options.flags, true);
+}
+
+// Test that the device is using appropriate settings for file-based encryption.
+// If this test fails, you should ensure that the device's fstab has the correct
+// fileencryption= option for the userdata partition and that the ro.crypto
+// system properties have been set to the correct values.  See
 // https://source.android.com/security/encryption/file-based.html
 TEST(FileBasedEncryptionPolicyTest, allowedPolicy) {
     int first_api_level = getFirstApiLevel();
     int vendor_api_level = getVendorApiLevel();
-    char crypto_type[PROPERTY_VALUE_MAX];
     struct fscrypt_get_policy_ex_arg arg;
     int res;
     int contents_mode;
@@ -207,13 +243,7 @@
     int flags;
     bool allow_legacy_modes = false;
 
-    android::base::unique_fd fd(open(DIR_TO_CHECK, O_RDONLY | O_CLOEXEC));
-    if (fd < 0) {
-        FAIL() << "Failed to open " DIR_TO_CHECK ": " << strerror(errno);
-    }
-
-    property_get("ro.crypto.type", crypto_type, "");
-    GTEST_LOG_(INFO) << "ro.crypto.type is '" << crypto_type << "'";
+    std::string crypto_type = loggedGetProperty("ro.crypto.type", "");
     GTEST_LOG_(INFO) << "First API level is " << first_api_level;
     GTEST_LOG_(INFO) << "Vendor API level is " << vendor_api_level;
 
@@ -221,13 +251,20 @@
     // SC or later.
     int min_api_level = (first_api_level < vendor_api_level) ? first_api_level
                                                              : vendor_api_level;
-    if (min_api_level >= S_API_LEVEL &&
-       !deviceSupportsFeature("android.hardware.security.model.compatible")) {
+    if (min_api_level >= __ANDROID_API_S__ &&
+        !deviceSupportsFeature("android.hardware.security.model.compatible")) {
         GTEST_SKIP()
             << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing.";
         return;
     }
 
+    GTEST_LOG_(INFO) << "Validating FBE settings for internal storage";
+
+    android::base::unique_fd fd(open(DIR_TO_CHECK, O_RDONLY | O_CLOEXEC));
+    if (fd < 0) {
+        FAIL() << "Failed to open " DIR_TO_CHECK ": " << strerror(errno);
+    }
+
     // Note: SELinux policy allows the shell domain to use these ioctls, but not
     // apps.  Therefore this test needs to be a real native test that's run
     // through the shell, not a JNI test run through an installed APK.
@@ -246,12 +283,12 @@
 
             // Starting with Android 10, file-based encryption is required on
             // new devices [CDD 9.9.2/C-0-3].
-            if (first_api_level < Q_API_LEVEL) {
+            if (first_api_level < __ANDROID_API_Q__) {
                 GTEST_LOG_(INFO)
                         << "Exempt from file-based encryption due to old starting API level";
                 return;
             }
-            if (strcmp(crypto_type, "managed") == 0) {
+            if (crypto_type == "managed") {
                 // Android is running in a virtualized environment and the file system is encrypted
                 // by the host system.
                 GTEST_LOG_(INFO) << "Exempt from file-based encryption because the file system is "
@@ -278,9 +315,9 @@
             // never be never reused for different cryptographic purposes
             // [CDD 9.9.3/C-1-14].  Effectively, these requirements mean that
             // the fscrypt policy version must not be v1.  If this part of the
-            // test fails, make sure the device's fstab has something like
-            // "fileencryption=aes-256-xts:aes-256-cts:v2".
-            if (first_api_level < R_API_LEVEL) {
+            // test fails, make sure the device's fstab doesn't contain the "v1"
+            // flag in the argument to the fileencryption option.
+            if (first_api_level < __ANDROID_API_R__) {
                 GTEST_LOG_(INFO) << "Exempt from non-reversible FBE key derivation due to old "
                                     "starting API level";
                 // On these old devices we also allow the use of some custom
@@ -305,6 +342,7 @@
     GTEST_LOG_(INFO) << "Filenames encryption mode: " << filenames_mode;
 
     validateEncryptionModes(contents_mode, filenames_mode, allow_legacy_modes);
+    validateEncryptionFlags(flags, false);
 
-    validateEncryptionFlags(flags);
+    validateAdoptableStorageSettings(first_api_level);
 }
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0341.java b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
new file mode 100644
index 0000000..130dce5
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0341.java
@@ -0,0 +1,221 @@
+/*
+ * 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.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionContext;
+import javax.security.cert.CertificateException;
+
+// Taken reference from
+// libcore/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
+class CVE_2021_0341_SSLSession implements SSLSession {
+
+    private byte[] idData;
+    private String nameHost = null;
+    private int namePort = -1;
+    private Hashtable table;
+    private boolean invalidateDone = false;
+    private Certificate[] certs = null;
+    private javax.security.cert.X509Certificate[] xCerts = null;
+
+    public CVE_2021_0341_SSLSession(Certificate[] xc)
+            throws CertificateEncodingException, CertificateException {
+        certs = xc;
+        xCerts = new javax.security.cert.X509Certificate[xc.length];
+        int i = 0;
+        for (Certificate cert : xc) {
+            xCerts[i++] = javax.security.cert.X509Certificate.getInstance(cert.getEncoded());
+        }
+    }
+
+    public int getApplicationBufferSize() {
+        return 1234567;
+    }
+
+    public String getCipherSuite() {
+        return "SuiteName";
+    }
+
+    public long getCreationTime() {
+        return 1000L;
+    }
+
+    public byte[] getId() {
+        return idData;
+    }
+
+    public long getLastAccessedTime() {
+        return 2000L;
+    }
+
+    public Certificate[] getLocalCertificates() {
+        return null;
+    }
+
+    public Principal getLocalPrincipal() {
+        return null;
+    }
+
+    public int getPacketBufferSize() {
+        return 12345;
+    }
+
+    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+        assumeFalse("peer not authenticated", (certs == null));
+        return certs;
+    }
+
+    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
+            throws SSLPeerUnverifiedException {
+        assumeFalse("peer not authenticated", (xCerts == null));
+        return xCerts;
+    }
+
+    public String getPeerHost() {
+        return nameHost;
+    }
+
+    public int getPeerPort() {
+        return namePort;
+    }
+
+    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+        return null;
+    }
+
+    public String getProtocol() {
+        return "ProtocolName";
+    }
+
+    public SSLSessionContext getSessionContext() {
+        return null;
+    }
+
+    public void putValue(String s, Object obj) {
+        assumeFalse("arguments can not be null", (s == null || obj == null));
+        Object obj1 = table.put(s, obj);
+        if (obj1 instanceof SSLSessionBindingListener) {
+            SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+            ((SSLSessionBindingListener) obj1).valueUnbound(sslsessionbindingevent);
+        }
+        if (obj instanceof SSLSessionBindingListener) {
+            SSLSessionBindingEvent sslsessionbindingevent1 = new SSLSessionBindingEvent(this, s);
+            ((SSLSessionBindingListener) obj).valueBound(sslsessionbindingevent1);
+        }
+    }
+
+    public void removeValue(String s) {
+        assumeFalse("argument can not be null", (s == null));
+        Object obj = table.remove(s);
+        if (obj instanceof SSLSessionBindingListener) {
+            SSLSessionBindingEvent sslsessionbindingevent = new SSLSessionBindingEvent(this, s);
+            ((SSLSessionBindingListener) obj).valueUnbound(sslsessionbindingevent);
+        }
+    }
+
+    public Object getValue(String s) {
+        assumeFalse("argument can not be null", (s == null));
+        return table.get(s);
+    }
+
+    public String[] getValueNames() {
+        Vector vector = new Vector();
+        Enumeration enumeration = table.keys();
+        while (enumeration.hasMoreElements()) {
+            vector.addElement(enumeration.nextElement());
+        }
+        String as[] = new String[vector.size()];
+        vector.copyInto(as);
+        return as;
+    }
+
+    public void invalidate() {
+        invalidateDone = true;
+    }
+
+    public boolean isValid() {
+        return invalidateDone;
+    }
+}
+
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0341 {
+
+    public final static byte[] X509_TEST_CERTIFICATE = ("-----BEGIN CERTIFICATE-----\n"
+            + "MIIC3DCCAcSgAwIBAgIURJspNgSx6GVbOLijqravWoGlm+0wDQYJKoZIhvcNAQEL\n"
+            + "BQAwETEPMA0GA1UECgwGZ29vZ2xlMB4XDTIyMDIxNzExNTE1NFoXDTMxMTExNzEx\n"
+            + "NTE1NFowETEPMA0GA1UECgwGZ29vZ2xlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n"
+            + "MIIBCgKCAQEA2PxVfeoY/uA66aVRXpuZXodTBFBGowTt/lAJxR8fVjDwRTOrRTrr\n"
+            + "2qdLPPK40lFQOSfHw/g6+9WjNjjSDBP+U2Agrvo8cU5R1DwJWyK2wcHOtBcL2bsj\n"
+            + "kRx18CZtZUu51a8KEhMCaIoHgGzwGMZkJnfmfO9ABbMfFsyn6KxFf0MXG3bRcQU7\n"
+            + "LyCXyQbo2Lal68QiTMXZs9rXN/a8ex+RmP9PKaXIEsIOeDrtLhzcWyNjrtTuDRoR\n"
+            + "K49xHOpz4EmqHLDzIKuhqyyo9tLR+okK0BRJoNxmfvRTbxNbjzpTTFgyB4KrKBCO\n"
+            + "VQXJROlBf7594xlCMn0QSwElVT4bMaMw/QIDAQABoywwKjAoBgNVHREEITAfggkq\n"
+            + "LmJhci5jb22CEiou44Kw44O844Kw44OrLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA\n"
+            + "piIwY84InjX4BUmAmM+D9CHD/9euucGxgdXqL6kKG1HRL6lHfwZAIxhlbn3jWFEx\n"
+            + "k5DTkaL039FGLvYzMI0McwTIuHY/7JwCbZUJ3pVl0waW4sab+2LScnpe9c422Tqb\n"
+            + "hECEhc71E/kRlG9FjQN3wjEj3RcnWZAWCqAnJN/dcd/1tBD88tzHVckDC9mSvxzP\n"
+            + "hkmIRRifIDxcrmx7PkpJ6dAfiw9e1Pl5THdsPTDtiGJ4hjlsAi8ury3rrx31lsyo\n"
+            + "kAwQy23Q7Rcbr2z8bijDuSWWWc9RRsz+O/ePy35NJci/RUwVFTpvOFtahC30Jdv3\n"
+            + "vpmqxLqEF7Z9I1yb3Q6YUg==\n" + "-----END CERTIFICATE-----\n").getBytes();
+
+    /**
+     * b/171980069
+     */
+    @AsbSecurityTest(cveBugId = 171980069)
+    @Test
+    public void testPocCVE_2021_0341() throws Exception {
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        assumeNotNull(cf);
+        HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
+        assumeNotNull(verifier);
+        InputStream in = new ByteArrayInputStream(X509_TEST_CERTIFICATE);
+        java.security.cert.X509Certificate x509 =
+                (java.security.cert.X509Certificate) cf.generateCertificate(in);
+        assumeNotNull(x509);
+        CVE_2021_0341_SSLSession session =
+                new CVE_2021_0341_SSLSession(new java.security.cert.X509Certificate[] {x509});
+        assertFalse(verifier.verify("\u82b1\u5b50.bar.com", session));
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
index b43f489..91e39e8 100644
--- a/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
+++ b/tests/tests/security/src/android/security/cts/IsolatedProcessTest.java
@@ -15,6 +15,7 @@
  */
 package android.security.cts;
 
+import android.app.Instrumentation;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -25,8 +26,8 @@
 import android.platform.test.annotations.AsbSecurityTest;
 import android.security.cts.IIsolatedService;
 import android.security.cts.IsolatedService;
-import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 import android.util.Log;
+import androidx.test.InstrumentationRegistry;
 import com.android.internal.util.ArrayUtils;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -39,7 +40,7 @@
 import org.junit.Test;
 
 @RunWith(AndroidJUnit4.class)
-public class IsolatedProcessTest extends StsExtraBusinessLogicTestCase {
+public class IsolatedProcessTest {
     static final String TAG = IsolatedProcessTest.class.getSimpleName();
 
     private static final long BIND_SERVICE_TIMEOUT = 5000;
@@ -72,6 +73,10 @@
         }
     };
 
+    private static Instrumentation getInstrumentation() {
+        return InstrumentationRegistry.getInstrumentation();
+    }
+
     @Before
     public void setUp() throws InterruptedException {
         mLatch = new CountDownLatch(1);
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
index 4271f74..5ec9a90 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
@@ -18,6 +18,7 @@
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -648,6 +649,7 @@
     protected boolean isAppSearchEnabled() {
         return SystemUtil.runWithShellPermissionIdentity(() ->
                 DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                        "shortcut_appsearch_integration", true));
+                        "shortcut_appsearch_integration", true))
+                && !getTestContext().getSystemService(ActivityManager.class).isLowRamDevice();
     }
 }
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ContentNotificationsTest.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ContentNotificationsTest.java
index 1bbf1dd..e9162ff 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ContentNotificationsTest.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookContract_ContentNotificationsTest.java
@@ -20,18 +20,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.hamcrest.Matchers.oneOf;
 import static org.junit.Assume.assumeThat;
-import static org.junit.Assume.assumeTrue;
-
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import android.Manifest;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
@@ -40,7 +35,6 @@
 import android.provider.SimPhonebookContract.ElementaryFiles;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 
 import androidx.annotation.Nullable;
 import androidx.test.core.app.ApplicationProvider;
@@ -50,9 +44,6 @@
 import com.android.compatibility.common.util.RequiredFeatureRule;
 import com.android.compatibility.common.util.SystemUtil;
 
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.SettableFuture;
-
 import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Before;
@@ -155,60 +146,6 @@
                 DEFAULT_TIMEOUT, () -> mObserver.observed.size() > 1);
     }
 
-    @Test
-    public void subscriptionsChange_notifiesObserver() throws Exception {
-        Resources resources = ApplicationProvider.getApplicationContext().getResources();
-        int id = resources.getIdentifier("config_hotswapCapable", "bool", "android");
-        boolean hotswapCapable = resources.getBoolean(id);
-        assumeTrue("Device does not support SIM hot swap", hotswapCapable);
-        assumeThat(mSubscriptionInfo, Matchers.notNullValue());
-        try {
-            setSimPower(0);
-
-            PollingCheck.check(
-                    "No content notifications observed for SIM removal",
-                    DEFAULT_TIMEOUT, () -> mObserver.observed.size() >= 1);
-            // It takes some time the SIM state transitions to finish so we sleep a bit to attempt
-            // to allow the notifications they trigger to stop so that the notifications we observe
-            // for the power on aren't polluted by the power off.
-            Thread.sleep(DEFAULT_TIMEOUT);
-            mObserver.observed.clear();
-        } finally {
-            setSimPower(1);
-        }
-        PollingCheck.check(
-                "No content notifications observed for SIM insertion",
-                DEFAULT_TIMEOUT, () -> mObserver.observed.size() >= 1);
-    }
-
-    private void setSimPower(int powerState) throws Exception {
-        TelephonyManager telephonyManager = ApplicationProvider.getApplicationContext()
-                .getSystemService(TelephonyManager.class);
-        int slotIndex = mSubscriptionInfo.getSimSlotIndex();
-        SettableFuture<Integer> resultFuture = SettableFuture.create();
-        SystemUtil.runWithShellPermissionIdentity(() -> telephonyManager.setSimPowerStateForSlot(
-                mSubscriptionInfo.getSimSlotIndex(), powerState,
-                MoreExecutors.directExecutor(), resultFuture::set),
-                Manifest.permission.MODIFY_PHONE_STATE, Manifest.permission.READ_PHONE_STATE);
-
-        int result = resultFuture.get(30, SECONDS);
-        assumeThat("setSimPowerStateForSlot failed for slot=" + slotIndex,
-                result, oneOf(
-                        TelephonyManager.SET_SIM_POWER_STATE_ALREADY_IN_STATE,
-                        TelephonyManager.SET_SIM_POWER_STATE_SUCCESS));
-        Thread.sleep(DEFAULT_TIMEOUT);
-        int simState = SystemUtil.runWithShellPermissionIdentity(() ->
-                        telephonyManager.getSimState(slotIndex),
-                Manifest.permission.READ_PHONE_STATE);
-        // This doesn't work on Cuttlefish so confirm the SIM was actually powered off.
-        if(powerState == 1) {
-            assumeThat(simState, Matchers.is(TelephonyManager.SIM_STATE_READY));
-        } else {
-            assumeThat(simState, Matchers.is(oneOf(TelephonyManager.SIM_STATE_ABSENT,
-                TelephonyManager.SIM_STATE_NOT_READY)));
-        }
-    }
-
     private static class RecordingContentObserver extends ContentObserver {
 
         List<Uri> observed = new CopyOnWriteArrayList<>();
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index 96a07b3..1b1d48e 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -79,6 +79,14 @@
             </intent-filter>
         </service>
 
+        <service android:name="android.telecom.cts.NullBindingConnectionService"
+                 android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+                 android:exported="true">
+            <intent-filter>
+                <action android:name="android.telecom.ConnectionService"/>
+            </intent-filter>
+        </service>
+
         <service android:name="android.telecom.cts.MockInCallService"
              android:permission="android.permission.BIND_INCALL_SERVICE"
              android:exported="true">
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
new file mode 100644
index 0000000..161d3ef
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingConnectionService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A minimal {@link Service} implementation intended to test cases where a {@link ConnectionService}
+ * tries to return a null binding.
+ */
+public class NullBindingConnectionService extends Service {
+    public static CountDownLatch sBindLatch = new CountDownLatch(1);
+    public static CountDownLatch sUnbindLatch = new CountDownLatch(1);
+
+    public NullBindingConnectionService() {
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        CountDownLatch latch = sBindLatch;
+        sUnbindLatch = new CountDownLatch(1);
+        latch.countDown();
+        return null;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        CountDownLatch latch = sUnbindLatch;
+        sBindLatch = new CountDownLatch(1);
+        latch.countDown();
+        return false;
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
new file mode 100644
index 0000000..611eeab
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/NullBindingTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom.cts;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+/**
+ * CTS tests to ensure that a ConnectionService which returns a null binding will be automatically
+ * unbound.
+ */
+
+public class NullBindingTest extends BaseTelecomTestWithMockServices {
+    private static final PhoneAccountHandle TEST_NULL_BINDING_HANDLE =
+            new PhoneAccountHandle(new ComponentName("android.telecom.cts",
+                    "android.telecom.cts.NullBindingConnectionService"),
+                    "1");
+
+    public static final PhoneAccount TEST_NULL_BINDING_ACCOUNT = PhoneAccount.builder(
+                    TEST_NULL_BINDING_HANDLE, "Null")
+            .setAddress(Uri.parse("sip:test@test.com"))
+            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+            .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
+            .build();
+
+    private static final Uri TEST_ADDRESS_1 = Uri.fromParts("sip", "call1@test.com", null);
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getContext();
+        if (mShouldTestTelecom) {
+            mTelecomManager.registerPhoneAccount(TEST_NULL_BINDING_ACCOUNT);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (mShouldTestTelecom) {
+            mTelecomManager.unregisterPhoneAccount(TEST_NULL_BINDING_HANDLE);
+        }
+    }
+
+    /**
+     * Ensures that when we bind to a ConnectionService which returns a null binding that the
+     * ConnectionService is unbound automatically.
+     */
+    public void testNullBinding() {
+        if (!mShouldTestTelecom) {
+            return;
+        }
+
+        // Place a call using the null binding connection service.
+        Bundle extras = new Bundle();
+        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEST_NULL_BINDING_HANDLE);
+        mTelecomManager.placeCall(TEST_ADDRESS_1, extras);
+
+        // Ensure it bound and then unbound.
+        assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sBindLatch));
+        assertTrue(TestUtils.waitForLatchCountDown(NullBindingConnectionService.sUnbindLatch));
+
+        // Ensure there is no call present in Telecom
+        assertFalse(mTelecomManager.isInCall());
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/DataServiceCallbackTest.java b/tests/tests/telephony/current/src/android/telephony/cts/DataServiceCallbackTest.java
new file mode 100644
index 0000000..1142fef
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/cts/DataServiceCallbackTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.telephony.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.InetAddresses;
+import android.net.LinkAddress;
+import android.os.IBinder;
+import android.telephony.data.ApnSetting;
+import android.telephony.data.DataCallResponse;
+import android.telephony.data.DataProfile;
+import android.telephony.data.DataServiceCallback;
+import android.telephony.data.IDataServiceCallback;
+import android.telephony.data.NetworkSliceInfo;
+import android.telephony.data.TrafficDescriptor;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DataServiceCallbackTest {
+    private static final int RESULT = DataServiceCallback.RESULT_SUCCESS;
+    private static final int ID = 1;
+    private static final int PROTOCOL_TYPE = ApnSetting.PROTOCOL_IP;
+    private static final int MTU_V4 = 1440;
+    private static final int MTU_V6 = 1400;
+    private static final TrafficDescriptor TRAFFIC_DESCRIPTOR = new TrafficDescriptor(
+            "DNN", new byte[]{-105, -92, -104, -29, -4, -110, 92, -108, -119, -122, 3, 51, -48, 110,
+                    78, 71, 10, 69, 78, 84, 69, 82, 80, 82, 73, 83, 69});
+    private static final DataCallResponse DATA_CALL_RESPONSE = new DataCallResponse.Builder()
+            .setCause(0)
+            .setRetryDurationMillis(-1L)
+            .setId(ID)
+            .setLinkStatus(2)
+            .setProtocolType(PROTOCOL_TYPE)
+            .setInterfaceName("IF_NAME")
+            .setAddresses(Arrays.asList(
+                    new LinkAddress(InetAddresses.parseNumericAddress("99.88.77.66"), 0)))
+            .setDnsAddresses(Arrays.asList(InetAddresses.parseNumericAddress("55.66.77.88")))
+            .setGatewayAddresses(Arrays.asList(InetAddresses.parseNumericAddress("11.22.33.44")))
+            .setPcscfAddresses(Arrays.asList(InetAddresses.parseNumericAddress("22.33.44.55")))
+            .setMtuV4(MTU_V4)
+            .setMtuV6(MTU_V6)
+            .setHandoverFailureMode(DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK)
+            .setPduSessionId(5)
+            .setSliceInfo(new NetworkSliceInfo.Builder()
+                    .setSliceServiceType(NetworkSliceInfo.SLICE_SERVICE_TYPE_EMBB)
+                    .setSliceDifferentiator(1)
+                    .setMappedHplmnSliceDifferentiator(10)
+                    .setMappedHplmnSliceServiceType(NetworkSliceInfo.SLICE_SERVICE_TYPE_MIOT)
+                    .build())
+            .setTrafficDescriptors(Arrays.asList(TRAFFIC_DESCRIPTOR))
+            .build();
+    private static final List<DataCallResponse> DATA_CALL_LIST = Arrays.asList(DATA_CALL_RESPONSE);
+    private static final String APN = "FAKE_APN";
+    private static final DataProfile DATA_PROFILE = new DataProfile.Builder()
+            .setApnSetting(new ApnSetting.Builder()
+                    .setEntryName(APN)
+                    .setApnName(APN)
+                    .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
+                    .setAuthType(ApnSetting.AUTH_TYPE_NONE)
+                    .setCarrierEnabled(true)
+                    .setModemCognitive(true)
+                    .setMtuV4(MTU_V4)
+                    .setMtuV6(MTU_V6)
+                    .setNetworkTypeBitmask(ApnSetting.TYPE_DEFAULT)
+                    .setProfileId(ID)
+                    .setPassword("PASSWORD")
+                    .setProtocol(PROTOCOL_TYPE)
+                    .setRoamingProtocol(PROTOCOL_TYPE)
+                    .setUser("USER_NAME")
+                    .build())
+            .setPreferred(true)
+            .setType(DataProfile.TYPE_COMMON)
+            .setTrafficDescriptor(TRAFFIC_DESCRIPTOR)
+            .build();
+
+    DataServiceCallback mDataServiceCallback;
+    int mResult;
+    DataCallResponse mResponse;
+    List<DataCallResponse> mDataCallList;
+    String mApn;
+    DataProfile mDataProfile;
+
+    private class TestDataServiceCallback implements IDataServiceCallback {
+        public void onSetupDataCallComplete(int result, DataCallResponse response) {
+            mResult = result;
+            mResponse = response;
+        }
+
+        public void onDeactivateDataCallComplete(int result) {
+            mResult = result;
+        }
+
+        public void onSetInitialAttachApnComplete(int result) {
+            mResult = result;
+        }
+
+        public void onSetDataProfileComplete(int result) {
+            mResult = result;
+        }
+
+        public void onRequestDataCallListComplete(int result, List<DataCallResponse> dataCallList) {
+            mResult = result;
+            mDataCallList = dataCallList;
+        }
+
+        public void onDataCallListChanged(List<DataCallResponse> dataCallList) {
+            mDataCallList = dataCallList;
+        }
+
+        public void onHandoverStarted(int result) {
+            mResult = result;
+        }
+
+        public void onHandoverCancelled(int result) {
+            mResult = result;
+        }
+
+        public void onApnUnthrottled(String apn) {
+            mApn = apn;
+        }
+
+        public void onDataProfileUnthrottled(DataProfile dataProfile) {
+            mDataProfile = dataProfile;
+        }
+
+        public IBinder asBinder() {
+            return null;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        mDataServiceCallback = new DataServiceCallback(new TestDataServiceCallback());
+    }
+
+    @Test
+    public void testOnSetupDataCallComplete() {
+        mDataServiceCallback.onSetupDataCallComplete(RESULT, DATA_CALL_RESPONSE);
+        assertThat(RESULT).isEqualTo(mResult);
+        assertThat(DATA_CALL_RESPONSE).isEqualTo(mResponse);
+    }
+
+    @Test
+    public void testOnDeactivateDataCallComplete() {
+        mDataServiceCallback.onDeactivateDataCallComplete(RESULT);
+        assertThat(RESULT).isEqualTo(mResult);
+    }
+
+    @Test
+    public void testOnSetInitialAttachApnComplete() {
+        mDataServiceCallback.onSetInitialAttachApnComplete(RESULT);
+        assertThat(RESULT).isEqualTo(mResult);
+    }
+
+    @Test
+    public void testOnSetDataProfileComplete() {
+        mDataServiceCallback.onSetDataProfileComplete(RESULT);
+        assertThat(RESULT).isEqualTo(mResult);
+    }
+
+    @Test
+    public void testOnRequestDataCallListComplete() {
+        mDataServiceCallback.onRequestDataCallListComplete(RESULT, DATA_CALL_LIST);
+        assertThat(RESULT).isEqualTo(mResult);
+        assertThat(DATA_CALL_LIST).isEqualTo(mDataCallList);
+    }
+
+    @Test
+    public void testOnDataCallListChanged() {
+        mDataServiceCallback.onDataCallListChanged(DATA_CALL_LIST);
+        assertThat(DATA_CALL_LIST).isEqualTo(mDataCallList);
+    }
+    @Test
+    public void testOnHandoverStarted() {
+        mDataServiceCallback.onHandoverStarted(RESULT);
+        assertThat(RESULT).isEqualTo(mResult);
+    }
+
+    @Test
+    public void testOnHandoverCancelled() {
+        mDataServiceCallback.onHandoverCancelled(RESULT);
+        assertThat(RESULT).isEqualTo(mResult);
+    }
+
+    @Test
+    public void testOnApnUnthrottled() {
+        mDataServiceCallback.onApnUnthrottled(APN);
+        assertThat(RESULT).isEqualTo(mResult);
+        assertThat(APN).isEqualTo(mApn);
+    }
+
+    @Test
+    public void testOnDataProfileUnthrottled() {
+        mDataServiceCallback.onDataProfileUnthrottled(DATA_PROFILE);
+        assertThat(RESULT).isEqualTo(mResult);
+        assertThat(DATA_PROFILE).isEqualTo(mDataProfile);
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SipManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SipManagerTest.java
deleted file mode 100644
index 9cd1ff3..0000000
--- a/tests/tests/telephony/current/src/android/telephony/cts/SipManagerTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.cts;
-
-import static androidx.test.InstrumentationRegistry.getContext;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.net.sip.SipException;
-import android.net.sip.SipManager;
-import android.net.sip.SipProfile;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.text.ParseException;
-import java.util.List;
-
-public class SipManagerTest {
-    private Context mContext;
-    private SipManager mSipManager;
-    private static final String SIP_URI1 = "test1";
-    private static final String SIP_URI2 = "test2";
-
-    @Before
-    public void setUp() {
-        mContext = getContext();
-        mSipManager = SipManager.newInstance(mContext);
-    }
-
-    @After
-    public void tearDown() throws SipException {
-        if (mSipManager != null) {
-            for (SipProfile profile : mSipManager.getProfiles()) {
-                mSipManager.close(profile.getUriString());
-            }
-        }
-    }
-
-    @Test
-    public void testGetProfiles() throws SipException, ParseException {
-        if (!SipManager.isApiSupported(mContext)) {
-            return;
-        }
-        SipProfile sipProfile1 = new SipProfile.Builder(SIP_URI1).build();
-        SipProfile sipProfile2 = new SipProfile.Builder(SIP_URI2).build();
-        mSipManager.open(sipProfile1);
-        mSipManager.open(sipProfile2);
-        List<SipProfile> profiles = mSipManager.getProfiles();
-        assertEquals(2, profiles.size());
-        assertTrue(profiles.get(0).getUriString().contains(SIP_URI2));
-        assertTrue(profiles.get(1).getUriString().contains(SIP_URI1));
-    }
-}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index aa02b4e..cb80083 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -3581,6 +3581,7 @@
                 (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
                         false));
 
+        waitForMs(500);
         boolean isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                         TelephonyManager.DATA_ENABLED_REASON_THERMAL));
@@ -3595,6 +3596,7 @@
                 (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
                         true));
 
+        waitForMs(500);
         isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                         TelephonyManager.DATA_ENABLED_REASON_THERMAL));
@@ -3617,6 +3619,7 @@
                 (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_POLICY,
                         false));
 
+        waitForMs(500);
         boolean isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                         TelephonyManager.DATA_ENABLED_REASON_POLICY));
@@ -3631,6 +3634,7 @@
                 (tm) -> tm.setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_POLICY,
                         true));
 
+        waitForMs(500);
         isDataEnabledForReason = ShellIdentityUtils.invokeMethodWithShellPermissions(
                 mTelephonyManager, (tm) -> tm.isDataEnabledForReason(
                         TelephonyManager.DATA_ENABLED_REASON_POLICY));
@@ -3728,6 +3732,7 @@
                         TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
                         !allowDataDuringVoiceCall));
 
+        waitForMs(500);
         assertNotEquals(allowDataDuringVoiceCall,
                 ShellIdentityUtils.invokeMethodWithShellPermissions(
                         mTelephonyManager, getPolicyHelper));
@@ -3737,6 +3742,7 @@
                         TelephonyManager.MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL,
                         allowDataDuringVoiceCall));
 
+        waitForMs(500);
         assertEquals(allowDataDuringVoiceCall,
                 ShellIdentityUtils.invokeMethodWithShellPermissions(
                         mTelephonyManager, getPolicyHelper));
@@ -3758,6 +3764,7 @@
                         TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
                         !mmsAlwaysAllowed));
 
+        waitForMs(500);
         assertNotEquals(mmsAlwaysAllowed,
                 ShellIdentityUtils.invokeMethodWithShellPermissions(
                         mTelephonyManager, getPolicyHelper));
@@ -3767,6 +3774,7 @@
                         TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
                         mmsAlwaysAllowed));
 
+        waitForMs(500);
         assertEquals(mmsAlwaysAllowed,
                 ShellIdentityUtils.invokeMethodWithShellPermissions(
                         mTelephonyManager, getPolicyHelper));
@@ -4821,9 +4829,22 @@
 
         try {
             mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(mSelfPackageName);
+            fail("TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone must be protected "
+                    + "with READ_PRIVILEGED_PHONE_STATE");
+        } catch (SecurityException expected) {
+        }
+
+        try {
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                    .adoptShellPermissionIdentity(
+                            "android.permission.READ_PRIVILEGED_PHONE_STATE");
+            mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(mSelfPackageName);
         } catch (SecurityException e) {
-            fail("TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone shouldn't require "
-                    + "READ_PRIVILEGED_PHONE_STATE");
+            fail("TelephonyManager#checkCarrierPrivilegesForPackageAnyPhone should not throw "
+                    + "SecurityException with READ_PRIVILEGED_PHONE_STATE permission");
+        } finally {
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                    .dropShellPermissionIdentity();
         }
     }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyRegistryManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyRegistryManagerTest.java
index e49fff9..367643c 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyRegistryManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyRegistryManagerTest.java
@@ -14,11 +14,13 @@
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.TelephonyManager.CarrierPrivilegesListener;
+import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 import android.telephony.TelephonyRegistryManager;
 import android.text.TextUtils;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -26,8 +28,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.Arrays;
-import java.util.List;
+import java.util.Set;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
@@ -271,73 +272,143 @@
     }
 
     @Test
-    public void testNotifyCarrierPrivilegesChanged() throws Exception {
+    public void testCarrierPrivilegesCallback() throws Exception {
         Context context = InstrumentationRegistry.getContext();
 
-        LinkedBlockingQueue<Pair<List<String>, int[]>> queue = new LinkedBlockingQueue(2);
-        CarrierPrivilegesListener cpl =
-                new CarrierPrivilegesListener() {
-                    @Override
-                    public void onCarrierPrivilegesChanged(
-                            List<String> privilegedPackageNames, int[] privilegedUids) {
-                        queue.offer(new Pair<>(privilegedPackageNames, privilegedUids));
-                    }
-                };
-        CarrierPrivilegesListener cpl2 =
-                (packageNames, uids) -> queue.offer(new Pair<>(packageNames, uids));
+        LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue =
+                new LinkedBlockingQueue(2);
+        LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue = new LinkedBlockingQueue(2);
+
+        CarrierPrivilegesCallback cpc = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue,
+                carrierServiceQueue);
+        CarrierPrivilegesCallback cpc2 = new TestCarrierPrivilegesCallback(carrierPrivilegesQueue,
+                carrierServiceQueue);
+
         TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
         try {
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                     telephonyManager,
-                    tm -> tm.addCarrierPrivilegesListener(0, context.getMainExecutor(), cpl));
-            // Clear the initial result from registering the listener. We can't necessarily
-            // guarantee this is empty so don't assert on it other than the fact we got _something_.
-            // We restore this at the end of the test.
-            Pair<List<String>, int[]> initialState =
-                    queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-            assertNotNull(initialState);
+                    tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc));
+            // Clear the initial carrierPrivilegesResult from registering the listener. We can't
+            // necessarily guarantee this is empty so don't assert on it other than the fact we
+            // got _something_. We restore this at the end of the test.
+            Pair<Set<String>, Set<Integer>> initialCarrierPrivilegesState =
+                    carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertNotNull(initialCarrierPrivilegesState);
+            Pair<String, Integer> initialCarrierServiceState =
+                    carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertNotNull(initialCarrierServiceState);
 
             // Update state
-            List<String> privilegedPackageNames =
-                    Arrays.asList("com.carrier.package1", "com.carrier.package2");
-            int[] privilegedUids = new int[] {12345, 54321};
+            Set<String> privilegedPackageNames =
+                    Set.of("com.carrier.package1", "com.carrier.package2");
+            Set<Integer> privilegedUids = Set.of(12345, 54321);
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                     mTelephonyRegistryMgr,
-                    trm ->
-                            trm.notifyCarrierPrivilegesChanged(
-                                    0, privilegedPackageNames, privilegedUids));
-            Pair<List<String>, int[]> result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-            assertEquals(privilegedPackageNames, result.first);
-            assertTrue(Arrays.equals(privilegedUids, result.second));
+                    trm -> {
+                        trm.notifyCarrierPrivilegesChanged(
+                                0, privilegedPackageNames, privilegedUids);
+                        trm.notifyCarrierServiceChanged(0, "com.carrier.package1", 12345);
+                    });
+            Pair<Set<String>, Set<Integer>> carrierPrivilegesResult =
+                    carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertEquals(privilegedPackageNames, carrierPrivilegesResult.first);
+            assertEquals(privilegedUids, carrierPrivilegesResult.second);
 
-            // Registering cpl2 now immediately gets us the most recent state
+            Pair<String, Integer> carrierServiceResult =
+                    carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertEquals("com.carrier.package1", carrierServiceResult.first);
+            assertEquals(12345, (long) carrierServiceResult.second);
+
+            // Update the state again, but only notify carrier privileges change this time
+            Set<String> newPrivilegedPackageNames = Set.of("com.carrier.package1",
+                    "com.carrier.package3");
+            Set<Integer> newPrivilegedUids = Set.of(12345, 678910);
+
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+                    mTelephonyRegistryMgr,
+                    trm -> {
+                        trm.notifyCarrierPrivilegesChanged(
+                                0, newPrivilegedPackageNames, newPrivilegedUids);
+                    });
+            // The CarrierPrivileges pkgs and UIDs should be updated
+            carrierPrivilegesResult =
+                    carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first);
+            assertEquals(newPrivilegedUids, carrierPrivilegesResult.second);
+
+            // And the CarrierService change notification should NOT be triggered
+            assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
+
+            // Registering cpc2 now immediately gets us the most recent state
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                     telephonyManager,
-                    tm -> tm.addCarrierPrivilegesListener(0, context.getMainExecutor(), cpl2));
-            result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-            assertEquals(privilegedPackageNames, result.first);
-            assertTrue(Arrays.equals(privilegedUids, result.second));
+                    tm -> tm.registerCarrierPrivilegesCallback(0, context.getMainExecutor(), cpc2));
+            carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+            assertEquals(newPrivilegedPackageNames, carrierPrivilegesResult.first);
+            assertEquals(newPrivilegedUids, carrierPrivilegesResult.second);
 
-            // Removing cpl means it won't get the final callback when we restore the original state
+            carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertEquals("com.carrier.package1", carrierServiceResult.first);
+            assertEquals(12345, (long) carrierServiceResult.second);
+
+            // Removing cpc means it won't get the final callback when we restore the original state
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
-                    telephonyManager, tm -> tm.removeCarrierPrivilegesListener(cpl));
+                    telephonyManager, tm -> tm.unregisterCarrierPrivilegesCallback(cpc));
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                     mTelephonyRegistryMgr,
-                    trm ->
-                            trm.notifyCarrierPrivilegesChanged(
-                                    0, initialState.first, initialState.second));
-            result = queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-            assertEquals(initialState.first, result.first);
-            assertTrue(Arrays.equals(initialState.second, result.second));
+                    trm -> {
+                        trm.notifyCarrierPrivilegesChanged(
+                                0, initialCarrierPrivilegesState.first,
+                                initialCarrierPrivilegesState.second);
+                        trm.notifyCarrierServiceChanged(0, initialCarrierServiceState.first,
+                                initialCarrierServiceState.second);
+                    });
+
+            carrierPrivilegesResult = carrierPrivilegesQueue.poll(TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+            assertEquals(initialCarrierPrivilegesState.first, carrierPrivilegesResult.first);
+            assertEquals(initialCarrierPrivilegesState.second, carrierPrivilegesResult.second);
+
+            carrierServiceResult = carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            assertEquals(initialCarrierServiceState.first, carrierServiceResult.first);
+            assertEquals(initialCarrierServiceState.second, carrierServiceResult.second);
+
             // No further callbacks received
-            assertNull(queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
+            assertNull(carrierPrivilegesQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
+            assertNull(carrierServiceQueue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
         } finally {
             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
                     telephonyManager,
                     tm -> {
-                        tm.removeCarrierPrivilegesListener(cpl); // redundant, but still allowed
-                        tm.removeCarrierPrivilegesListener(cpl2);
+                        tm.unregisterCarrierPrivilegesCallback(cpc); // redundant, but still allowed
+                        tm.unregisterCarrierPrivilegesCallback(cpc2);
                     });
         }
     }
+
+    private class TestCarrierPrivilegesCallback implements CarrierPrivilegesCallback {
+        LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> mCarrierPrivilegesQueue;
+        LinkedBlockingQueue<Pair<String, Integer>> mCarrierServiceQueue;
+
+        TestCarrierPrivilegesCallback(
+                LinkedBlockingQueue<Pair<Set<String>, Set<Integer>>> carrierPrivilegesQueue,
+                LinkedBlockingQueue<Pair<String, Integer>> carrierServiceQueue) {
+            mCarrierPrivilegesQueue = carrierPrivilegesQueue;
+            mCarrierServiceQueue = carrierServiceQueue;
+        }
+
+        @Override
+        public void onCarrierPrivilegesChanged(@NonNull Set<String> privilegedPackageNames,
+                @NonNull Set<Integer> privilegedUids) {
+            mCarrierPrivilegesQueue.offer(new Pair<>(privilegedPackageNames, privilegedUids));
+        }
+
+        @Override
+        public void onCarrierServiceChanged(@Nullable String carrierServicePackageName,
+                int carrierServiceUid) {
+            mCarrierServiceQueue.offer(new Pair<>(carrierServicePackageName, carrierServiceUid));
+        }
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java b/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
index e604c57..2cb2ecc 100644
--- a/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/euicc/cts/EuiccManagerTest.java
@@ -35,6 +35,7 @@
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccInfo;
 import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -595,21 +596,11 @@
             if (cardInfo.isEuicc()) {
                 for (UiccPortInfo portInfo : portInfoList) {
                     // Check if port is active and no profile install on it.
-                    if (portInfo.isActive() && portInfo.getIccId() == null) {
+                    if (portInfo.isActive() && TextUtils.isEmpty(portInfo.getIccId())) {
                         boolean result = mEuiccManager.isSimPortAvailable(portInfo.getPortIndex());
                         assertTrue(result);
-                    } else {
-                        // Port is not available.
-                        boolean result = mEuiccManager.isSimPortAvailable(portInfo.getPortIndex());
-                        assertFalse(result);
                     }
                 }
-            } else {
-                for (UiccPortInfo portInfo : portInfoList) {
-                    // Port is not Euicc.
-                    boolean result = mEuiccManager.isSimPortAvailable(portInfo.getPortIndex());
-                    assertFalse(result);
-                }
             }
         }
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index 01361ff..3495b66 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -1472,14 +1472,8 @@
                 ImsException.class);
 
         // IMS registers
-        ArraySet<String> featureTags = new ArraySet<>();
-        // Chat Session
-        featureTags.add(CHAT_FEATURE_TAG);
-        featureTags.add(FILE_TRANSFER_FEATURE_TAG);
-        ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
-                IMS_REGI_TECH_LTE).setFeatureTags(featureTags).build();
-        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(attr);
-        waitForParam(mQueue, attr);
+        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
+                IMS_REGI_TECH_LTE);
 
         // Notify framework that the RCS capability status is changed and PRESENCE UCE is enabled.
         RcsImsCapabilities capabilities =
@@ -1502,6 +1496,20 @@
         assertEquals(RcsUceAdapter.PUBLISH_STATE_OK, waitForIntResult(publishStateQueue));
         publishStateQueue.clear();
 
+        // IMS registers
+        ArraySet<String> featureTags = new ArraySet<>();
+        // Chat Session
+        featureTags.add(CHAT_FEATURE_TAG);
+        featureTags.add(FILE_TRANSFER_FEATURE_TAG);
+        ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
+                IMS_REGI_TECH_LTE).setFeatureTags(featureTags).build();
+        sServiceConnector.getCarrierService().getImsRegistration().onRegistered(attr);
+        waitForParam(mQueue, attr);
+
+        assertEquals(RcsUceAdapter.PUBLISH_STATE_PUBLISHING, waitForIntResult(publishStateQueue));
+        assertEquals(RcsUceAdapter.PUBLISH_STATE_OK, waitForIntResult(publishStateQueue));
+        publishStateQueue.clear();
+
         // Can not verify the pidf fully, but we can ensure that the service id for the feature is
         // contained in the XML. Multible PUBLISH requests may occur based on the state of the stack
         // at the time of this call, retry to get correct PIDF up to 5 times.
diff --git a/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java b/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java
index ceafff3..1713ffd 100644
--- a/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java
+++ b/tests/tests/text/src/android/text/cts/PrecomputedTextTest.java
@@ -25,7 +25,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -100,20 +99,22 @@
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
                 .setTextDirection(LTR).build());
 
-        LineBreakConfig lineBreakConfig = new LineBreakConfig();
-        lineBreakConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        LineBreakConfig strictNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
         assertNotNull(new Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setLineBreakConfig(lineBreakConfig)
+                .setLineBreakConfig(strictNoneConfig)
                 .setTextDirection(LTR).build());
 
-        LineBreakConfig lineBreakConfig2 = new LineBreakConfig();
-        lineBreakConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig nonePhraseConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
         assertNotNull(new Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
                 .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
-                .setLineBreakConfig(lineBreakConfig2)
+                .setLineBreakConfig(nonePhraseConfig)
                 .setTextDirection(LTR).build());
     }
 
@@ -127,9 +128,9 @@
         assertEquals(RTL, new Params.Builder(PAINT).setTextDirection(RTL).build()
                 .getTextDirection());
 
-        LineBreakConfig lineBreakConfig = new LineBreakConfig();
-        lineBreakConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
-        lineBreakConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig lineBreakConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
         assertTrue(lineBreakConfig.equals(new Params.Builder(PAINT)
                 .setLineBreakConfig(lineBreakConfig).build().getLineBreakConfig()));
     }
@@ -142,16 +143,22 @@
                      new Params.Builder(PAINT).build().getHyphenationFrequency());
         assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR,
                      new Params.Builder(PAINT).build().getTextDirection());
+    }
 
-        // Verify that there is no LineBreakConfig instance by default.
-        assertNull(new Params.Builder(PAINT).build().getLineBreakConfig());
+    @Test
+    public void testParams_defaultLineBreakConfig() {
+        // Verify it will return the pre-defined instance with the default value if the
+        // LineBreakConfig has not been set to Params before.
+        LineBreakConfig config = new Params.Builder(PAINT).build().getLineBreakConfig();
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, config.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, config.getLineBreakWordStyle());
     }
 
     @Test
     public void testParams_equals() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
-        config.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
 
         final Params base = new Params.Builder(PAINT)
                 .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingVariantsTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingVariantsTest.java
index 35772d4..502a91d 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingVariantsTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingVariantsTest.java
@@ -94,8 +94,9 @@
 
     @Test
     public void testBreakVariant_loose() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 90, SAMPLE_TEXT);
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 80,
                 "\u30D0\u30C3\u30C6\u30EA\u30FC\u30BB\u30FC\u30D0",
@@ -137,8 +138,9 @@
 
     @Test
     public void testBreakVariant_loose_text2() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 120, SAMPLE_TEXT2);
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 110,
                 "\u65B0\u3057\u3044\u6A5F\u7A2E\u3082\u6C17\u306B\u306A\u308B",
@@ -195,8 +197,9 @@
 
     @Test
     public void testBreakVariant_strict() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 90, SAMPLE_TEXT);
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 80,
                 "\u30D0\u30C3\u30C6\u30EA\u30FC\u30BB\u30FC",
@@ -239,8 +242,9 @@
 
     @Test
     public void testBreakVariant_strict_text2() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 120, SAMPLE_TEXT2);
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 110,
                 "\u65B0\u3057\u3044\u6A5F\u7A2E\u3082\u6C17\u306B\u306A\u308B",
@@ -298,8 +302,9 @@
 
     @Test
     public void testBreakVariant_phrase() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 90, SAMPLE_TEXT);
         assertLineBreak(SAMPLE_TEXT, "ja-JP", config, 80,
                 "\u30D0\u30C3\u30C6\u30EA\u30FC\u30BB\u30FC\u30D0",
@@ -341,8 +346,9 @@
 
     @Test
     public void testBreakVariant_phrase_text2() {
-        LineBreakConfig config = new LineBreakConfig();
-        config.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig config = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 120, SAMPLE_TEXT2);
         assertLineBreak(SAMPLE_TEXT2, "ja-JP", config, 110,
                 "\u65B0\u3057\u3044\u6A5F\u7A2E\u3082\u6C17\u306B",
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 5322a3d..3ce16a6 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -241,8 +241,9 @@
         }
         {
             // setLineBreakConfig
-            LineBreakConfig lineBreakConfig = new LineBreakConfig();
-            lineBreakConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+            LineBreakConfig lineBreakConfig = new LineBreakConfig.Builder()
+                    .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                    .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
             StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0,
                     LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH);
@@ -256,8 +257,9 @@
         }
         {
             // setLineBreakConfig with word style(lw=phrase)
-            LineBreakConfig lineBreakConfig = new LineBreakConfig();
-            lineBreakConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+            LineBreakConfig lineBreakConfig = new LineBreakConfig.Builder()
+                    .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                    .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
 
             StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0,
                     LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH);
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
index 72550c4..d86ffb1 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/SelectionEventTest.java
@@ -16,6 +16,11 @@
 
 package android.view.textclassifier.cts;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import android.view.textclassifier.SelectionEvent;
+import android.view.textclassifier.TextClassifier;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -27,7 +32,23 @@
 public class SelectionEventTest {
 
     @Test
-    public void testSelectionEvent_placeholder() {
-        // TODO: add tests for SelectionEvent
+    public void testSelectionEvent() {
+        SelectionEvent event = SelectionEvent.createSelectionActionEvent(0, 1,
+                SelectionEvent.ACTION_COPY);
+        assertThat(event.getEventType()).isEqualTo(SelectionEvent.ACTION_COPY);
+        assertThat(event.getStart()).isEqualTo(0);
+        assertThat(event.getEnd()).isEqualTo(0);
+        assertThat(event.getInvocationMethod()).isEqualTo(SelectionEvent.INVOCATION_UNKNOWN);
+        assertThat(event.getEntityType()).isEqualTo(TextClassifier.TYPE_UNKNOWN);
+        assertThat(event.getEventIndex()).isEqualTo(0);
+        assertThat(event.getPackageName()).isEqualTo("");
+        assertThat(event.getSmartStart()).isEqualTo(0);
+        assertThat(event.getSmartEnd()).isEqualTo(0);
+        assertThat(event.getWidgetType()).isEqualTo(TextClassifier.WIDGET_TYPE_UNKNOWN);
+        assertThat(event.getWidgetVersion()).isNull();
+        assertThat(event.getResultId()).isEqualTo("");
+        assertThat(event.getEventTime()).isEqualTo(0);
+        assertThat(event.getDurationSinceSessionStart()).isEqualTo(0);
+        assertThat(event.getDurationSincePreviousEvent()).isEqualTo(0);
     }
 }
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
index 1414ed7..3592c96 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextLinksTest.java
@@ -231,6 +231,7 @@
         assertNull(request.getDefaultLocales());
         assertTrue(request.getExtras().isEmpty());
         assertNull(request.getEntityConfig());
+        assertNull(request.getCallingPackageName());
     }
 
     @Test
@@ -253,6 +254,7 @@
                 TextClassifier.HINT_TEXT_IS_EDITABLE,
                 request.getEntityConfig().getHints().iterator().next());
         assertEquals(referenceTime, request.getReferenceTime());
+        assertNull(request.getCallingPackageName());
     }
 
 }
diff --git a/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppManagerTest.java b/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppManagerTest.java
index f108fd0..9162020 100644
--- a/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppManagerTest.java
+++ b/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppManagerTest.java
@@ -158,7 +158,7 @@
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mManager.registerCallback(mCallback, getExecutor());
+                mManager.registerCallback(getExecutor(), mCallback);
             }
         });
     }
@@ -264,8 +264,7 @@
         PollingCheck.waitFor(
                 TIME_OUT_MS, () -> StubTvInteractiveAppService.sAppLinkInfo == null);
 
-        info = new AppLinkInfo.Builder("pkg1", "class1").setPackageName("pkg2")
-                .setClassName("class2").setUriScheme("url1").setUriHost("host2")
+        info = new AppLinkInfo.Builder("pkg1", "class1").setUriScheme("url1").setUriHost("host2")
                 .setUriPrefix("prefix").build();
 
         mManager.registerAppLinkInfo(stubInfo.getId(), info);
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index 626f08d..8e39664 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -649,7 +649,7 @@
         TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback();
 
         // add it as sharee
-        lnb.addCallback(lnbCB2, getExecutor());
+        lnb.addCallback(getExecutor(), lnbCB2);
 
         // check callback
         lnb.sendDiseqcMessage(new byte[] {1, 2});
@@ -1565,7 +1565,7 @@
 
         // add sharee and check the callback
         TunerTestLnbCallback lnbCB2 = new TunerTestLnbCallback();
-        lnbA.addCallback(lnbCB2, getExecutor());
+        lnbA.addCallback(getExecutor(), lnbCB2);
         lnbA.sendDiseqcMessage(new byte[] {1, 2});
         assertTrue(lnbCB1.getOnDiseqcMessageCalled());
         lnbCB1.resetOnDiseqcMessageCalled();
diff --git a/tests/tests/uidmigration/Android.bp b/tests/tests/uidmigration/Android.bp
index 92db2e1..4f98ae6 100644
--- a/tests/tests/uidmigration/Android.bp
+++ b/tests/tests/uidmigration/Android.bp
@@ -24,6 +24,7 @@
         "androidx.test.rules",
         "ctstestrunner-axt",
         "permission-test-util-lib",
+        "services.core",
         "CtsSharedUserMigrationTestLibs",
     ],
     libs: [
@@ -36,5 +37,5 @@
         "cts",
         "general-tests",
     ],
-    sdk_version: "test_current",
+    platform_apis: true,
 }
diff --git a/tests/tests/uidmigration/DataTestApp/AndroidManifest2.xml b/tests/tests/uidmigration/DataTestApp/AndroidManifest2.xml
index 17fb471..996cc80 100644
--- a/tests/tests/uidmigration/DataTestApp/AndroidManifest2.xml
+++ b/tests/tests/uidmigration/DataTestApp/AndroidManifest2.xml
@@ -17,8 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.uidmigration.cts.DataTestApp"
     android:sharedUserId="android.uidmigration.cts"
-    android:sharedUserMaxSdkVersion="32"
-    android:inheritKeyStoreKeys="true" >
+    android:sharedUserMaxSdkVersion="32" >
 
     <queries>
         <package android:name="android.uidmigration.cts" />
diff --git a/tests/tests/uidmigration/DataTestApp/src/android/uidmigration/cts/DataProvider.kt b/tests/tests/uidmigration/DataTestApp/src/android/uidmigration/cts/DataProvider.kt
index 10e2fbc..ef77854 100644
--- a/tests/tests/uidmigration/DataTestApp/src/android/uidmigration/cts/DataProvider.kt
+++ b/tests/tests/uidmigration/DataTestApp/src/android/uidmigration/cts/DataProvider.kt
@@ -18,24 +18,11 @@
 import android.content.Context
 import android.content.SharedPreferences
 import android.os.Bundle
-import android.security.keystore.KeyGenParameterSpec
-import android.security.keystore.KeyProperties
-import android.util.Log
-import java.nio.charset.StandardCharsets.UTF_8
-import java.security.GeneralSecurityException
-import java.security.KeyPairGenerator
-import java.security.KeyStore
-import java.security.MessageDigest
-import java.security.Signature
 import java.util.UUID
-import javax.crypto.Cipher
-import javax.crypto.KeyGenerator
-import javax.crypto.spec.IvParameterSpec
 
 class DataProvider : BaseProvider() {
 
     companion object {
-        private const val ANDROID_KEYSTORE = "AndroidKeyStore"
         private const val RESULT_KEY = "result"
     }
 
@@ -59,126 +46,9 @@
         return data
     }
 
-    // Generate new AES secret key and encrypt arg.
-    private fun encryptAES(arg: String): Bundle {
-        val keyAlias = "aes"
-        val result = Bundle()
-        try {
-            val keyGen = KeyGenerator.getInstance(
-                KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE
-            )
-            val spec = KeyGenParameterSpec.Builder(
-                keyAlias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
-            )
-                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
-                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
-                .setKeySize(256)
-                .build()
-            keyGen.init(spec)
-            val key = keyGen.generateKey()
-            val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
-            cipher.init(Cipher.ENCRYPT_MODE, key)
-            val enc = cipher.doFinal(arg.toByteArray(UTF_8))
-            val iv = cipher.iv
-            result.putByteArray(RESULT_KEY, enc)
-            result.putByteArray("iv", iv)
-        } catch (e: Exception) {
-            Log.e("DataTestApp", "Crypto error", e)
-        }
-        return result
-    }
-
-    // Decrypt provided data with iv + key in keystore.
-    private fun decryptAES(extra: Bundle): Bundle {
-        val keyAlias = "aes"
-        val result = Bundle()
-        val enc = extra.getByteArray(RESULT_KEY)
-        val iv = extra.getByteArray("iv")
-        if (enc == null || iv == null) return result
-        try {
-            val ks = KeyStore.getInstance(ANDROID_KEYSTORE)
-            ks.load(null)
-
-            // Fetch the existing key in keystore.
-            val entry = ks.getEntry(keyAlias, null) as KeyStore.SecretKeyEntry
-            val key = entry.secretKey
-            val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
-            val ivSpec = IvParameterSpec(iv)
-            cipher.init(Cipher.DECRYPT_MODE, key, ivSpec)
-            val dec = cipher.doFinal(enc)
-            result.putString(RESULT_KEY, String(dec, UTF_8))
-        } catch (e: Exception) {
-            Log.e("DataTestApp", "Crypto error", e)
-        }
-        return result
-    }
-
-    @Throws(GeneralSecurityException::class)
-    private fun ecCertChainDigest(ks: KeyStore): ByteArray? {
-        val keyAlias = "ec"
-        val certs = ks.getCertificateChain(keyAlias) ?: return null
-        val digest = MessageDigest.getInstance("SHA256")
-        for (cert in certs) {
-            digest.update(cert.encoded)
-        }
-        return digest.digest()
-    }
-
-    // Generates a new EC keypair in keystore, and return the signed signature data.
-    private fun signEC(args: String): Bundle {
-        val keyAlias = "ec"
-        val result = Bundle()
-        val data = args.toByteArray(UTF_8)
-        try {
-            val kpg = KeyPairGenerator.getInstance(
-                KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE
-            )
-            val spec = KeyGenParameterSpec.Builder(
-                keyAlias, KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
-            )
-                .setDigests(KeyProperties.DIGEST_SHA256)
-                .setAttestationChallenge(UUID.randomUUID().toString().toByteArray(UTF_8))
-                .build()
-            kpg.initialize(spec)
-            val kp = kpg.generateKeyPair()
-            val s = Signature.getInstance("SHA256withECDSA")
-            s.initSign(kp.private)
-            s.update(data)
-            result.putByteArray(RESULT_KEY, s.sign())
-            val ks = KeyStore.getInstance(ANDROID_KEYSTORE)
-            ks.load(null)
-            result.putByteArray("certChain", ecCertChainDigest(ks))
-        } catch (e: Exception) {
-            Log.e("DataTestApp", "Crypto error", e)
-        }
-        return result
-    }
-
-    // Fetch the previously generated EC keypair and returns the certificate.
-    private fun getEcCert(): Bundle {
-        val keyAlias = "ec"
-        val result = Bundle()
-        try {
-            val ks = KeyStore.getInstance(ANDROID_KEYSTORE)
-            ks.load(null)
-
-            // Fetch the existing key in keystore.
-            val entry = ks.getEntry(keyAlias, null) as KeyStore.PrivateKeyEntry
-            result.putByteArray(RESULT_KEY, entry.certificate.encoded)
-            result.putByteArray("certChain", ecCertChainDigest(ks))
-        } catch (e: Exception) {
-            Log.e("DataTestApp", "Crypto error", e)
-        }
-        return result
-    }
-
     override fun call(method: String, arg: String?, extras: Bundle?): Bundle {
         return when (method) {
             "data" -> checkData()
-            "encryptAES" -> encryptAES(arg!!)
-            "decryptAES" -> decryptAES(extras!!)
-            "signEC" -> signEC(arg!!)
-            "getECCert" -> getEcCert()
             else -> Bundle()
         }
     }
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
new file mode 100644
index 0000000..cb84f3f
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
@@ -0,0 +1,145 @@
+/*
+ * 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.uidmigration.cts
+
+import android.Manifest.permission.INTERNET
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PackageInfoFlags
+import android.permission.cts.PermissionUtils
+import android.permission.cts.PermissionUtils.isPermissionGranted
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.server.pm.SharedUidMigration.LIVE_TRANSITION
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+
+// All tests ignored: appId migration is disabled (http://b/220015249)
+@RunWith(AndroidJUnit4::class)
+class AppIdMigrationTest {
+
+    companion object {
+        private const val RESULT_KEY = "result"
+    }
+
+    private lateinit var mContext: Context
+    private lateinit var mPm: PackageManager
+
+    @Before
+    fun setup() {
+        mContext = ApplicationProvider.getApplicationContext<Context>()
+        mPm = mContext.packageManager
+    }
+
+    @After
+    fun tearDown() {
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        uninstallPackage(Const.PERM_TEST_PKG)
+        uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
+        uninstallPackage(Const.DATA_TEST_PKG)
+    }
+
+    @Ignore
+    @Test
+    fun testAppInstall() = withStrategy(LIVE_TRANSITION) {
+        assertTrue(installPackage(InstallTest.APK))
+        assertTrue(installPackage(InstallTest.APK2))
+
+        // Both app should share the same UID.
+        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(2, pkgs.size)
+
+        // Should not allow upgrading to an APK that directly removes sharedUserId.
+        assertFalse(installPackage(InstallTest.APK3))
+
+        // Leave shared UID.
+        assertTrue(installPackage(InstallTest.APK4))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(1, pkgs.size)
+
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+    }
+
+    @Ignore
+    @Test
+    fun testPermissionMigration() = withStrategy(LIVE_TRANSITION) {
+        val apk = "$TMP_APK_PATH/PermissionTestApp"
+        assertTrue(installPackage(apk + "1.apk"))
+        assertTrue(installPackage(apk + "2.apk"))
+        val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+
+        // Runtime permissions are not granted by default.
+        assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+        // Grant a runtime permission.
+        PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
+
+        // All apps in the UID group should have the same permissions.
+        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+        // Upgrade and leave shared UID.
+        assertTrue(installPackage(apk + "3.apk"))
+
+        // The app in the original UID group should no longer have the permissions.
+        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+
+        // The upgraded app should still have the permissions.
+        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+        uninstallPackage(Const.PERM_TEST_PKG)
+        uninstallPackage(secondaryPkg)
+    }
+
+    @Ignore
+    @Test
+    fun testDataMigration() = withStrategy(LIVE_TRANSITION) {
+        val apk = "$TMP_APK_PATH/DataTestApp"
+        assertTrue(installPackage(apk + "1.apk"))
+        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        val authority = Const.DATA_TEST_PKG + ".provider"
+        val resolver = mContext.contentResolver
+
+        // Ask the app to generate a new random UUID and persist in data.
+        var result = resolver.call(authority, "data", null, null).assertNotNull()
+        val oldUUID = result.getString(RESULT_KEY).assertNotNull()
+
+        // Update the data test APK and make sure UID changed.
+        assertTrue(installPackage(apk + "2.apk"))
+        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        assertNotEquals(oldUid, newUid)
+
+        // Ask the app again for a UUID. If data migration is working, it shall be the same.
+        result = resolver.call(authority, "data", null, null).assertNotNull()
+        val newUUID = result.getString(RESULT_KEY)
+        assertEquals(oldUUID, newUUID)
+        uninstallPackage(Const.DATA_TEST_PKG)
+    }
+}
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
new file mode 100644
index 0000000..a525ff8
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.uidmigration.cts
+
+import android.content.pm.PackageManager
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration
+import com.android.server.pm.SharedUidMigration.PROPERTY_KEY
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+
+const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
+
+val FLAG_ZERO = PackageManager.PackageInfoFlags.of(0)
+
+// What each APK meant
+// APK : pkg , with sharedUserId
+// APK2: pkg2, with sharedUserId
+// APK3: pkg , with sharedUserId removed
+// APK4: pkg , with sharedUserMaxSdkVersion="32"
+
+object InstallTest {
+    const val APK = "$TMP_APK_PATH/InstallTestApp.apk"
+    const val APK2 = "$TMP_APK_PATH/InstallTestApp2.apk"
+    const val APK3 = "$TMP_APK_PATH/InstallTestApp3.apk"
+    const val APK4 = "$TMP_APK_PATH/InstallTestApp4.apk"
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun <T> T?.assertNotNull(): T {
+    assertNotNull(this)
+    return this!!
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
+
+fun installPackage(apkPath: String): Boolean {
+    return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
+}
+
+fun uninstallPackage(packageName: String) {
+    runShellCommand("pm uninstall $packageName")
+}
+
+@SharedUidMigration.Strategy
+var migrationStrategy: Int
+    get() = SharedUidMigration.getCurrentStrategy()
+    set(value) { runShellCommand("setprop $PROPERTY_KEY $value") }
+
+inline fun withStrategy(strategy: Int? = null, body: () -> Unit) {
+    if (SharedUidMigration.isDisabled()) {
+        // Nothing to test if shared UID migration is disabled
+        return
+    }
+
+    val backup = migrationStrategy
+    strategy?.let { migrationStrategy = it }
+    try {
+        body.invoke()
+    } finally {
+        // Always restore the device state no matter what happened
+        migrationStrategy = backup
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
index 9c71b7c..3958a12 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
@@ -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.
@@ -13,63 +13,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.uidmigration.cts
 
-import android.Manifest.permission.INTERNET
-import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
-import android.content.BroadcastReceiver
 import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
 import android.content.pm.PackageManager
-import android.content.pm.PackageManager.PackageInfoFlags
-import android.permission.cts.PermissionUtils
-import android.permission.cts.PermissionUtils.isPermissionGranted
+import android.os.Build
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration.BEST_EFFORT
+import com.android.server.pm.SharedUidMigration.NEW_INSTALL_ONLY
 import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.io.ByteArrayInputStream
-import java.nio.charset.StandardCharsets.UTF_8
-import java.security.Signature
-import java.security.cert.CertificateFactory
-import java.security.cert.X509Certificate
-import java.util.UUID
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import java.util.concurrent.TimeUnit
-import org.junit.Assert.assertArrayEquals
-import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 class SharedUserMigrationTest {
 
-    companion object {
-        private const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
-        private const val RESULT_KEY = "result"
-        private val NOT_AN_ERROR = Throwable()
-    }
-
     private lateinit var mContext: Context
     private lateinit var mPm: PackageManager
 
-    @Suppress("NOTHING_TO_INLINE")
-    private inline fun <T> T?.assertNotNull(): T {
-        assertNotNull(this)
-        return this!!
-    }
-
-    @Suppress("NOTHING_TO_INLINE")
-    private inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
-
     @Before
     fun setup() {
         mContext = ApplicationProvider.getApplicationContext<Context>()
@@ -80,248 +49,97 @@
     fun tearDown() {
         uninstallPackage(Const.INSTALL_TEST_PKG)
         uninstallPackage(Const.INSTALL_TEST_PKG + "2")
-        uninstallPackage(Const.PERM_TEST_PKG)
-        uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
-        uninstallPackage(Const.DATA_TEST_PKG)
     }
 
-    @Test
-    fun testAppInstall() {
-        val apk = "$TMP_APK_PATH/InstallTestApp"
-        assertTrue(installPackage("$apk.apk"))
-        assertTrue(installPackage(apk + "2.apk"))
-
-        // Both app should share the same UID.
-        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
-        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+    // Restore and ensure both test apps are sharing UID.
+    private fun reset(uid: Int) {
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        assertTrue(installPackage(InstallTest.APK))
+        val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         assertEquals(2, pkgs.size)
+    }
 
-        // Should not allow directly removing sharedUserId.
-        assertFalse(installPackage(apk + "3.apk"))
+    private fun testNewInstallOnly(uid: Int) {
+        migrationStrategy = NEW_INSTALL_ONLY
 
-        // Leave shared UID.
-        assertTrue(installPackage(apk + "4.apk"))
+        // Should not allow upgrading to an APK that directly removes sharedUserId.
+        assertFalse(installPackage(InstallTest.APK3))
+
+        // Directly parsing APK4 should return no sharedUserId.
+        var pkgInfo = mPm.getPackageArchiveInfo(InstallTest.APK4, FLAG_ZERO).assertNotNull()
+        assertNull(pkgInfo.sharedUserId)
+
+        assertTrue(installPackage(InstallTest.APK4))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // With NEW_INSTALL_ONLY, upgrades should not change appId.
+        assertEquals(2, pkgs.size)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNotNull(pkgInfo.sharedUserId)
+
+        // Should not allow re-joining sharedUserId.
+        assertFalse(installPackage(InstallTest.APK))
+
+        // Uninstall and install a new pkg leaving shared UID
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        assertTrue(installPackage(InstallTest.APK4))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // Newly installed apps with sharedUserMaxSdkVersion set should not join shared UID.
+        assertEquals(1, pkgs.size)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNull(pkgInfo.sharedUserId)
+    }
+
+    private fun testBestEffort(uid: Int) {
+        migrationStrategy = BEST_EFFORT
+
+        assertTrue(installPackage(InstallTest.APK4))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // With BEST_EFFORT, upgrades should also not change appId.
+        assertEquals(2, pkgs.size)
+        var pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNotNull(pkgInfo.sharedUserId)
+
+        val oldUidName = mPm.getNameForUid(uid)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+
+        // There should be only 1 package left in the shared UID group.
+        // This should trigger the transparent shared UID migration.
         pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         assertEquals(1, pkgs.size)
 
-        // Should not allow re-joining sharedUserId.
-        assertFalse(installPackage("$apk.apk"))
+        // Confirm that the internal PackageSetting is actually migrated.
+        val newUidName = mPm.getNameForUid(uid)
+        assertNotEquals(oldUidName, newUidName)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNull(pkgInfo.sharedUserId)
 
-        uninstallPackage(Const.INSTALL_TEST_PKG)
-        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        // Even installing another shared UID app, the appId shall not be reused.
+        assertTrue(installPackage(InstallTest.APK2))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(1, pkgs.size)
     }
 
     @Test
-    fun testPermissionMigration() {
-        val apk = "$TMP_APK_PATH/PermissionTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        assertTrue(installPackage(apk + "2.apk"))
-        val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+    fun testAppInstall() = withStrategy {
+        assertTrue(installPackage(InstallTest.APK))
+        assertTrue(installPackage(InstallTest.APK2))
 
-        // Runtime permissions are not granted by default.
-        assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+        // Both app should share the same UID.
+        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(2, pkgs.size)
 
-        // Grant a runtime permission.
-        PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
-
-        // All apps in the UID group should have the same permissions.
-        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
-        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
-        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
-        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
-
-        // Upgrade and leave shared UID.
-        assertTrue(installPackage(apk + "3.apk"))
-
-        // The app in the original UID group should no longer have the permissions.
-        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
-        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
-
-        // The upgraded app should still have the permissions.
-        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
-        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
-        uninstallPackage(Const.PERM_TEST_PKG)
-        uninstallPackage(secondaryPkg)
-    }
-
-    @Test
-    fun testDataMigration() {
-        val apk = "$TMP_APK_PATH/DataTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        val authority = Const.DATA_TEST_PKG + ".provider"
-        val resolver = mContext.contentResolver
-
-        // Ask the app to generate a new random UUID and persist in data.
-        var result = resolver.call(authority, "data", null, null).assertNotNull()
-        val oldUUID = result.getString(RESULT_KEY).assertNotNull()
-
-        val receiver = PackageBroadcastReceiver(oldUid)
-        IntentFilter().apply {
-            addAction(Intent.ACTION_PACKAGE_REMOVED)
-            addAction(Intent.ACTION_PACKAGE_ADDED)
-            addAction(Intent.ACTION_PACKAGE_REPLACED)
-            addDataScheme("package")
-            mContext.registerReceiver(receiver, this)
-        }
-        IntentFilter().apply {
-            addAction(Intent.ACTION_UID_REMOVED)
-            addAction(Const.ACTION_UPDATE_ACK)
-            mContext.registerReceiver(receiver, this)
-        }
-
-        // Update the data test APK and make sure UID changed.
-        assertTrue(installPackage(apk + "2.apk"))
-        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        assertNotEquals(oldUid, newUid)
-
-        // Ensure system broadcasts are delivered properly.
-        try {
-            val e = receiver.poll(30, TimeUnit.SECONDS)
-            if (e !== NOT_AN_ERROR) {
-                throw AssertionError(e)
-            }
-        } catch (e: InterruptedException) {
-            fail(e.message)
-        }
-        assertEquals(newUid, receiver.newUid)
-        mContext.unregisterReceiver(receiver)
-
-        // Ask the app again for a UUID. If data migration is working, it shall be the same.
-        result = resolver.call(authority, "data", null, null).assertNotNull()
-        val newUUID = result.getString(RESULT_KEY)
-        assertEquals(oldUUID, newUUID)
-        uninstallPackage(Const.DATA_TEST_PKG)
-    }
-
-    @Test
-    fun testKeyMigration() {
-        val apk = "$TMP_APK_PATH/DataTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        val authority = Const.DATA_TEST_PKG + ".provider"
-        val resolver = mContext.contentResolver
-        val secret = UUID.randomUUID().toString()
-
-        // Ask the app to encrypt secret with AES.
-        var result = resolver.call(authority, "encryptAES", secret, null).assertNotNull()
-        assertNotNull(result[RESULT_KEY])
-        assertNotNull(result["iv"])
-        val encResult = result
-
-        // Ask the app to generate a new EC keypair and sign our data.
-        result = resolver.call(authority, "signEC", secret, null).assertNotNull()
-        val signature = result.getByteArray(RESULT_KEY).assertNotNull()
-        val oldCertChain = result.getByteArray("certChain").assertNotNull()
-
-        // Update the data test APK and make sure UID changed.
-        assertTrue(installPackage(apk + "2.apk"))
-        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        assertNotEquals(oldUid, newUid)
-
-        // Ask the app to decrypt our secret.
-        result = resolver.call(authority, "decryptAES", null, encResult).assertNotNull()
-        val decSecret = result.getString(RESULT_KEY)
-        assertEquals(secret, decSecret)
-
-        // Ask the app to return the previously generated EC certificate.
-        result = resolver.call(authority, "getECCert", null, null).assertNotNull()
-        val rawCert = result.getByteArray(RESULT_KEY).assertNotNull()
-        val newCertChain = result.getByteArray("certChain").assertNotNull()
-        val cf = CertificateFactory.getInstance("X.509")
-        val cert = cf.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate
-
-        // Verify the signature and cert.
-        assertArrayEquals(oldCertChain, newCertChain)
-        val s = Signature.getInstance("SHA256withECDSA")
-        s.initVerify(cert)
-        s.update(secret.toByteArray(UTF_8))
-        assertTrue(s.verify(signature))
-        uninstallPackage(Const.DATA_TEST_PKG)
-    }
-
-    private fun installPackage(apkPath: String): Boolean {
-        return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
-    }
-
-    private fun uninstallPackage(packageName: String) {
-        runShellCommand("pm uninstall $packageName")
-    }
-
-    class PackageBroadcastReceiver(
-        private val mPreviousUid: Int
-    ) : BroadcastReceiver(), BlockingQueue<Throwable?> by ArrayBlockingQueue<Throwable?>(1) {
-
-        var newUid = -1
-            private set
-        private var mCounter = 0
-
-        override fun onReceive(context: Context?, intent: Intent) {
-            try {
-                verifyInternal(intent)
-            } catch (e: Throwable) {
-                offer(e)
+        if (Build.IS_USERDEBUG) {
+            testNewInstallOnly(uid)
+            reset(uid)
+            testBestEffort(uid)
+        } else {
+            when (migrationStrategy) {
+                NEW_INSTALL_ONLY -> testNewInstallOnly(uid)
+                BEST_EFFORT -> testBestEffort(uid)
             }
         }
 
-        private fun verifyInternal(intent: Intent) {
-            val action = intent.action
-            assertNotNull(action)
-            if (action == Intent.ACTION_UID_REMOVED) {
-                // Not the test package, none of our business.
-                if (intent.getIntExtra(Intent.EXTRA_UID, -1) != mPreviousUid) {
-                    return
-                }
-            }
-            val data = intent.data
-            if (data != null) {
-                assertEquals("package", data.scheme)
-                val pkg = data.schemeSpecificPart
-                assertNotNull(pkg)
-                // Not the test package, none of our business.
-                if (Const.DATA_TEST_PKG != pkg) {
-                    return
-                }
-            }
-
-            // Broadcasts must come in the following order:
-            // ACTION_PACKAGE_REMOVED -> ACTION_UID_REMOVED
-            // -> ACTION_PACKAGE_ADDED -> ACTION_UPDATE_ACK
-            mCounter++
-            when (action) {
-                Intent.ACTION_PACKAGE_REMOVED -> {
-                    assertEquals(1, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_UID, -1))
-                    newUid = intent.getIntExtra(Intent.EXTRA_NEW_UID, -1)
-                    assertNotEquals(mPreviousUid, newUid)
-                }
-                Intent.ACTION_UID_REMOVED -> {
-                    assertEquals(2, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(
-                        Const.DATA_TEST_PKG,
-                        intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
-                    )
-                }
-                Intent.ACTION_PACKAGE_ADDED -> {
-                    assertEquals(3, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, mPreviousUid))
-                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_PREVIOUS_UID, -1))
-                }
-                Const.ACTION_UPDATE_ACK -> {
-                    assertEquals(4, mCounter)
-                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, -2))
-                    // End of actions
-                    offer(NOT_AN_ERROR)
-                }
-                Intent.ACTION_PACKAGE_REPLACED -> fail("PACKAGE_REPLACED should not be called!")
-                else -> fail("Unknown action received")
-            }
-        }
+        tearDown()
     }
 }
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
index 72b4e97..95ed1db0 100644
--- a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
+++ b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
@@ -1625,6 +1625,30 @@
     }
 
     @Test
+    public void testSurfaceTransaction_scaleToZero() {
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        long parentSurfaceControl = createFromWindow(holder.getSurface());
+                        long childSurfaceControl = create(parentSurfaceControl);
+
+                        setSolidBuffer(parentSurfaceControl,
+                                DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, PixelColor.YELLOW);
+                        setSolidBuffer(childSurfaceControl,
+                                DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, PixelColor.RED);
+                        setScale(childSurfaceControl, 0f, 0f);
+                    }
+                },
+                new PixelChecker(PixelColor.YELLOW) {
+                    @Override
+                    public boolean checkPixels(int matchingPixelCount, int width, int height) {
+                        return matchingPixelCount > 9000 & matchingPixelCount < 11000;
+                    }
+                });
+    }
+
+    @Test
     public void testSurfaceTransaction_setPositionAndScale() {
         verifyTest(
                 new BasicSurfaceHolderCallback() {
diff --git a/tests/tests/view/src/android/view/cts/DisplayRefreshRateCtsActivity.java b/tests/tests/view/src/android/view/cts/DisplayRefreshRateCtsActivity.java
index 957ee10..2fd87ca 100644
--- a/tests/tests/view/src/android/view/cts/DisplayRefreshRateCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/DisplayRefreshRateCtsActivity.java
@@ -18,6 +18,8 @@
 
 import android.opengl.GLSurfaceView;
 import android.util.Log;
+import android.view.Window;
+import android.view.WindowManager;
 
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
@@ -141,4 +143,14 @@
     public FpsResult getFpsResult() {
         return mResult;
     }
+
+    public void setModeId(int modeId) {
+        runOnUiThread(() -> {
+            Window w = getWindow();
+            WindowManager.LayoutParams params = w.getAttributes();
+            params.preferredDisplayModeId = modeId;
+            w.setAttributes(params);
+        });
+
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
index 618ca21..c8f16ef 100644
--- a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
+++ b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
@@ -18,21 +18,32 @@
 
 import static org.junit.Assert.assertTrue;
 
+import android.Manifest;
 import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.Display;
 import android.view.WindowManager;
 
 import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Test that the screen refresh rate claimed by
  * android.view.Display.getRefreshRate() matches the steady-state framerate
@@ -51,30 +62,112 @@
 
     private static final String TAG = "DisplayRefreshRateTest";
 
-    @Rule
-    public ActivityTestRule<DisplayRefreshRateCtsActivity> mActivityRule =
-            new ActivityTestRule<>(DisplayRefreshRateCtsActivity.class);
+    private DisplayManager mDisplayManager;
+
+    private Display mDisplay;
+
+    private int mInitialMatchContentFrameRate;
+
+    private final DisplayListener mDisplayListener = new DisplayListener();
 
     private DisplayRefreshRateCtsActivity mActivity;
     private DisplayRefreshRateCtsActivity.FpsResult mFpsResult;
 
+    @Rule
+    public ActivityTestRule<DisplayRefreshRateCtsActivity> mActivityRule =
+            new ActivityTestRule<>(DisplayRefreshRateCtsActivity.class);
+
+    @Rule
+    public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+            InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+            Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+            Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE);
+
+    class DisplayListener implements DisplayManager.DisplayListener {
+        private CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+        void waitForModeToChange(int modeId) throws InterruptedException {
+            while (modeId != mDisplay.getMode().getModeId()) {
+                mCountDownLatch.await(5, TimeUnit.SECONDS);
+            }
+        }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId != mDisplay.getDisplayId()) {
+                return;
+            }
+
+            mCountDownLatch.countDown();
+        }
+    }
+
+
     @Before
-    public void setup() {
+    public void setup() throws InterruptedException {
         mActivity = mActivityRule.getActivity();
         mFpsResult = mActivity.getFpsResult();
+
+        Context context = mActivity.getApplicationContext();
+        mDisplayManager = context.getSystemService(DisplayManager.class);
+
+        mInitialMatchContentFrameRate =
+                toSwitchingType(mDisplayManager.getMatchContentFrameRateUserPreference());
+        mDisplayManager.setRefreshRateSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
+        mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
+
+        // This tests the fps of the default display.
+        // In consideration of multi-display devices we use getApplicationContext()
+        // to get the default display.
+        WindowManager wm = context.getSystemService(WindowManager.class);
+        mDisplay = wm.getDefaultDisplay();
+
+        mDisplayManager.registerDisplayListener(mDisplayListener,
+                new Handler(Looper.getMainLooper()));
+
+        int highestRefreshRateModeId = getHighestRefreshRateModeId();
+        mActivity.setModeId(highestRefreshRateModeId);
+        mDisplayListener.waitForModeToChange(highestRefreshRateModeId);
+    }
+
+    private int getHighestRefreshRateModeId() {
+        int highestRefreshRateModeId = mDisplay.getMode().getModeId();
+        for (Display.Mode mode : mDisplay.getSupportedModes()) {
+            if (mode.getPhysicalHeight() != mDisplay.getMode().getPhysicalHeight()) {
+                continue;
+            }
+
+            if (mode.getPhysicalWidth() != mDisplay.getMode().getPhysicalWidth()) {
+                continue;
+            }
+
+            if (mode.getRefreshRate() > mDisplay.getMode().getRefreshRate()) {
+                highestRefreshRateModeId = mode.getModeId();
+            }
+        }
+        return highestRefreshRateModeId;
+    }
+
+    @After
+    public void tearDown() {
+        mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+        mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
     }
 
     @Test
     public void testRefreshRate() {
         boolean fpsOk = false;
-        // This tests the fps of the default display.
-        // In consideration of multi-display devices we use getApplicationContext()
-        // to get the default display.
-        Context context = mActivity.getApplicationContext();
-        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-
-        Display dpy = wm.getDefaultDisplay();
-        float claimedFps = dpy.getRefreshRate();
+        float claimedFps = mDisplay.getRefreshRate();
 
         for (int i = 0; i < 3; i++) {
             float achievedFps = mFpsResult.waitResult();
@@ -93,4 +186,17 @@
         mActivity.finish();
         assertTrue(fpsOk);
     }
+
+    private static int toSwitchingType(int matchContentFrameRateUserPreference) {
+        switch (matchContentFrameRateUserPreference) {
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_NEVER:
+                return DisplayManager.SWITCHING_TYPE_NONE;
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY:
+                return DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS;
+            case DisplayManager.MATCH_CONTENT_FRAMERATE_ALWAYS:
+                return DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
+            default:
+                return -1;
+        }
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/SurfaceControlTest.java b/tests/tests/view/src/android/view/cts/SurfaceControlTest.java
index 8595664..ab245d2 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceControlTest.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceControlTest.java
@@ -1224,4 +1224,31 @@
                     }
                 });
     }
+
+    @Test
+    public void testSurfaceControl_scaleToZero() {
+        verifyTest(
+                new BasicSurfaceHolderCallback() {
+                    @Override
+                    public void surfaceCreated(SurfaceHolder holder) {
+                        SurfaceControl parentSurfaceControl = createFromWindow(holder);
+                        SurfaceControl childSurfaceControl = create(parentSurfaceControl);
+
+                        setSolidBuffer(parentSurfaceControl,
+                                DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, PixelColor.YELLOW);
+                        setSolidBuffer(childSurfaceControl,
+                                DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, PixelColor.RED);
+                        new SurfaceControl.Transaction()
+                                .setScale(childSurfaceControl, 0, 0)
+                                .apply();
+                    }
+                },
+                new PixelChecker(PixelColor.YELLOW) {
+                    @Override
+                    public boolean checkPixels(int matchingPixelCount, int width, int height) {
+                        return matchingPixelCount > 9000 && matchingPixelCount < 11000;
+                    }
+                }
+        );
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/input/OWNERS b/tests/tests/view/src/android/view/cts/input/OWNERS
index bbaec4d..c88bfe9 100644
--- a/tests/tests/view/src/android/view/cts/input/OWNERS
+++ b/tests/tests/view/src/android/view/cts/input/OWNERS
@@ -1,4 +1 @@
-# Bug component: 136048
-michaelwr@google.com
-prabirmsp@google.com
-svv@google.com
\ No newline at end of file
+include platform/frameworks/base:/INPUT_OWNERS
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index db505a9..dbf9c5a 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -8551,10 +8551,8 @@
         mTextView.setTextMetricsParams(param);
         assertTrue(param.equals(mTextView.getTextMetricsParams()));
 
-        LineBreakConfig lbConfig = new LineBreakConfig();
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
-        lbConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
-        mTextView.setLineBreakConfig(lbConfig);
+        mTextView.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        mTextView.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
 
         PrecomputedText.Params resultParams = mTextView.getTextMetricsParams();
         assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT,
@@ -8607,186 +8605,219 @@
     public void testLineBreakConfigDefaultValue() {
         final Context context = InstrumentationRegistry.getTargetContext();
         final TextView textView = new TextView(context);
-        LineBreakConfig lbConfig = textView.getLineBreakConfig();
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, lbConfig.getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, lbConfig.getLineBreakWordStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, textView.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, textView.getLineBreakWordStyle());
     }
 
     @UiThreadTest
     @Test
     public void testSetGetLineBreakConfig() {
         TextView tv = new TextView(mActivity);
-        LineBreakConfig lbConfig = new LineBreakConfig();
+        tv.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE);
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, tv.getLineBreakStyle());
 
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        tv.setLineBreakConfig(lbConfig);
-        LineBreakConfig resultLbConfig = tv.getLineBreakConfig();
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE, resultLbConfig.getLineBreakStyle());
+        tv.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE, tv.getLineBreakStyle());
 
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL);
-        tv.setLineBreakConfig(lbConfig);
-        resultLbConfig = tv.getLineBreakConfig();
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NORMAL, resultLbConfig.getLineBreakStyle());
+        tv.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL);
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NORMAL, tv.getLineBreakStyle());
 
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
-        tv.setLineBreakConfig(lbConfig);
-        resultLbConfig = tv.getLineBreakConfig();
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT, resultLbConfig.getLineBreakStyle());
+        tv.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT, tv.getLineBreakStyle());
 
-        lbConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
-        tv.setLineBreakConfig(lbConfig);
-        resultLbConfig = tv.getLineBreakConfig();
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
-                resultLbConfig.getLineBreakWordStyle());
+        tv.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, tv.getLineBreakWordStyle());
 
-        lbConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
-        tv.setLineBreakConfig(lbConfig);
-        resultLbConfig = tv.getLineBreakConfig();
+        tv.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE, tv.getLineBreakWordStyle());
+    }
+
+    @Test
+    public void testUpdateLineBreakConfigBuilder() {
+        LineBreakConfig.Builder builder = new LineBreakConfig.Builder();
+        builder.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig resultConfig = builder.build();
+
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT, resultConfig.getLineBreakStyle());
         assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                resultLbConfig.getLineBreakWordStyle());
-
-        try {
-            lbConfig.set(null);
-            fail("Should thrown NullPointerException if the line break config is null");
-        } catch (NullPointerException e) {
-        }
-
-        try {
-            tv.setLineBreakConfig(null);
-            fail("Should thrown NullPointerException if the line break config is null");
-        } catch (NullPointerException e) {
-        }
+                resultConfig.getLineBreakWordStyle());
     }
 
     @Test
     public void testLineBreakConfigByStyle() {
         TextView defaultTv = findTextView(R.id.textview_line_break_style_default);
-        TextView noneTv = findTextView(R.id.textview_line_break_style_none);
-        TextView looseTv = findTextView(R.id.textview_line_break_style_loose);
-        TextView normalTv = findTextView(R.id.textview_line_break_style_normal);
-        TextView strictTv = findTextView(R.id.textview_line_break_style_strict);
+        TextView nonePhraseTv = findTextView(R.id.textview_line_break_style_none);
+        TextView looseNoneTv = findTextView(R.id.textview_line_break_style_loose);
+        TextView normalPhraseTv = findTextView(R.id.textview_line_break_style_normal);
+        TextView strictNoneTv = findTextView(R.id.textview_line_break_style_strict);
+        TextView loosePhraseTv = findTextView(R.id.textview_line_break_with_style);
 
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE,
-                defaultTv.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE,
-                noneTv.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE,
-                looseTv.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NORMAL,
-                normalTv.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT,
-                strictTv.getLineBreakConfig().getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, defaultTv.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE, defaultTv.getLineBreakWordStyle());
 
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
-                defaultTv.getLineBreakConfig().getLineBreakWordStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NONE, nonePhraseTv.getLineBreakStyle());
         assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                noneTv.getLineBreakConfig().getLineBreakWordStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
-                looseTv.getLineBreakConfig().getLineBreakWordStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                normalTv.getLineBreakConfig().getLineBreakWordStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
-                strictTv.getLineBreakConfig().getLineBreakWordStyle());
+                nonePhraseTv.getLineBreakWordStyle());
 
-        TextView styleTv = findTextView(R.id.textview_line_break_with_style);
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE,
-                styleTv.getLineBreakConfig().getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE, looseNoneTv.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
+                looseNoneTv.getLineBreakWordStyle());
+
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_NORMAL, normalPhraseTv.getLineBreakStyle());
         assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                styleTv.getLineBreakConfig().getLineBreakWordStyle());
+                normalPhraseTv.getLineBreakWordStyle());
+
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT, strictNoneTv.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
+                strictNoneTv.getLineBreakWordStyle());
+
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE, loosePhraseTv.getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
+                loosePhraseTv.getLineBreakWordStyle());
     }
 
     @Test
     public void testLineBreakConfigWithTextAppearance() {
         TextView textView = new TextView(mActivity);
+        textView.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
+        textView.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
+
+        // Override the line break config via TextAppearance.
         textView.setTextAppearance(R.style.LineBreakStyle_strict);
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT,
-                textView.getLineBreakConfig().getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT, textView.getLineBreakStyle());
 
         textView.setTextAppearance(R.style.LineBreakWordStyle_phrase);
         assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                textView.getLineBreakConfig().getLineBreakWordStyle());
+                textView.getLineBreakWordStyle());
 
         textView.setTextAppearance(R.style.LineBreakConfig_loose_phrase);
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE,
-                textView.getLineBreakConfig().getLineBreakStyle());
+        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_LOOSE, textView.getLineBreakStyle());
         assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                textView.getLineBreakConfig().getLineBreakWordStyle());
-
-        LineBreakConfig lbConfig = new LineBreakConfig();
-
-        // Verify only the lineBreakStyle style is set.
-        TextView textView2 = new TextView(mActivity);
-        // Init the line break config in the TextView.
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        lbConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
-        textView2.setLineBreakConfig(lbConfig);
-        // Override the line break style from "loose" to "strict" via the TextAppearance.
-        textView2.setTextAppearance(R.style.LineBreakStyle_strict);
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT,
-                textView2.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                textView2.getLineBreakConfig().getLineBreakWordStyle());
-
-        // Verify only the lineBreakWordStyle style is set.
-        TextView textView3 = new TextView(mActivity);
-        // Init the line break config in the TextView.
-        lbConfig.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
-        lbConfig.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
-        textView3.setLineBreakConfig(lbConfig);
-        // Override the line break word style from "none" to "phrase" via the TextAppearance.
-        textView3.setTextAppearance(R.style.LineBreakWordStyle_phrase);
-        assertEquals(LineBreakConfig.LINE_BREAK_STYLE_STRICT,
-                textView3.getLineBreakConfig().getLineBreakStyle());
-        assertEquals(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
-                textView3.getLineBreakConfig().getLineBreakWordStyle());
+                textView.getLineBreakWordStyle());
     }
 
     @Test
-    public void testLineBreakConfigEquals() {
-        LineBreakConfig config1 = new LineBreakConfig();
-        config1.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
+    public void testLineBreakStyleEquals_returnsFalseIfStyleIsDifferent() {
+        LineBreakConfig looseNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        LineBreakConfig config2 = new LineBreakConfig();
-        config2.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL);
+        LineBreakConfig normalNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        LineBreakConfig config3 = new LineBreakConfig();
-        config3.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT);
+        LineBreakConfig strictNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        assertFalse(config1.equals(config2));
-        assertFalse(config1.equals(config3));
-        assertFalse(config2.equals(config3));
-        assertFalse(Objects.equals(config1, config2));
-        assertFalse(Objects.equals(config1, config3));
-        assertFalse(Objects.equals(config2, config3));
+        // Verify the lineBreakConfig instances are not equals.
+        assertFalse(looseNoneConfig.equals(normalNoneConfig));
+        assertFalse(looseNoneConfig.equals(strictNoneConfig));
+        assertFalse(normalNoneConfig.equals(strictNoneConfig));
+        assertFalse(Objects.equals(looseNoneConfig, normalNoneConfig));
+        assertFalse(Objects.equals(looseNoneConfig, strictNoneConfig));
+        assertFalse(Objects.equals(normalNoneConfig, strictNoneConfig));
+    }
 
-        LineBreakConfig config4 = new LineBreakConfig();
-        config4.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        assertTrue(config1.equals(config4));
-        assertTrue(Objects.equals(config1, config4));
+    @Test
+    public void testLineBreakStyleEquals_returnsTrueIfStyleIsNotDifferent() {
+        LineBreakConfig looseNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        LineBreakConfig config5 = new LineBreakConfig();
-        config5.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
+        LineBreakConfig newLooseNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        LineBreakConfig config6 = new LineBreakConfig();
-        config6.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        assertTrue(newLooseNoneConfig.equals(looseNoneConfig));
+        assertTrue(Objects.equals(newLooseNoneConfig, looseNoneConfig));
 
-        LineBreakConfig config7 = new LineBreakConfig();
-        config7.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        config7.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        LineBreakConfig normalNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        assertFalse(config5.equals(config6));
-        assertFalse(config5.equals(config7));
-        assertFalse(config6.equals(config7));
-        assertFalse(Objects.equals(config5, config6));
-        assertFalse(Objects.equals(config5, config7));
-        assertFalse(Objects.equals(config6, config7));
+        LineBreakConfig newNormalNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NORMAL)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
 
-        LineBreakConfig config8 = new LineBreakConfig();
-        config8.setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_LOOSE);
-        config8.setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE);
+        assertTrue(newNormalNoneConfig.equals(normalNoneConfig));
+        assertTrue(Objects.equals(newNormalNoneConfig, normalNoneConfig));
 
-        assertTrue(config7.equals(config8));
-        assertTrue(Objects.equals(config7, config8));
+        LineBreakConfig strictNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
+
+        LineBreakConfig newStringNoneStrictConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_STRICT)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
+
+        assertTrue(newStringNoneStrictConfig.equals(strictNoneConfig));
+        assertTrue(Objects.equals(newStringNoneStrictConfig, strictNoneConfig));
+    }
+
+    @Test
+    public void testLineBreakWordStyleEquals_returnsFalseIfWordStyleIsDifferent() {
+        LineBreakConfig nonePhraseConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
+
+        LineBreakConfig noneNoneConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE).build();
+
+        // Verify the lineBreakConfig instances are not equals.
+        assertFalse(nonePhraseConfig.equals(noneNoneConfig));
+        assertFalse(Objects.equals(nonePhraseConfig, noneNoneConfig));
+    }
+
+    @Test
+    public void testLineBreakWordStyleEquals_returnsTrueIfWordStyleIsNotDifferent() {
+        LineBreakConfig nonePhraseConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
+
+        LineBreakConfig newNonePhraseConfig = new LineBreakConfig.Builder()
+                .setLineBreakStyle(LineBreakConfig.LINE_BREAK_STYLE_NONE)
+                .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE).build();
+        assertTrue(nonePhraseConfig.equals(newNonePhraseConfig));
+        assertTrue(Objects.equals(nonePhraseConfig, newNonePhraseConfig));
+    }
+
+    @Test
+    public void testLineBreakConfigEquals_returnFalseIfValueOfConfigIsDifferent() {
+        LineBreakConfig[] lineBreakConfigArray = new LineBreakConfig[8];
+
+        int[] lineBreakStyleArray = {
+            LineBreakConfig.LINE_BREAK_STYLE_NONE,
+            LineBreakConfig.LINE_BREAK_STYLE_LOOSE,
+            LineBreakConfig.LINE_BREAK_STYLE_NORMAL,
+            LineBreakConfig.LINE_BREAK_STYLE_STRICT,
+        };
+
+        int[] lineBreakWordStyleArray = {
+            LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE,
+            LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE,
+        };
+
+        int index = 0;
+        for (int lineBreakStyle : lineBreakStyleArray) {
+            for (int lineBreakWordStyle : lineBreakWordStyleArray) {
+                lineBreakConfigArray[index++] = new LineBreakConfig.Builder()
+                        .setLineBreakStyle(lineBreakStyle)
+                        .setLineBreakWordStyle(lineBreakWordStyle).build();
+            }
+        }
+
+        // Verify the lineBreakConfig instances are not equal.
+        for (int i = 0; i < lineBreakConfigArray.length - 1; i++) {
+            LineBreakConfig lbConfig = lineBreakConfigArray[i];
+            for (int j = i + 1; j < lineBreakConfigArray.length; j++) {
+                LineBreakConfig comparedLbConfig = lineBreakConfigArray[j];
+                assertFalse(lbConfig.equals(comparedLbConfig));
+                assertFalse(Objects.equals(lbConfig, comparedLbConfig));
+            }
+        }
     }
 
     @Test
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index c3a16f3..e21a64c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -853,8 +853,12 @@
     public void testTextToastNotAllowed_whenInTheBackground_withoutNotificationPermission()
             throws Throwable {
         assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
+
         // Make it background
         mActivityRule.finishActivity();
+        // may take time for the app process importance to get downgraded from foreground:
+        SystemClock.sleep(TIME_FOR_UI_OPERATION);
+
         List<TextToastInfo> toastInfoList = createTextToasts(1, "Text", Toast.LENGTH_SHORT);
 
         mActivityRule.runOnUiThread(
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index ed2342d..b6fd50a 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -4700,10 +4700,10 @@
     }
 
     /**
-     * Verify the invalid and valid usages of {@code WifiManager#getAutojoinGlobal}.
+     * Verify the invalid and valid usages of {@code WifiManager#queryAutojoinGlobal}.
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
-    public void testGetAutojoinGlobal() throws Exception {
+    public void testQueryAutojoinGlobal() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
@@ -4721,19 +4721,19 @@
         };
         // Test invalid inputs trigger IllegalArgumentException
         assertThrows("null executor should trigger exception", NullPointerException.class,
-                () -> mWifiManager.getAutojoinGlobal(null, listener));
+                () -> mWifiManager.queryAutojoinGlobal(null, listener));
         assertThrows("null listener should trigger exception", NullPointerException.class,
-                () -> mWifiManager.getAutojoinGlobal(mExecutor, null));
+                () -> mWifiManager.queryAutojoinGlobal(mExecutor, null));
 
         // Test caller with no permission triggers SecurityException.
         assertThrows("No permission should trigger SecurityException", SecurityException.class,
-                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+                () -> mWifiManager.queryAutojoinGlobal(mExecutor, listener));
 
         // Test get/set autojoin global enabled
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.allowAutojoinGlobal(true));
         ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+                () -> mWifiManager.queryAutojoinGlobal(mExecutor, listener));
         synchronized (mLock) {
             mLock.wait(TEST_WAIT_DURATION_MS);
         }
@@ -4743,7 +4743,7 @@
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.allowAutojoinGlobal(false));
         ShellIdentityUtils.invokeWithShellPermissions(
-                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+                () -> mWifiManager.queryAutojoinGlobal(mExecutor, listener));
         synchronized (mLock) {
             mLock.wait(TEST_WAIT_DURATION_MS);
         }
@@ -5553,8 +5553,27 @@
     }
 
     /**
-     * Tests
-     * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}.
+     * Verifies that
+     * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)} raises
+     * a security exception without permission.
+     */
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+    public void testIsItPossibleToCreateInterfaceNotAllowed() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        assertThrows(SecurityException.class, () -> mWifiManager.reportCreateInterfaceImpact(
+                WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor,
+                (canBeCreatedLocal, interfacesWhichWillBeDeletedLocal) -> {
+                    // should not get here (security exception!)
+                }));
+    }
+
+    /**
+     * Verifies
+     * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)} .
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
     public void testIsItPossibleToCreateInterface() throws Exception {
@@ -5565,17 +5584,35 @@
 
         AtomicBoolean called = new AtomicBoolean(false);
         AtomicBoolean canBeCreated = new AtomicBoolean(false);
-        assertThrows(SecurityException.class, () -> mWifiManager.reportCreateInterfaceImpact(
-                WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor,
-                (canBeCreatedLocal, interfacesWhichWillBeDeleted) -> {
-                    synchronized (mLock) {
-                        canBeCreated.set(canBeCreatedLocal);
-                        called.set(true);
-                        mLock.notify();
-                    }
-                }));
+        AtomicReference<List<WifiManager.InterfaceCreationImpact>>
+                interfacesWhichWillBeDeleted = new AtomicReference<>(null);
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.reportCreateInterfaceImpact(
+                        WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor,
+                        (canBeCreatedLocal, interfacesWhichWillBeDeletedLocal) -> {
+                            synchronized (mLock) {
+                                canBeCreated.set(canBeCreatedLocal);
+                                called.set(true);
+                                interfacesWhichWillBeDeleted.set(interfacesWhichWillBeDeletedLocal);
+                                mLock.notify();
+                            }
+                        }));
         synchronized (mLock) {
             mLock.wait(TEST_WAIT_DURATION_MS);
         }
+        assertTrue(called.get());
+        if (canBeCreated.get()) {
+            for (WifiManager.InterfaceCreationImpact entry : interfacesWhichWillBeDeleted.get()) {
+                int interfaceType = entry.getInterfaceType();
+                assertTrue(interfaceType == WifiManager.WIFI_INTERFACE_TYPE_STA
+                        || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_AP
+                        || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_DIRECT
+                        || interfaceType == WifiManager.WIFI_INTERFACE_TYPE_AWARE);
+                Set<String> packages = entry.getPackages();
+                for (String p : packages) {
+                    assertNotNull(p);
+                }
+            }
+        }
     }
 }
diff --git a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
index ec4e27b..f1780b2 100644
--- a/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
@@ -131,6 +131,15 @@
         } catch (Exception ignore) {}
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+    @Test
+    public void testGetMaxSsidsPerScan() {
+        try {
+            WifiNl80211Manager manager = mContext.getSystemService(WifiNl80211Manager.class);
+            manager.getMaxSsidsPerScan("wlan0");
+        } catch (Exception ignore) { }
+    }
+
     @Test
     public void testSetOnServiceDeadCallback() {
         try {
diff --git a/tests/uwb/src/android/uwb/cts/RangingSessionTest.java b/tests/uwb/src/android/uwb/cts/RangingSessionTest.java
index 19c945a..6fcdc74 100644
--- a/tests/uwb/src/android/uwb/cts/RangingSessionTest.java
+++ b/tests/uwb/src/android/uwb/cts/RangingSessionTest.java
@@ -32,7 +32,7 @@
 
 import android.os.PersistableBundle;
 import android.os.RemoteException;
-import android.uwb.IUwbAdapter2;
+import android.uwb.IUwbAdapter;
 import android.uwb.RangingReport;
 import android.uwb.RangingSession;
 import android.uwb.SessionHandle;
@@ -64,7 +64,7 @@
     public void testOnRangingOpened_OnOpenSuccessCalled() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         verifyOpenState(session, false);
 
@@ -80,7 +80,7 @@
     public void testOnRangingOpened_OnServiceDiscoveredConnectedCalled() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         verifyOpenState(session, false);
 
@@ -103,7 +103,7 @@
     public void testOnRangingOpened_CannotOpenClosedSession() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
 
         session.onRangingOpened();
@@ -127,7 +127,7 @@
     public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         verifyOpenState(session, false);
 
@@ -143,7 +143,7 @@
     public void testOnRangingClosed_OnClosedCalled() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         session.onRangingStarted(PARAMS);
         session.onRangingClosed(REASON, PARAMS);
@@ -158,7 +158,7 @@
     public void testOnRangingResult_OnReportReceivedCalled() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         verifyOpenState(session, false);
 
@@ -174,7 +174,7 @@
     public void testStart_CannotStartIfAlreadyStarted() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
         session.onRangingOpened();
@@ -191,7 +191,7 @@
     public void testStop_CannotStopIfAlreadyStopped() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
         doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
@@ -210,7 +210,7 @@
     public void testStop_CannotStopIfOpenFailed() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new StartAnswer(session)).when(adapter).startRanging(any(), any());
         doAnswer(new StopAnswer(session)).when(adapter).stopRanging(any());
@@ -230,7 +230,7 @@
     public void testCallbacks_OnlyWhenOpened() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new OpenAnswer(session)).when(adapter).openRanging(
                 any(), any(), any(), any(), any());
@@ -353,7 +353,7 @@
     public void testClose_NoCallbackUntilInvoked() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         session.onRangingOpened();
 
@@ -382,7 +382,7 @@
     public void testClose_OnClosedCalled() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
         session.onRangingOpened();
@@ -395,7 +395,7 @@
     public void testClose_CannotInteractFurther() throws RemoteException {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
         doAnswer(new CloseAnswer(session)).when(adapter).closeRanging(any());
         session.close();
@@ -410,7 +410,7 @@
     public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
 
         assertFalse(session.isOpen());
@@ -427,7 +427,7 @@
     public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
         SessionHandle handle = new SessionHandle(123);
         RangingSession.Callback callback = mock(RangingSession.Callback.class);
-        IUwbAdapter2 adapter = mock(IUwbAdapter2.class);
+        IUwbAdapter adapter = mock(IUwbAdapter.class);
         RangingSession session = new RangingSession(EXECUTOR, callback, adapter, handle);
 
         assertFalse(session.isOpen());
diff --git a/tools/cts-tradefed/OWNERS b/tools/cts-tradefed/OWNERS
index 790c317..d27cf19 100644
--- a/tools/cts-tradefed/OWNERS
+++ b/tools/cts-tradefed/OWNERS
@@ -1,6 +1,5 @@
 #  Android EngProd Approvers
 guangzhu@google.com
-fdeng@google.com
 normancheung@google.com
 jdesprez@google.com
 
@@ -15,4 +14,4 @@
 per-file cts-on-csi*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
 per-file csi-*.xml = ycchen@google.com, hsinyichen@google.com, tyanh@google.com
 per-file cts-on-gsi*.xml = bettyzhou@google.com, ycchen@google.com, hsinyichen@google.com, tyanh@google.com
-
+per-file cts-known-failures.xml = rossyeh@google.com, mariay@google.com, robinjacob@google.com
diff --git a/tools/cts-tradefed/res/config/csi-known-failures.xml b/tools/cts-tradefed/res/config/csi-known-failures.xml
index bbb98b7..86c8fe6 100644
--- a/tools/cts-tradefed/res/config/csi-known-failures.xml
+++ b/tools/cts-tradefed/res/config/csi-known-failures.xml
@@ -32,84 +32,38 @@
     <option name="compatibility:exclude-filter" value="CtsStatsdHostTestCases android.cts.statsd.atom.UidAtomTests#testAppCrashOccurred" />
     <option name="compatibility:exclude-filter" value="CtsUiRenderingTestCases android.uirendering.cts.testclasses.SurfaceViewTests#testMovingWhiteSurfaceView" />
 
-    <!-- Exclude known failure of CtsMediaTestCases (mostly on some Pixel phones) -->
+    <!-- Exclude known failure of CtsMedia*TestCases (mostly on some Pixel phones) -->
     <!-- CSI doesn't seem to include ringtones. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.RingtoneManagerTest" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.RingtoneTest" />
+    <option name="compatibility:exclude-filter" value="CtsMediaAudioTestCases android.media.audio.cts.RingtoneManagerTest" />
+    <option name="compatibility:exclude-filter" value="CtsMediaAudioTestCases android.media.audio.cts.RingtoneTest" />
 
     <!-- Following failures take about 10 min each, so exclude them to reduce test time. -->
     <!-- CSI on Goldfish can pass the following tests in StreamingMediaPlayerTest. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.StreamingMediaPlayerTest#testHTTP_H263_AMR_Video2" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.StreamingMediaPlayerTest#testHTTP_H264Base_AAC_Video2" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.StreamingMediaPlayerTest#testHTTP_MPEG4SP_AAC_Video2" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.cts.player.StreamingMediaPlayerTest#testHTTP_H263_AMR_Video2" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.cts.player.StreamingMediaPlayerTest#testHTTP_H264Base_AAC_Video2" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.cts.player.StreamingMediaPlayerTest#testHTTP_MPEG4SP_AAC_Video2" />
 
     <!-- CSI on Cuttlefish and Goldfish can pass the following tests in VideoCodecTest. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoCodecTest#testParallelEncodingAndDecodingAVC" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoCodecTest#testParallelEncodingAndDecodingHEVC" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoCodecTest#testParallelEncodingAndDecodingVP8" />
+    <option name="compatibility:exclude-filter" value="CtsMediaCodecTestCases android.media.codec.cts.VideoCodecTest#testParallelEncodingAndDecoding" />
 
     <!-- Failures will crash the test harness, so exclude it here (even though only failed with VP9 decoder). -->
     <!-- CSI on Cuttlefish and Goldfish can pass the following tests in VideoDecoderRotationTest. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderRotationTest" />
+    <option name="compatibility:exclude-filter" value="CtsMediaCodecTestCases android.media.codec.cts.VideoDecoderRotationTest" />
 
     <!-- CSI on Cuttlefish and Goldfish can pass the following tests in VideoDecoderPerfTest. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther0Perf0320x0240" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther0Perf0720x0480" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther0Perf1280x0720" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther1Perf0320x0240" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther1Perf0720x0480" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther1Perf1280x0720" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testAvcOther1Perf1920x1080" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther0Perf0352x0288" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther0Perf0640x0360" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther0Perf0720x0480" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther0Perf1280x0720" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther0Perf1920x1080" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf0352x0288" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf0640x0360" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf0720x0480" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf1280x0720" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf1920x1080" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoDecoderPerfTest#testHevcOther1Perf3840x2160" />
+    <option name="compatibility:exclude-filter" value="CtsMediaDecoderTestCases android.media.decoder.cts.VideoDecoderPerfTest#testPerf" />
 
     <!-- CSI on Cuttlefish and Goldfish can pass the following tests in VideoEncoderTest. -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH263SurfMinMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfArbitraryH" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfArbitraryW" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfNearMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfNearMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfNearMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH265SurfQCIF" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfArbitraryH" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfArbitraryW" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfNearMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfNearMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfNearMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogMpeg4SurfNearMinMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8Surf480p" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfArbitraryH" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfArbitraryW" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfNearMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfNearMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfNearMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP8SurfQCIF" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9Surf480p" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfArbitraryH" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfArbitraryW" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfNearMaxMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfNearMaxMin" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfNearMinMax" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogVP9SurfQCIF" />
-
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfMinMin" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfArbitraryH" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfArbitraryW" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfMaxMax" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfMaxMin" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfMinMax" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfNearMaxMax" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfNearMaxMin" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfNearMinMax" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfQCIF" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurfNearMinMin" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases android.media.encoder.cts.VideoEncoderTest#testSurf480p" />
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 72ff5ce..1da1953 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -255,4 +255,7 @@
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testSetCameraDisabledLogged" />
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases com.android.cts.devicepolicy.MixedProfileOwnerTest#testSetCameraDisabledLogged" />
 
+    <!-- b/182630972, b/214019488 -->
+    <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.PinnedStackTests#testEnterPipWithMinimalSize" />
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-meerkat.xml b/tools/cts-tradefed/res/config/cts-meerkat.xml
index 6bc6b30..31aed81 100644
--- a/tools/cts-tradefed/res/config/cts-meerkat.xml
+++ b/tools/cts-tradefed/res/config/cts-meerkat.xml
@@ -39,7 +39,7 @@
     <!-- System Alert Window (SAW) -->
     <option name="compatibility:include-filter" value="CtsSystemIntentTestCases"/>
     <option name="compatibility:include-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.HideOverlayWindowsTest"/>
-    <option name="compatibility:include-filter" value="CtsMediaTestCases android.media.cts.MediaProjectionTest"/>
+    <option name="compatibility:include-filter" value="CtsMediaMiscTestCases android.media.misc.cts.MediaProjectionTest"/>
 
     <!-- Toasts -->
     <option name="compatibility:include-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.ToastWindowTest"/>
diff --git a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
index d220e8f..bd4153b 100644
--- a/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-aosp-exclude.xml
@@ -61,10 +61,10 @@
     <option name="compatibility:exclude-filter" value="CtsAppTestCases android.app.cts.ActivityKeyboardShortcutsTest#testRequestShowKeyboardShortcuts" />
 
     <!-- b/161837932: Fix MediaPlayerTests that use "too small" resolution -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.MediaPlayerTest#testOnSubtitleDataListener" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.MediaPlayerTest#testChangeSubtitleTrack" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.MediaPlayerTest#testDeselectTrackForSubtitleTracks" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.MediaPlayerTest#testGetTrackInfoForVideoWithSubtitleTracks" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testOnSubtitleDataListener" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testChangeSubtitleTrack" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testDeselectTrackForSubtitleTracks" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases android.media.player.cts.MediaPlayerTest#testGetTrackInfoForVideoWithSubtitleTracks" />
 
     <!-- b/152359655: ResumeOnReboot can't work on GSI -->
     <option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.ResumeOnRebootHostTest" />
diff --git a/tools/cts-tradefed/res/config/cts-on-csi-cf.xml b/tools/cts-tradefed/res/config/cts-on-csi-cf.xml
index c810f2d..6d55fe2 100644
--- a/tools/cts-tradefed/res/config/cts-on-csi-cf.xml
+++ b/tools/cts-tradefed/res/config/cts-on-csi-cf.xml
@@ -41,8 +41,16 @@
     <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases" />
     <option name="compatibility:exclude-filter" value="CtsMediaBitstreamsTestCases" />
     <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases" />
-    <option name="compatibility:exclude-filter" value="CtsMediaDrmTestCases" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaAudioTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaCodecTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaDecoderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaDrmFrameworkTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaEncoderTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaExtractorTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaMiscTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaMuxerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaPlayerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsMediaRecorderTestCases" />
     <option name="compatibility:exclude-filter" value="CtsMediaV2TestCases" />
     <option name="compatibility:exclude-filter" value="CtsNativeHardwareTestCases" />
     <option name="compatibility:exclude-filter" value="CtsOpenGLTestCases" />
diff --git a/tools/cts-tradefed/res/config/cts-on-csi-no-apks.xml b/tools/cts-tradefed/res/config/cts-on-csi-no-apks.xml
index a99c656..dc93565 100644
--- a/tools/cts-tradefed/res/config/cts-on-csi-no-apks.xml
+++ b/tools/cts-tradefed/res/config/cts-on-csi-no-apks.xml
@@ -159,8 +159,8 @@
     <option name="compatibility:exclude-filter" value="CtsContentTestCases android.content.cts.AvailableIntentsTest#testManageStorage" />
 
     <!-- No SystemUI -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.AudioPlaybackCaptureTest" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.MediaProjectionTest" />
+    <option name="compatibility:exclude-filter" value="CtsMediaAudioTestCases android.media.audio.cts.AudioPlaybackCaptureTest" />
+    <option name="compatibility:exclude-filter" value="CtsMediaMiscTestCases android.media.misc.cts.MediaProjectionTest" />
     <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest22#testCompatRevoked" />
     <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testGranted" />
     <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testRevokeAffectsWholeGroup" />
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
index 673d93c..ced6aaf 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ApkPackageNameCheck.java
@@ -30,13 +30,13 @@
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.InstrumentationTest;
 import com.android.tradefed.util.AaptParser;
+import com.android.tradefed.util.FileUtil;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 import java.io.File;
-import java.io.FilenameFilter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -69,20 +69,12 @@
             fail(String.format("%s does not exists", testcases));
             return;
         }
-        File[] listConfig = testcases.listFiles(new FilenameFilter() {
-            @Override
-            public boolean accept(File dir, String name) {
-                if (name.endsWith(".config")) {
-                    return true;
-                }
-                return false;
-            }
-        });
-        assertTrue(listConfig.length > 0);
+        Set<File> listConfigs = FileUtil.findFilesObject(testcases, ".*\\.config");
+        assertTrue(listConfigs.size() > 0);
         // We check all apk installed by all modules
         Map<String, String> packageNames = new HashMap<>();
 
-        for (File config : listConfig) {
+        for (File config : listConfigs) {
             IConfiguration c = ConfigurationFactory.getInstance()
                     .createConfigurationFromArgs(new String[] {config.getAbsolutePath()});
             // For each config, we check all the apk it's going to install
@@ -97,15 +89,17 @@
                     if (prep instanceof FilePusher && ((FilePusher) prep).shouldAppendBitness()) {
                         for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
                             String path = f.getPath();
-                            if (!new File(testcases, path + "32").exists()
-                                    || !new File(testcases, path + "64").exists()) {
+                            File file32 = FileUtil.findFile(config.getParentFile(), path + "32");
+                            File file64 = FileUtil.findFile(config.getParentFile(), path + "64");
+                            if (file32 == null || file64 == null) {
                                 // TODO: Enforce should abort on failure is True in CTS
                                 if (((FilePusher) prep).shouldAbortOnFailure()) {
                                     fail(
                                             String.format(
-                                                    "File %s[32/64] wasn't found in testcases/ while "
-                                                            + "it's expected to be pushed as part of "
-                                                            + "%s",
+                                                    "File %s[32/64] wasn't found in module "
+                                                            + "dependencies while "
+                                                            + "it's expected to be pushed as part"
+                                                            + " of %s.",
                                                     path, config.getName()));
                                 }
                             }
@@ -113,24 +107,27 @@
                     } else if (prep instanceof PushFilePreparer) {
                         for (File f : ((PushFilePreparer) prep).getPushSpecs(null).values()) {
                             String path = f.getPath();
-                            if (!new File(testcases, path).exists()) {
+                            File toBePushed = FileUtil.findFile(config.getParentFile(), path);
+                            if (toBePushed == null) {
                                 // TODO: Enforce should abort on failure is True in CTS
                                 if (((PushFilePreparer) prep).shouldAbortOnFailure()) {
                                     fail(
                                             String.format(
-                                                    "File %s wasn't found in testcases/ while it's "
-                                                            + "expected to be pushed as part of %s",
+                                                    "File %s wasn't found in module dependencies "
+                                                            + "while it's expected to be pushed "
+                                                            + "as part of %s.",
                                                     path, config.getName()));
                                 }
                             }
                         }
                     }
                 }
-    
+
+                // All apks need to be in the config dir or sub-dir
                 for (File apk : apkNames) {
                     String apkName = apk.getName();
-                    File apkFile = new File(testcases, apkName);
-                    if (!apkFile.exists()) {
+                    File apkFile = FileUtil.findFile(config.getParentFile(), apkName);
+                    if (apkFile == null || !apkFile.exists()) {
                         fail(String.format("Module %s is trying to install %s which does not "
                                 + "exists in testcases/", config.getName(), apkFile));
                     }
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
index 0a392fd..7b6e0d1 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
@@ -40,6 +40,7 @@
 import com.android.tradefed.testtype.ITestFilterReceiver;
 import com.android.tradefed.testtype.suite.ITestSuite;
 import com.android.tradefed.testtype.suite.params.ModuleParameters;
+import com.android.tradefed.util.FileUtil;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -47,7 +48,6 @@
 import org.junit.runners.JUnit4;
 
 import java.io.File;
-import java.io.FilenameFilter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -193,16 +193,8 @@
             fail(String.format("%s does not exists", testcases));
             return;
         }
-        File[] listConfig = testcases.listFiles(new FilenameFilter() {
-            @Override
-            public boolean accept(File dir, String name) {
-                if (name.endsWith(".config")) {
-                    return true;
-                }
-                return false;
-            }
-        });
-        assertTrue(listConfig.length > 0);
+        Set<File> listConfigs = FileUtil.findFilesObject(testcases, ".*\\.config");
+        assertTrue(listConfigs.size() > 0);
         // Create a FolderBuildInfo to similate the CompatibilityBuildProvider
         FolderBuildInfo stubFolder = new FolderBuildInfo("-1", "-1");
         stubFolder.setRootDir(new File(ctsRoot));
@@ -213,7 +205,7 @@
 
         List<String> missingMandatoryParameters = new ArrayList<>();
         // We expect to be able to load every single config in testcases/
-        for (File config : listConfig) {
+        for (File config : listConfigs) {
             IConfiguration c = ConfigurationFactory.getInstance()
                     .createConfigurationFromArgs(new String[] {config.getAbsolutePath()});
             if (c.getDeviceConfig().size() > 2) {
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index 97ee339..94a65bf 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -29,18 +29,17 @@
 import org.junit.runners.JUnit4;
 
 import java.io.File;
-import java.io.FilenameFilter;
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Tests to validate that the build is containing usable test artifact.
@@ -83,23 +82,31 @@
          * and embed native libraries.
          */
         APK_EXCEPTIONS.add("CtsExtractNativeLibsAppFalse64");
+
+        /**
+         * These apks are prebuilts needed for some tests
+         */
+        APK_EXCEPTIONS.add("CtsApkVerityTestAppPrebuilt");
+        APK_EXCEPTIONS.add("CtsApkVerityTestApp2Prebuilt");
+
+        /**
+         * Data apk used by SimpleperfTestCases
+         */
+        APK_EXCEPTIONS.add("base");
     }
 
     private static final Set<String> BINARY_EXCEPTIONS = new HashSet<>();
     static {
         /**
-         * Tests that build for either 32 bit or 64 bit only.
-         */
-        BINARY_EXCEPTIONS.add("CVE-2017-0684" + "32");
-        BINARY_EXCEPTIONS.add("CVE_2019_2135" + "64");
-        BINARY_EXCEPTIONS.add("CVE-2020-0037" + "64");
-        BINARY_EXCEPTIONS.add("CVE-2020-0038" + "64");
-        BINARY_EXCEPTIONS.add("CVE-2020-0039" + "64");
-
-        /**
-         * This binary is a host side helper, so we do not need to check it.
+         * These binaries are host side helpers, so we do not need to check them.
          */
         BINARY_EXCEPTIONS.add("sepolicy-analyze");
+        BINARY_EXCEPTIONS.add("avbtool");
+        BINARY_EXCEPTIONS.add("img2simg");
+        BINARY_EXCEPTIONS.add("lpmake");
+        BINARY_EXCEPTIONS.add("lpunpack");
+        BINARY_EXCEPTIONS.add("sign_virt_apex");
+        BINARY_EXCEPTIONS.add("simg2img");
     }
 
     private static final String BINARY_EXCEPTIONS_REGEX [] = {
@@ -126,26 +133,22 @@
      * the two abis required and the second one will fail.
      */
     @Test
-    public void testApksAbis() {
+    public void testApksAbis() throws IOException {
         String ctsRoot = System.getProperty("CTS_ROOT");
         File testcases = new File(ctsRoot, "/android-cts/testcases/");
         if (!testcases.exists()) {
             fail(String.format("%s does not exists", testcases));
             return;
         }
-        File[] listApks = testcases.listFiles(new FilenameFilter() {
-            @Override
-            public boolean accept(File dir, String name) {
-                for (String apk : APK_EXCEPTIONS) {
-                    if (name.startsWith(apk)) {
-                        return false;
+        Set<File> listApks = FileUtil.findFilesObject(testcases, ".*\\.apk");
+        listApks.removeIf(
+                a -> {for (String apk : APK_EXCEPTIONS) {
+                    if (a.getName().startsWith(apk)) {
+                        return true;
                     }
                 }
-
-                return name.endsWith(".apk");
-            }
-        });
-        assertTrue(listApks.length > 0);
+                return false;});
+        assertTrue(listApks.size() > 0);
         int maxAbi = 0;
         Map<String, Integer> apkToAbi = new HashMap<>();
 
@@ -205,38 +208,37 @@
      * If there is only one bitness, then we check that it's the right one.
      */
     @Test
-    public void testBinariesAbis() {
+    public void testBinariesAbis() throws IOException {
         String ctsRoot = System.getProperty("CTS_ROOT");
         File testcases = new File(ctsRoot, "/android-cts/testcases/");
         if (!testcases.exists()) {
             fail(String.format("%s does not exist", testcases));
             return;
         }
-        String[] listBinaries = testcases.list(new FilenameFilter() {
-            @Override
-            public boolean accept(File dir, String name) {
+        Set<File> listBinaries = FileUtil.findFilesObject(testcases, ".*");
+        listBinaries.removeIf(f -> {
+                String name = f.getName();
                 if (name.contains(".")) {
-                    return false;
+                    return true;
                 }
                 if (BINARY_EXCEPTIONS.contains(name)) {
-                    return false;
+                    return true;
                 }
                 for (String suffixException : BINARY_SUFFIX_EXCEPTIONS) {
                     if (name.endsWith(suffixException)) {
-                        return false;
+                        return true;
                     }
                 }
-                File file = new File(dir, name);
-                if (file.isDirectory()) {
-                    return false;
+                if (f.isDirectory()) {
+                    return true;
                 }
-                if (!file.canExecute()) {
-                    return false;
+                if (!f.canExecute()) {
+                    return true;
                 }
                 try {
                     // Ignore python binaries
-                    if (FileUtil.readStringFromFile(file).startsWith("#!/usr/bin/env python")) {
-                        return false;
+                    if (FileUtil.readStringFromFile(f).startsWith("#!/usr/bin/env python")) {
+                        return true;
                     }
                 } catch (IOException e) {
                     throw new RuntimeException(e);
@@ -244,14 +246,13 @@
                 for(String pattern: BINARY_EXCEPTIONS_REGEX) {
                     Matcher matcher = Pattern.compile(pattern).matcher(name);
                     if (matcher.matches()) {
-                        return false;
+                        return true;
                     }
                 }
-                return true;
-            }
+                return false;
         });
-        assertTrue(listBinaries.length > 0);
-        List<String> orderedList = Arrays.asList(listBinaries);
+        assertTrue(listBinaries.size() > 0);
+        List<String> orderedList = listBinaries.stream().map(f->f.getName()).collect(Collectors.toList());
         // we sort to have binary starting with same name, next to each other. The last two
         // characters of their name with be the bitness (32 or 64).
         Collections.sort(orderedList);