Merge "Wait for alert dialog" into tm-dev
diff --git a/apps/CameraITS/tests/scene1_2/test_raw_exposure.py b/apps/CameraITS/tests/scene1_2/test_raw_exposure.py
index 9b4afe0..5bd44e8 100644
--- a/apps/CameraITS/tests/scene1_2/test_raw_exposure.py
+++ b/apps/CameraITS/tests/scene1_2/test_raw_exposure.py
@@ -129,11 +129,14 @@
     allow_under_saturated = False
     # Check pixel means are increasing (with small tolerance)
     for ch, color in enumerate(COLORS):
-      e_msg = 'ISO=%d, %s, exp %3fms mean: %.2f, %s mean: %.2f, TOL=%.f%%' % (
-          sens, color, exps[i-1], mean[ch],
-          'black level' if i == 1 else 'exp_time %.3fms'%exps[i-2],
-          prev_mean[ch], IMG_DELTA_THRESH*100)
       if mean[ch] <= prev_mean[ch] * IMG_DELTA_THRESH:
+        e_msg = f'{color} not increasing with increased exp time! ISO: {sens}, '
+        if i == 1:
+          e_msg += f'black_level: {black_levels[ch]}, '
+        else:
+          e_msg += f'exp[i-1]: {exps[i-2]:.3f}ms, mean[i-1]: {prev_mean[ch]:.2f}, '
+        e_msg += (f'exp[i]: {exps[i-1]:.3f}ms, mean[i]: {mean[ch]}, '
+                  f'TOL: {IMG_DELTA_THRESH}')
         raise AssertionError(e_msg)
 
 
diff --git a/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py b/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
index bb982d9..59ead98 100644
--- a/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
+++ b/apps/CameraITS/tests/scene1_2/test_yuv_jpeg_all.py
@@ -51,6 +51,9 @@
   """
   out_surface = {'width': size[0], 'height': size[1], 'format': img_type}
   cap = cam.do_capture(req, out_surface)
+  logging.debug('e_cap: %d, s_cap: %d',
+                cap['metadata']['android.sensor.exposureTime'],
+                cap['metadata']['android.sensor.sensitivity'])
   if img_type == 'jpg':
     if cap['format'] != 'jpeg':
       raise AssertionError(f"{cap['format']} != jpeg")
@@ -67,6 +70,7 @@
   if debug:
     image_processing_utils.write_image(img, '%s_%s_w%d_h%d.jpg'%(
         os.path.join(log_path, NAME), img_type, size[0], size[1]))
+
   if img_type == 'jpg':
     if img.shape[0] != size[1]:
       raise AssertionError(f'{img.shape[0]} != {size[1]}')
@@ -107,6 +111,7 @@
       # should look the same (once converted by the image_processing_utils).
       e, s = target_exposure_utils.get_target_exposure_combos(
           log_path, cam)['midExposureTime']
+      logging.debug('e_req: %d, s_req: %d', e, s)
       req = capture_request_utils.manual_capture_request(s, e, 0.0, True, props)
 
       rgbs = []
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 35cd382..5f59a49 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -28,7 +28,6 @@
 import opencv_processing_utils
 
 _ANDROID11_API_LEVEL = 30
-_FOV_PERCENT_RTOL = 0.15  # Relative tolerance on circle FoV % to expected.
 _NAME = os.path.splitext(os.path.basename(__file__))[0]
 _PREVIEW_SIZE = (1920, 1080)
 
@@ -140,21 +139,6 @@
   return False
 
 
-def _check_fov(circle, ref_fov, w, h, first_api_level):
-  """Check the FoV for correct size."""
-  fov_percent = image_fov_utils.calc_circle_image_ratio(
-      circle['r'], w, h)
-  chk_percent = image_fov_utils.calc_expected_circle_image_ratio(
-      ref_fov, w, h)
-  chk_enabled = _is_checked_aspect_ratio(first_api_level, w, h)
-  if chk_enabled and not np.isclose(fov_percent, chk_percent,
-                                    rtol=_FOV_PERCENT_RTOL):
-    e_msg = 'FoV %%: %.2f, Ref FoV %%: %.2f, ' % (fov_percent, chk_percent)
-    e_msg += 'TOL=%.f%%, img: %dx%d, ref: %dx%d' % (
-        _FOV_PERCENT_RTOL*100, w, h, ref_fov['w'], ref_fov['h'])
-    return e_msg
-
-
 class AspectRatioAndCropTest(its_base_test.ItsBaseTest):
   """Test aspect ratio/field of view/cropping for each tested fmt combinations.
 
@@ -305,11 +289,12 @@
 
           # Check pass/fail for fov coverage for all fmts in AR_CHECKED
           img /= 255  # image_processing_utils uses [0, 1].
-          fov_chk_msg = _check_fov(circle, ref_fov, w_iter, h_iter,
-                                   first_api_level)
-          if fov_chk_msg:
-            failed_fov.append(fov_chk_msg)
-            image_processing_utils.write_image(img, img_name, True)
+          if _is_checked_aspect_ratio(first_api_level, w_iter, h_iter):
+            fov_chk_msg = image_fov_utils.check_fov(
+                circle, ref_fov, w_iter, h_iter)
+            if fov_chk_msg:
+              failed_fov.append(fov_chk_msg)
+              image_processing_utils.write_image(img, img_name, True)
 
           # Check pass/fail for aspect ratio.
           ar_chk_msg = image_fov_utils.check_ar(
diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
index af7e5d5..399aa05 100644
--- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
@@ -21,10 +21,41 @@
 import camera_properties_utils
 import its_session_utils
 import video_processing_utils
+import capture_request_utils
+import image_processing_utils
+import opencv_processing_utils
+import image_fov_utils
 
 _ANDROID13_API_LEVEL = 32
 _NAME = os.path.splitext(os.path.basename(__file__))[0]
-_VIDEO_RECORDING_DURATION_SECONDS = 2
+_VIDEO_RECORDING_DURATION_SECONDS = 3
+_FOV_PERCENT_RTOL = 0.15  # Relative tolerance on circle FoV % to expected.
+_AR_CHECKED_PRE_API_30 = ('4:3', '16:9', '18:9')
+_AR_DIFF_ATOL = 0.01
+
+
+def _print_failed_test_results(failed_ar, failed_fov, failed_crop,
+                               quality):
+  """Print failed test results."""
+  if failed_ar:
+    logging.error('Aspect ratio test summary for %s', quality)
+    logging.error('Images failed in the aspect ratio test:')
+    logging.error('Aspect ratio value: width / height')
+    for fa in failed_ar:
+      logging.error('%s', fa)
+
+  if failed_fov:
+    logging.error('FoV test summary for %s', quality)
+    logging.error('Images failed in the FoV test:')
+    for fov in failed_fov:
+      logging.error('%s', str(fov))
+
+  if failed_crop:
+    logging.error('Crop test summary for %s', quality)
+    logging.error('Images failed in the crop test:')
+    logging.error('Circle center (H x V) relative to the image center.')
+    for fc in failed_crop:
+      logging.error('%s', fc)
 
 
 class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
@@ -86,6 +117,10 @@
 
   def test_video_aspect_ratio_and_crop(self):
     logging.debug('Starting %s', _NAME)
+    failed_ar = []  # Streams failed the aspect ratio test.
+    failed_crop = []  # Streams failed the crop test.
+    failed_fov = []  # Streams that fail FoV test.
+
     with its_session_utils.ItsSession(
         device_id=self.dut.serial,
         camera_id=self.camera_id,
@@ -106,15 +141,127 @@
           self.camera_id)
       logging.debug('Supported video qualities: %s', supported_video_qualities)
 
+      # Determine camera capabilities.
+      full_or_better = camera_properties_utils.full_or_better(props)
+      raw_avlb = camera_properties_utils.raw16(props)
+      fls_logical = props['android.lens.info.availableFocalLengths']
+      logging.debug('logical available focal lengths: %s', str(fls_logical))
+      fls_physical = props['android.lens.info.availableFocalLengths']
+      logging.debug('physical available focal lengths: %s',
+                    str(fls_physical))
+
+      req = capture_request_utils.auto_capture_request()
+      ref_img_name_stem = f'{os.path.join(self.log_path, _NAME)}'
+
+      if raw_avlb and (fls_physical == fls_logical):
+        logging.debug('RAW')
+        ref_fov, cc_ct_gt, aspect_ratio_gt = (
+            image_fov_utils.find_fov_reference(
+                cam, req, props, 'RAW', ref_img_name_stem))
+      else:
+        logging.debug('JPEG')
+        ref_fov, cc_ct_gt, aspect_ratio_gt = (
+            image_fov_utils.find_fov_reference(
+                cam, req, props, 'JPEG', ref_img_name_stem))
+
+      run_crop_test = full_or_better and raw_avlb
+
       for quality_profile_id_pair in supported_video_qualities:
         quality = quality_profile_id_pair.split(':')[0]
         profile_id = quality_profile_id_pair.split(':')[-1]
         # Check if we support testing this quality.
-        if quality in video_processing_utils._ITS_SUPPORTED_QUALITIES:
-          logging.debug("Testing video recording for quality: %s" % quality)
-          cam.do_basic_recording(profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS)
-        # TODO(ruchamk): Add processing of video recordings, aspect ratio
-        # and crop checks.
+        if quality in video_processing_utils.ITS_SUPPORTED_QUALITIES:
+          logging.debug('Testing video recording for quality: %s', quality)
+          video_recording_obj = cam.do_basic_recording(
+              profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS)
+          logging.debug('video_recording_obj: %s', video_recording_obj)
+          # TODO(ruchamk): Modify video recording object to send videoFrame
+          # width and height instead of videoSize to avoid string operation
+          # here.
+          video_size = video_recording_obj['videoSize']
+          width = int(video_size.split('x')[0])
+          height = int(video_size.split('x')[-1])
+
+          # Pull the video recording file from the device.
+          self.dut.adb.pull([video_recording_obj['recordedOutputPath'],
+                             self.log_path])
+          logging.debug('Recorded video is available at: %s',
+                        self.log_path)
+          mp4_file_name = video_recording_obj['recordedOutputPath'].split('/')[-1]
+          logging.debug('mp4_file_name: %s', mp4_file_name)
+
+          key_frame_files = []
+          key_frame_files = video_processing_utils.extract_key_frames_from_video(
+              self.log_path, mp4_file_name)
+          logging.debug('key_frame_files:%s', key_frame_files)
+
+          # Get the key frame file to process.
+          last_key_frame_file = video_processing_utils.get_key_frame_to_process(
+              key_frame_files)
+          logging.debug('last_key_frame: %s', last_key_frame_file)
+          last_key_frame_path = os.path.join(self.log_path, last_key_frame_file)
+
+          # Convert lastKeyFrame to numpy array
+          np_image = image_processing_utils.convert_image_to_numpy_array(
+              last_key_frame_path)
+          logging.debug('numpy image shape: %s', np_image.shape)
+
+          # Check fov
+          circle = opencv_processing_utils.find_circle(
+              np_image, ref_img_name_stem, image_fov_utils.CIRCLE_MIN_AREA,
+              image_fov_utils.CIRCLE_COLOR)
+
+          # Check pass/fail for fov coverage for all fmts in AR_CHECKED
+          fov_chk_msg = image_fov_utils.check_fov(
+              circle, ref_fov, width, height)
+          if fov_chk_msg:
+            img_name = '%s_%s_w%d_h%d_fov.png' % (
+                os.path.join(self.log_path, _NAME), quality, width, height)
+            fov_chk_quality_msg = f'Quality: {quality} {fov_chk_msg}'
+            failed_fov.append(fov_chk_quality_msg)
+            image_processing_utils.write_image(np_image/255, img_name, True)
+
+          # Check pass/fail for aspect ratio.
+          ar_chk_msg = image_fov_utils.check_ar(
+              circle, aspect_ratio_gt, width, height,
+              f'{quality}')
+          if ar_chk_msg:
+            img_name = '%s_%s_w%d_h%d_ar.png' % (
+                os.path.join(self.log_path, _NAME), quality, width, height)
+            failed_ar.append(ar_chk_msg)
+            image_processing_utils.write_image(np_image/255, img_name, True)
+
+          # Check pass/fail for crop.
+          if run_crop_test:
+            # Normalize the circle size to 1/4 of the image size, so that
+            # circle size won't affect the crop test result
+            crop_thresh_factor = ((min(ref_fov['w'], ref_fov['h']) / 4.0) /
+                                  max(ref_fov['circle_w'], ref_fov['circle_h']))
+            crop_chk_msg = image_fov_utils.check_crop(
+                circle, cc_ct_gt, width, height,
+                f'{quality}', crop_thresh_factor)
+            if crop_chk_msg:
+              crop_img_name = '%s_%s_w%d_h%d_crop.png' % (
+                  os.path.join(self.log_path, _NAME), quality, width, height)
+              opencv_processing_utils.append_circle_center_to_img(
+                  circle, np_image*255, crop_img_name)
+              failed_crop.append(crop_chk_msg)
+              image_processing_utils.write_image(np_image/255,
+                                                 crop_img_name, True)
+          else:
+            logging.debug('Crop test skipped')
+
+      # Print any failed test results.
+      _print_failed_test_results(failed_ar, failed_fov, failed_crop, quality)
+      e_msg = ''
+      if failed_ar:
+        e_msg = 'Aspect ratio '
+      if failed_fov:
+        e_msg += 'FoV '
+      if failed_crop:
+        e_msg += 'Crop '
+      if e_msg:
+        raise AssertionError(f'{e_msg}check failed.')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CameraITS/utils/image_fov_utils.py b/apps/CameraITS/utils/image_fov_utils.py
index b9caf33..8ac4ece 100644
--- a/apps/CameraITS/utils/image_fov_utils.py
+++ b/apps/CameraITS/utils/image_fov_utils.py
@@ -26,7 +26,7 @@
 
 CIRCLE_COLOR = 0  # [0: black, 255: white]
 CIRCLE_MIN_AREA = 0.01  # 1% of image size
-
+FOV_PERCENT_RTOL = 0.15  # Relative tolerance on circle FoV % to expected.
 LARGE_SIZE_IMAGE = 2000  # Size of a large image (compared against max(w, h))
 THRESH_AR_L = 0.02  # Aspect ratio test threshold of large images
 THRESH_AR_S = 0.075  # Aspect ratio test threshold of mini images
@@ -35,6 +35,17 @@
 THRESH_MIN_PIXEL = 4  # Crop test allowed offset
 
 
+def check_fov(circle, ref_fov, w, h):
+  """Check the FoV for correct size."""
+  fov_percent = calc_circle_image_ratio(circle['r'], w, h)
+  chk_percent = calc_expected_circle_image_ratio(ref_fov, w, h)
+  if not math.isclose(fov_percent, chk_percent, rel_tol=FOV_PERCENT_RTOL):
+    e_msg = (f'FoV %: {fov_percent:.2f}, Ref FoV %: {chk_percent:.2f}, '
+             f'TOL={FOV_PERCENT_RTOL*100}%, img: {w}x{h}, ref: '
+             f"{ref_fov['w']}x{ref_fov['h']}")
+    return e_msg
+
+
 def check_ar(circle, ar_gt, w, h, e_msg_stem):
   """Check the aspect ratio of the circle.
 
diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py
index 6da2d92..3ebee72 100644
--- a/apps/CameraITS/utils/image_processing_utils.py
+++ b/apps/CameraITS/utils/image_processing_utils.py
@@ -245,6 +245,19 @@
   h = img.size[1]
   return numpy.array(img).reshape(h, w, 3) / 255.0
 
+def convert_image_to_numpy_array(image_path):
+  """
+  Converts an image at the path image_path to numpy array and returns the array.
+
+  Args:
+    image_path: file path
+  Returns:
+    numpy array
+  """
+  if not os.path.exists(image_path):
+    raise assertionError(f'{image_path} does not exist.')
+  image = Image.open(image_path)
+  return numpy.array(image)
 
 def convert_capture_to_planes(cap, props=None):
   """Convert a captured image object to separate image planes.
diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py
index 8c7881b..35c21c4 100644
--- a/apps/CameraITS/utils/sensor_fusion_utils.py
+++ b/apps/CameraITS/utils/sensor_fusion_utils.py
@@ -615,7 +615,8 @@
   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.ylim([np.amin(z), np.amax(z)])
+  pylab.ylabel('gyro x,y movement (rads/s)')
   pylab.legend()
 
   # z on separate axes
diff --git a/apps/CameraITS/utils/target_exposure_utils.py b/apps/CameraITS/utils/target_exposure_utils.py
index 279b5ea..65e53ec 100644
--- a/apps/CameraITS/utils/target_exposure_utils.py
+++ b/apps/CameraITS/utils/target_exposure_utils.py
@@ -69,71 +69,71 @@
 
     # Combo 1: smallest legal exposure time.
     e1_expt = exp_time_range[0]
-    e1_sens = exposure / e1_expt
+    e1_sens = int(exposure / e1_expt)
     if e1_sens > sens_range[1]:
       e1_sens = sens_range[1]
-      e1_expt = exposure / e1_sens
-    e1_logging = (f'e1 exp: {e1_expt}, sens: {e1_sens}')
+      e1_expt = int(exposure / e1_sens)
+    e1_logging = (f'MinExp exp: {e1_expt}, sens: {e1_sens}')
     logging.debug('%s', e1_logging)
 
     # Combo 2: largest legal exposure time.
     e2_expt = exp_time_range[1]
-    e2_sens = exposure / e2_expt
+    e2_sens = int(exposure / e2_expt)
     if e2_sens < sens_range[0]:
       e2_sens = sens_range[0]
-      e2_expt = exposure / e2_sens
-    e2_logging = (f'e2 exp: {e2_expt}, sens: {e2_sens}')
+      e2_expt = int(exposure / e2_sens)
+    e2_logging = (f'MaxExp exp: {e2_expt}, sens: {e2_sens}')
     logging.debug('%s', e2_logging)
 
     # Combo 3: smallest legal sensitivity.
     e3_sens = sens_range[0]
-    e3_expt = exposure / e3_sens
+    e3_expt = int(exposure / e3_sens)
     if e3_expt > exp_time_range[1]:
       e3_expt = exp_time_range[1]
-      e3_sens = exposure / e3_expt
-    e3_logging = (f'e3 exp: {e3_expt}, sens: {e3_sens}')
+      e3_sens = int(exposure / e3_expt)
+    e3_logging = (f'MinISO exp: {e3_expt}, sens: {e3_sens}')
     logging.debug('%s', e3_logging)
 
     # Combo 4: largest legal sensitivity.
     e4_sens = sens_range[1]
-    e4_expt = exposure / e4_sens
+    e4_expt = int(exposure / e4_sens)
     if e4_expt < exp_time_range[0]:
       e4_expt = exp_time_range[0]
-      e4_sens = exposure / e4_expt
-    e4_logging = (f'e4 exp: {e4_expt}, sens: {e4_sens}')
+      e4_sens = int(exposure / e4_expt)
+    e4_logging = (f'MaxISO exp: {e4_expt}, sens: {e4_sens}')
     logging.debug('%s', e4_logging)
 
     # Combo 5: middle exposure time.
-    e5_expt = (exp_time_range[0] + exp_time_range[1]) / 2.0
-    e5_sens = exposure / e5_expt
+    e5_expt = int((exp_time_range[0] + exp_time_range[1]) / 2.0)
+    e5_sens = int(exposure / e5_expt)
     if e5_sens > sens_range[1]:
       e5_sens = sens_range[1]
-      e5_expt = exposure / e5_sens
+      e5_expt = int(exposure / e5_sens)
     if e5_sens < sens_range[0]:
       e5_sens = sens_range[0]
-      e5_expt = exposure / e5_sens
-    e5_logging = (f'e5 exp: {e5_expt}, sens: {e5_sens}')
+      e5_expt = int(exposure / e5_sens)
+    e5_logging = (f'MidExp exp: {e5_expt}, sens: {e5_sens}')
     logging.debug('%s', e5_logging)
 
     # Combo 6: middle sensitivity.
-    e6_sens = (sens_range[0] + sens_range[1]) / 2.0
-    e6_expt = exposure / e6_sens
+    e6_sens = int((sens_range[0] + sens_range[1]) / 2.0)
+    e6_expt = int(exposure / e6_sens)
     if e6_expt > exp_time_range[1]:
       e6_expt = exp_time_range[1]
-      e6_sens = exposure / e6_expt
+      e6_sens = int(exposure / e6_expt)
     if e6_expt < exp_time_range[0]:
       e6_expt = exp_time_range[0]
-      e6_sens = exposure / e6_expt
-    e6_logging = (f'e6 exp: {e6_expt}, sens: {e6_sens}')
+      e6_sens = int(exposure / e6_expt)
+    e6_logging = (f'MidISO exp: {e6_expt}, sens: {e6_sens}')
     logging.debug('%s', e6_logging)
 
     return {
-        'minExposureTime': (int(e1_expt), int(e1_sens)),
-        'maxExposureTime': (int(e2_expt), int(e2_sens)),
-        'minSensitivity': (int(e3_expt), int(e3_sens)),
-        'maxSensitivity': (int(e4_expt), int(e4_sens)),
-        'midExposureTime': (int(e5_expt), int(e5_sens)),
-        'midSensitivity': (int(e6_expt), int(e6_sens))
+        'minExposureTime': (e1_expt, e1_sens),
+        'maxExposureTime': (e2_expt, e2_sens),
+        'minSensitivity': (e3_expt, e3_sens),
+        'maxSensitivity': (e4_expt, e4_sens),
+        'midExposureTime': (e5_expt, e5_sens),
+        'midSensitivity': (e6_expt, e6_sens)
     }
 
 
diff --git a/apps/CameraITS/utils/video_processing_utils.py b/apps/CameraITS/utils/video_processing_utils.py
index 967bb9e..f862c59 100644
--- a/apps/CameraITS/utils/video_processing_utils.py
+++ b/apps/CameraITS/utils/video_processing_utils.py
@@ -16,7 +16,13 @@
 # Each item in this list corresponds to quality levels defined per
 # CamcorderProfile. For Video ITS, we will currently test below qualities
 # only if supported by the camera device.
-_ITS_SUPPORTED_QUALITIES = (
+import logging
+import os.path
+import subprocess
+import time
+
+
+ITS_SUPPORTED_QUALITIES = (
     'HIGH',
     '2160P',
     '1080P',
@@ -28,3 +34,62 @@
     'LOW',
     'VGA'
 )
+
+
+def extract_key_frames_from_video(log_path, mp4_file_name):
+  """
+  Returns a list of extracted key frames.
+
+  Ffmpeg tool is used to extract key frames from the video at path
+  os.path.join(log_path, mp4_file_name).
+  The extracted key frames will have the name mp4_file_name with "_key_frame"
+  suffix to identify the frames for video of each quality.Since there can be
+  multiple key frames, each key frame image will be differentiated with it's
+  frame index.All the extracted key frames will be available in  jpeg format
+  at the same path as the video file.
+
+  Args:
+    log_path: path for video file directory
+    mp4_file_name: name of the file in mp4 format.
+    Ex: VID_20220325_050918_0_CIF_352x288.mp4
+  Returns:
+    key_frame_files: A list of paths for each key frame extracted from the
+    video.
+  """
+  ffmpeg_image_name = f"{mp4_file_name.split('.')[0]}_key_frame"
+  ffmpeg_image_file_path = os.path.join(log_path, ffmpeg_image_name + '_%02d.png')
+  cmd = ['ffmpeg',
+    '-skip_frame',
+    'nokey',
+    '-i',
+    os.path.join(log_path, mp4_file_name),
+    '-vsync',
+    'vfr',
+    '-frame_pts',
+    'true' ,
+    ffmpeg_image_file_path,
+  ]
+  logging.debug('Extracting key frames for: %s' % mp4_file_name)
+  output = subprocess.call(cmd)
+  arr = os.listdir(os.path.join(log_path))
+  key_frame_files = []
+  for file in arr:
+    if '.png' in file and not os.path.isdir(file) and ffmpeg_image_name in file:
+      key_frame_files.append(file)
+  return key_frame_files
+
+
+def get_key_frame_to_process(key_frame_files):
+  """
+  Returns the key frame file from the list of key_frame_files.
+
+  If the size of the list is 1 then the file in the list will be returned else
+  the file with highest frame_index will be returned for further processing.
+
+  Args:
+    key_frame_files: A list of key frame files.
+  Returns:
+    key_frame_file to be used for further processing.
+  """
+  key_frame_files.sort()
+  return key_frame_files[-1]
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9e7dab9..66c1d2f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -51,6 +51,7 @@
     <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
     <uses-permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY" />
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
     <uses-feature android:name="android.hardware.camera" android:required="false"/>
     <uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
     <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
@@ -2948,6 +2949,7 @@
                     android:value="android.hardware.type.watch" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
+            <meta-data android:name="CddTest" android:value="7.7.1/H-1-1" />
         </activity>
 
         <activity android:name=".usb.accessory.AccessoryAttachmentHandler"
@@ -2977,6 +2979,9 @@
                     android:value="android.hardware.type.watch" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
+            <meta-data android:name="CddTest" android:value="7.7.2/C-1-1" />
+            <meta-data android:name="ApiTest"
+                       android:value="android.hardware.usb.UsbDeviceConnection#controlTransfer|android.hardware.usb.UsbDeviceConnection#bulkTransfer" />
         </activity>
 
         <activity android:name=".usb.mtp.MtpHostTestActivity" android:label="@string/mtp_host_test"
@@ -2991,6 +2996,7 @@
                        android:value="android.hardware.type.automotive:android.hardware.type.television" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
+            <meta-data android:name="CddTest" android:value="7.7.2/C-3-1" />
         </activity>
 
 <!-- Turned off Sensor Power Test in initial L release
@@ -3085,6 +3091,7 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+            <meta-data android:name="test_required_features" android:value="android.software.secure_lock_screen" />
             <meta-data android:name="test_excluded_features"
                        android:value="android.hardware.type.automotive" />
             <meta-data android:name="display_mode" android:value="multi_display_mode" />
@@ -3222,7 +3229,7 @@
                 <action android:name="android.service.notification.NotificationListenerService" />
             </intent-filter>
             <meta-data android:name="android.service.notification.default_filter_types"
-                       android:value="alerting|silent" />
+                       android:value="conversations|alerting|silent" />
             <meta-data android:name="android.service.notification.disabled_filter_types"
                        android:value="ongoing" />
         </service>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index c2d1897..dc3bed4 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3307,6 +3307,8 @@
     <string name="provisioning_byod_work_notification_instruction">
         Please press the Go button to trigger a notification.\n
         \n
+        If a permission is requested, grant it and press the Go button again.\n
+        \n
         Verify that the notification is badged (see sample badge below). Then mark this test accordingly.
     </string>
     <string name="provisioning_byod_notification_title">This is a notification</string>
@@ -3610,7 +3612,7 @@
     <string name="provisioning_byod_turn_off_work_prepare_notifications">Prepare a work notification</string>
     <string name="provisioning_byod_turn_off_work_prepare_notifications_instruction">
         This is a test setup step.\n
-        1. Press the go button to send a work notification.\n
+        1. Press the go button to send a work notification. (if a permission is requested, grant it and press the go button again). \n
         2. Verify that the notification is displayed and mark this test as passed.\n
         (Note: in the following test, you will be asked to verify the notification disappears after work profile is turned off.)
     </string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
index ac451e4..ddadfff 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
@@ -226,7 +226,7 @@
 
         //Init bands for Mic test
         mBandSpecsMic[0] = new AudioBandSpecs(
-                5, 100,          /* frequency start,stop */
+                30, 100,          /* frequency start,stop */
                 20.0, -20.0,     /* start top,bottom value */
                 20.0, -20.0      /* stop top,bottom value */);
 
@@ -242,7 +242,7 @@
 
         //Init bands for Tone test
         mBandSpecsTone[0] = new AudioBandSpecs(
-                5, 900,          /* frequency start,stop */
+                30, 900,          /* frequency start,stop */
                 -10.0, -100.0,     /* start top,bottom value */
                 -10.0, -100.0      /* stop top,bottom value */);
 
@@ -258,7 +258,7 @@
 
       //Init bands for Background test
         mBandSpecsBack[0] = new AudioBandSpecs(
-                5, 100,          /* frequency start,stop */
+                30, 100,          /* frequency start,stop */
                 10.0, -120.0,     /* start top,bottom value */
                 -10.0, -120.0      /* stop top,bottom value */);
 
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 3f27a2d..55791c6 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
@@ -59,6 +59,7 @@
 import android.view.View;
 import android.view.Surface;
 import android.view.TextureView;
+import android.widget.Adapter;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
@@ -98,6 +99,7 @@
                         1f,    1.772f,        0f, 0f, -226.816f,
                         0f,        0f,        0f, 1f,        0f
                     });
+    private static final String CAMERA_ID_PREFIX = "Camera ";
 
     private TextureView mPreviewView;
     private SurfaceTexture mPreviewTexture;
@@ -262,7 +264,7 @@
         String[] cameraNames = new String[cameraIdSet.size()];
         int i = 0;
         for (String id : cameraIdSet) {
-            cameraNames[i++] = "Camera " + id;
+            cameraNames[i++] = CAMERA_ID_PREFIX + id;
         }
         mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
         mCameraSpinner.setAdapter(
@@ -592,11 +594,10 @@
         shutdownCamera();
 
         mCurrentCameraIndex = index;
+        Adapter adapter = mCameraSpinner.getAdapter();
+        String idDisplayed = (String) adapter.getItem(index);
+        mCameraId = idDisplayed.substring(CAMERA_ID_PREFIX.length());
 
-        Set<String> cameraIdSet = mTestCases.keySet();
-        List<String> stringsList = new ArrayList<>(cameraIdSet);
-
-        mCameraId = stringsList.get(index);
         try {
             mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
             mCameraDevice = mBlockingCameraManager.openCamera(mCameraId,
@@ -761,7 +762,8 @@
 
     private void startPreview() {
         try {
-            if (mPreviewSize == null || !mPreviewSize.equals(mNextCombination.mPreviewSize)) {
+            if (mPreviewSize == null || !mPreviewSize.equals(mNextCombination.mPreviewSize) ||
+                    mYuvImageReader == null) {
                 mPreviewSize = mNextCombination.mPreviewSize;
 
                 mYuvImageReader = ImageReader.newInstance(mPreviewSize.getWidth(),
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 520d95f..caeec91 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
@@ -1703,12 +1703,12 @@
     private void doGetSupportedVideoQualities(String id) throws ItsException {
         int cameraId = Integer.parseInt(id);
         StringBuilder profiles = new StringBuilder();
-        appendSupportProfile(profiles, "480", CamcorderProfile.QUALITY_480P, cameraId);
-        appendSupportProfile(profiles, "1080", CamcorderProfile.QUALITY_1080P, cameraId);
-        appendSupportProfile(profiles, "2160", CamcorderProfile.QUALITY_2160P, cameraId);
+        appendSupportProfile(profiles, "480P", CamcorderProfile.QUALITY_480P, cameraId);
+        appendSupportProfile(profiles, "1080P", CamcorderProfile.QUALITY_1080P, cameraId);
+        appendSupportProfile(profiles, "2160P", CamcorderProfile.QUALITY_2160P, cameraId);
         appendSupportProfile(profiles, "2k", CamcorderProfile.QUALITY_2K, cameraId);
         appendSupportProfile(profiles, "4KDCI", CamcorderProfile.QUALITY_4KDCI, cameraId);
-        appendSupportProfile(profiles, "720", CamcorderProfile.QUALITY_720P, cameraId);
+        appendSupportProfile(profiles, "720P", CamcorderProfile.QUALITY_720P, cameraId);
         appendSupportProfile(profiles, "8KUHD", CamcorderProfile.QUALITY_8KUHD, cameraId);
         appendSupportProfile(profiles, "CIF", CamcorderProfile.QUALITY_CIF, cameraId);
         appendSupportProfile(profiles, "HIGH", CamcorderProfile.QUALITY_HIGH, cameraId);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index e67fd85..10010cb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
+import static android.Manifest.permission.POST_NOTIFICATIONS;
 import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
 import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;
 
@@ -165,6 +166,7 @@
     private static final int REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT = 4;
     private static final int REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT = 5;
     private static final int REQUEST_AUDIO_CAPTURE = 6;
+    private static final int REQUEST_POST_NOTIFICATIONS = 7;
 
     private static final String ORIGINAL_RESTRICTIONS_NAME = "original restrictions";
 
@@ -188,13 +190,24 @@
     private ArrayList<File> mTempFiles = new ArrayList<File>();
 
     private Handler mMainThreadHandler;
+    private int mNextNotificationVisibility;
 
     private void showNotification(int visibility) {
+        mNextNotificationVisibility = visibility;
+
+        if (hasPostNotificationsPermission()) {
+            showNotificationInner();
+        } else {
+            requestPostNotificationsPermission(REQUEST_POST_NOTIFICATIONS);
+        }
+    }
+
+    private void showNotificationInner() {
         final Notification notification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
                 .setSmallIcon(R.drawable.icon)
                 .setContentTitle(getString(R.string.provisioning_byod_notification_title))
                 .setContentText(getString(R.string.provisioning_byod_notification_title))
-                .setVisibility(visibility)
+                .setVisibility(mNextNotificationVisibility)
                 .setAutoCancel(true)
                 .setPublicVersion(createPublicVersionNotification())
                 .build();
@@ -597,10 +610,22 @@
                 requestCode);
     }
 
+    private boolean hasPostNotificationsPermission() {
+        return ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private void requestPostNotificationsPermission(int requestCode) {
+        ActivityCompat.requestPermissions(this,
+                new String[]{Manifest.permission.POST_NOTIFICATIONS},
+                requestCode);
+    }
+
     /**
      * Launch the right test based on the request code, after validating the right permission
      * has been granted.
      */
+    @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
             @NonNull int[] grants) {
         // Test that the right permission was granted.
@@ -616,6 +641,14 @@
                     return;
                 }
                 break;
+            case REQUEST_POST_NOTIFICATIONS:
+                if (!permissions[0].equals(POST_NOTIFICATIONS)
+                        || grants[0] != PackageManager.PERMISSION_GRANTED) {
+                    Log.e(TAG, "The test needs notifications permission.");
+                    finish();
+                    return;
+                }
+                break;
         }
 
         // Execute the right test.
@@ -627,6 +660,9 @@
             case EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST:
                 startCaptureVideoActivity(requestCode);
                 break;
+            case REQUEST_POST_NOTIFICATIONS:
+                showNotificationInner();
+                break;
             default:
                 Log.e(TAG, "Unknown action.");
                 finish();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index e91f92b..5909757 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -123,12 +123,14 @@
         tests.add(new IsEnabledTest());
         tests.add(new ServiceStartedTest());
         tests.add(new NotificationReceivedTest());
+        /*
+        // TODO (b/200701618): re-enable tests if conditions in 3.8.3.1 change to MUST
         if (!isAutomotive) {
             tests.add(new SendUserToChangeFilter());
             tests.add(new AskIfFilterChanged());
             tests.add(new NotificationTypeFilterTest());
             tests.add(new ResetChangeFilter());
-        }
+        }*/
         tests.add(new LongMessageTest());
         tests.add(new DataIntactTest());
         tests.add(new AudiblyAlertedTest());
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OWNERS
index 5627ff5..5940ede4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/OWNERS
@@ -1,2 +1,2 @@
 blindahl@google.com
-shalamanov@google.com
+kritidang@google.com
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/Policy.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/Policy.java
index ada4af5..133bf8a 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/Policy.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/Policy.java
@@ -50,18 +50,19 @@
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDelegate;
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.AppOp;
+import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeNone;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnAffiliatedProfileOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnBackgroundDeviceOwnerUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
-import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfCorporateOwnedProfileOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwnerUsingParentInstance;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerPrimaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerProfileWithNoDeviceOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwnerProfile;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnUnaffiliatedProfileOwnerSecondaryUser;
 
 import com.google.auto.value.AutoAnnotation;
@@ -192,7 +193,7 @@
     }
 
     @AutoAnnotation
-    private static IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser includeRunOnNonAffiliatedDeviceOwnerSecondaryUser() {
+    private static IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser includeRunOnNonAffiliatedDeviceOwnerSecondaryUser() {
         return new AutoAnnotation_Policy_includeRunOnNonAffiliatedDeviceOwnerSecondaryUser();
     }
 
@@ -339,6 +340,7 @@
                             "AppOp:" + appOp.appliedWith(), withAppOpAnnotations));
         }
 
+        removeShadowingAnnotations(annotations);
 
         if (annotations.isEmpty()) {
             // Don't run the original test unparameterized
@@ -393,6 +395,8 @@
             }
         }
 
+        removeShadowedAnnotations(annotations);
+
         if (annotations.isEmpty()) {
             // Don't run the original test unparameterized
             annotations.add(includeNone());
@@ -461,6 +465,8 @@
             }
         }
 
+        removeShadowedAnnotations(annotations);
+
         if (annotations.isEmpty()) {
             // Don't run the original test unparameterized
             annotations.add(includeNone());
@@ -511,6 +517,8 @@
 
         List<Annotation> annotationList = new ArrayList<>(annotations);
 
+        removeShadowingAnnotations(annotations);
+
         if (singleTestOnly) {
             // We select one annotation in an arbitrary but deterministic way
             annotationList.sort(Comparator.comparing(
@@ -577,4 +585,110 @@
 
         return true;
     }
+
+    /**
+     * Remove entries from {@code annotations} which are shadowed by another entry
+     * in {@code annotatipns} (directly or indirectly).
+     */
+    private static void removeShadowedAnnotations(Set<Annotation> annotations) {
+        Set<Class<? extends Annotation>> shadowedAnnotations = new HashSet<>();
+        for (Annotation annotation : annotations) {
+            if (annotation instanceof DynamicParameterizedAnnotation) {
+                continue; // Doesn't shadow anything
+            }
+
+            ParameterizedAnnotation parameterizedAnnotation =
+                    annotation.annotationType().getAnnotation(ParameterizedAnnotation.class);
+
+            if (parameterizedAnnotation == null) {
+                continue; // Not parameterized
+            }
+
+            for (Class<? extends Annotation> shadowedAnnotationClass
+                    : parameterizedAnnotation.shadows()) {
+                addShadowed(shadowedAnnotations, shadowedAnnotationClass);
+            }
+        }
+
+        annotations.removeIf(a -> shadowedAnnotations.contains(a.annotationType()));
+    }
+
+    private static void addShadowed(Set<Class<? extends Annotation>> shadowedAnnotations,
+            Class<? extends Annotation> annotationClass) {
+        shadowedAnnotations.add(annotationClass);
+        ParameterizedAnnotation parameterizedAnnotation =
+                annotationClass.getAnnotation(ParameterizedAnnotation.class);
+
+        if (parameterizedAnnotation == null) {
+            return;
+        }
+
+        for (Class<? extends Annotation> shadowedAnnotationClass
+                : parameterizedAnnotation.shadows()) {
+            addShadowed(shadowedAnnotations, shadowedAnnotationClass);
+        }
+    }
+
+    // This maps classes to classes which shadow them - we just need to ensure it contains all
+    // annotation classes we encounter
+    private static Map<Class<? extends Annotation>, Set<Class<? extends Annotation>>>
+            sReverseShadowMap = new HashMap<>();
+
+    /**
+     * Remove entries from {@code annotations} which are shadowing another entry
+     * in {@code annotatipns} (directly or indirectly).
+     */
+    private static void removeShadowingAnnotations(Set<Annotation> annotations) {
+        for (Annotation annotation : annotations) {
+            recordInReverseShadowMap(annotation);
+        }
+
+        Set<Class<? extends Annotation>> shadowingAnnotations = new HashSet<>();
+
+        for (Annotation annotation : annotations) {
+            shadowingAnnotations.addAll(
+                    sReverseShadowMap.getOrDefault(annotation.annotationType(), Set.of()));
+        }
+
+        annotations.removeIf(a -> shadowingAnnotations.contains(a.annotationType()));
+    }
+
+    private static void recordInReverseShadowMap(Annotation annotation) {
+        if (annotation instanceof DynamicParameterizedAnnotation) {
+            return; // Not shadowed by anything
+        }
+
+        ParameterizedAnnotation parameterizedAnnotation =
+                annotation.annotationType().getAnnotation(ParameterizedAnnotation.class);
+
+        if (parameterizedAnnotation == null) {
+            return; // Not parameterized
+        }
+
+        if (parameterizedAnnotation.shadows().length == 0) {
+            return; // Doesn't shadow anything
+        }
+
+        recordShadowedInReverseShadowMap(annotation.annotationType(), parameterizedAnnotation);
+    }
+
+    private static void recordShadowedInReverseShadowMap(Class<? extends Annotation> annotation,
+            ParameterizedAnnotation parameterizedAnnotation) {
+        for (Class<? extends Annotation> shadowedAnnotation : parameterizedAnnotation.shadows()) {
+            ParameterizedAnnotation shadowedParameterizedAnnotation =
+                    shadowedAnnotation.getAnnotation(ParameterizedAnnotation.class);
+
+            if (shadowedParameterizedAnnotation == null) {
+                continue; // Not parameterized
+            }
+
+            if (!sReverseShadowMap.containsKey(shadowedAnnotation)) {
+                sReverseShadowMap.put(shadowedAnnotation, new HashSet<>());
+            }
+
+            sReverseShadowMap.get(shadowedAnnotation).add(annotation);
+
+            recordShadowedInReverseShadowMap(annotation, shadowedParameterizedAnnotation);
+        }
+    }
 }
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/meta/ParameterizedAnnotation.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/meta/ParameterizedAnnotation.java
index bab40ca..14e0784 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/meta/ParameterizedAnnotation.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/meta/ParameterizedAnnotation.java
@@ -16,6 +16,7 @@
 
 package com.android.bedstead.harrier.annotations.meta;
 
+import java.lang.annotation.Annotation;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -34,4 +35,19 @@
 @Retention(RetentionPolicy.RUNTIME)
 @RequiresBedsteadJUnit4
 public @interface ParameterizedAnnotation {
+
+    /**
+     * Other parameterized annotations which are less powerful versions of this one.
+     *
+     * <p>For example, if this annotation represents a permission, and there is another annotation
+     * representing a permission which allows a subset of this one, then this annotation may shadow
+     * that one.
+     *
+     * <p>This will mean that these annotations will never be used together - one will be removed
+     * depending on whether the test requires the most powerful or least powerful state.
+     *
+     * <p>This should not be used if you want to explicitly test the state represented by each
+     * annotation.
+     */
+    Class<? extends Annotation>[] shadows() default {};
 }
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
index 284d7d2..71ad1e5 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedDeviceOwnerSecondaryUser.java
@@ -35,7 +35,7 @@
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@ParameterizedAnnotation
+@ParameterizedAnnotation(shadows = IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser.class)
 @RequireRunOnSecondaryUser
 @EnsureHasDeviceOwner(isPrimary = true, affiliationIds = "affiliated")
 @EnsureHasProfileOwner(affiliationIds = "affiliated")
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
index 08637b8..acc620a 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnAffiliatedProfileOwnerSecondaryUser.java
@@ -35,7 +35,7 @@
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@ParameterizedAnnotation
+@ParameterizedAnnotation(shadows = IncludeRunOnUnaffiliatedProfileOwnerSecondaryUser.class)
 @RequireRunOnSecondaryUser
 @EnsureHasDeviceOwner(affiliationIds = "affiliated")
 @EnsureHasProfileOwner(affiliationIds = "affiliated", isPrimary = true)
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
index 61c5f19..548c99b 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfCorporateOwnedProfileOwner.java
@@ -32,7 +32,7 @@
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@ParameterizedAnnotation
+@ParameterizedAnnotation(shadows = IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner.class)
 @RequireRunOnPrimaryUser
 // TODO(scottjonathan): Add annotation to create corporate-owned profile
 public @interface IncludeRunOnParentOfCorporateOwnedProfileOwner {
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner.java
index 1ed3c33..34a9d2a 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner.java
@@ -34,7 +34,7 @@
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@ParameterizedAnnotation
+@ParameterizedAnnotation(shadows = IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwnerProfile.class)
 @RequireRunOnPrimaryUser
 @EnsureHasNoDeviceOwner
 @EnsureHasWorkProfile(dpcIsPrimary = true)
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser.java
similarity index 96%
rename from common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
rename to common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser.java
index 75c047e..bb96ce1 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser.java
@@ -37,7 +37,7 @@
 @ParameterizedAnnotation
 @RequireRunOnSecondaryUser
 @EnsureHasDeviceOwner(isPrimary = true, affiliationIds = {})
-public @interface IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser {
+public @interface IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser {
     /**
      * Weight sets the order that annotations will be resolved.
      *
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyAppStreamingPolicy.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyAppStreamingPolicy.java
index 4e09bf1..8ba8f6c 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyAppStreamingPolicy.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyAppStreamingPolicy.java
@@ -18,7 +18,6 @@
 
 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_GLOBALLY;
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
 
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
@@ -29,9 +28,6 @@
  * <p>Users of this policy are
  * {@link android.app.admin.DevicePolicyManager#setNearbyAppStreamingPolicy(int)}}.
  */
-@EnterprisePolicy(dpc = {
-        APPLIED_BY_DEVICE_OWNER | APPLIES_GLOBALLY,
-        APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
-})
+@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER)
 public class NearbyAppStreamingPolicy {
 }
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyNotificationStreamingPolicy.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyNotificationStreamingPolicy.java
index d0a607f..af4b435 100644
--- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyNotificationStreamingPolicy.java
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/NearbyNotificationStreamingPolicy.java
@@ -18,7 +18,6 @@
 
 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_GLOBALLY;
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER;
 
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
@@ -29,9 +28,6 @@
  * <p>Users of this policy are
  * {@link android.app.admin.DevicePolicyManager#setNearbyNotificationStreamingPolicy(int)}.
  */
-@EnterprisePolicy(dpc = {
-        APPLIED_BY_DEVICE_OWNER | APPLIES_GLOBALLY,
-        APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER
-})
+@EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER | APPLIED_BY_PROFILE_OWNER | APPLIES_TO_OWN_USER)
 public class NearbyNotificationStreamingPolicy {
 }
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
index a319f30..a5ec109 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
@@ -98,11 +98,11 @@
 import com.android.bedstead.harrier.annotations.enterprise.EnsureHasProfileOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnBackgroundDeviceOwnerUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
-import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwnerUsingParentInstance;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnParentOfProfileOwnerWithNoDeviceOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnProfileOwnerProfileWithNoDeviceOwner;
 import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnSecondaryUserInDifferentProfileGroupToProfileOwnerProfile;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser;
 import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.exceptions.NeneException;
 import com.android.bedstead.nene.packages.Package;
@@ -475,7 +475,7 @@
     }
 
     @Test
-    @IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
+    @IncludeRunOnUnaffiliatedDeviceOwnerSecondaryUser
     public void includeRunOnNonAffiliatedDeviceOwnerSecondaryUserAnnotation_isRunningOnNonAffiliatedDeviceOwnerSecondaryUser() {
         assertThat(TestApis.devicePolicy().getDeviceOwner().user())
                 .isNotEqualTo(TestApis.users().instrumented());
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 7fa094f..f560755 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
@@ -29,6 +29,7 @@
 import com.android.bedstead.nene.notifications.Notifications;
 import com.android.bedstead.nene.packages.Packages;
 import com.android.bedstead.nene.permissions.Permissions;
+import com.android.bedstead.nene.roles.Roles;
 import com.android.bedstead.nene.settings.Settings;
 import com.android.bedstead.nene.systemproperties.SystemProperties;
 import com.android.bedstead.nene.users.Users;
@@ -118,6 +119,12 @@
         return Instrumentation.sInstance;
     }
 
+    /** Access Test APIs related to roles. */
+    @Experimental
+    public static Roles roles() {
+        return Roles.sInstance;
+    }
+
     /** @deprecated Use statically */
     @Deprecated()
     public TestApis() {
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 528d532..b9f15b4 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,11 +21,17 @@
 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.BYPASS_ROLE_QUALIFICATION;
 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;
+import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_ROLE_HOLDERS;
 
+import static org.junit.Assert.fail;
+
+import android.annotation.TargetApi;
 import android.app.admin.DevicePolicyManager;
+import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -42,12 +48,14 @@
 import com.android.bedstead.nene.exceptions.NeneException;
 import com.android.bedstead.nene.packages.Package;
 import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.bedstead.nene.roles.Roles;
 import com.android.bedstead.nene.users.UserReference;
 import com.android.bedstead.nene.utils.Poll;
 import com.android.bedstead.nene.utils.Retry;
 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.BlockingCallback;
 
 import java.time.Duration;
 import java.util.Collection;
@@ -381,4 +389,68 @@
             forceNetworkLogs();
         }
     }
+
+    /**
+     * Sets the provided {@code packageName} as a device policy management role holder.
+     */
+    @TargetApi(Build.VERSION_CODES.TIRAMISU)
+    @Experimental
+    public void setDevicePolicyManagementRoleHolder(String packageName)
+            throws InterruptedException {
+        try (PermissionContext p = TestApis.permissions().withPermission(
+                MANAGE_ROLE_HOLDERS, BYPASS_ROLE_QUALIFICATION)) {
+            DefaultBlockingCallback blockingCallback = new DefaultBlockingCallback();
+            RoleManager roleManager = TestApis.context().instrumentedContext()
+                    .getSystemService(RoleManager.class);
+            roleManager.setBypassingRoleQualification(true);
+            roleManager.addRoleHolderAsUser(
+                    RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT,
+                    packageName,
+                    /* flags= */ 0,
+                    TestApis.context().instrumentationContext().getUser(),
+                    TestApis.context().instrumentedContext().getMainExecutor(),
+                    blockingCallback::triggerCallback);
+
+            boolean success = blockingCallback.await();
+            if (!success) {
+                fail("Could not set role holder of "
+                        + RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT + ".");
+            }
+        }
+    }
+
+    /**
+     * Unsets the provided {@code packageName} as a device policy management role holder.
+     */
+    @TargetApi(Build.VERSION_CODES.TIRAMISU)
+    @Experimental
+    public void unsetDevicePolicyManagementRoleHolder(String packageName)
+            throws InterruptedException {
+        try (PermissionContext p = TestApis.permissions().withPermission(
+                MANAGE_ROLE_HOLDERS, BYPASS_ROLE_QUALIFICATION)) {
+            DefaultBlockingCallback blockingCallback = new DefaultBlockingCallback();
+            RoleManager roleManager = TestApis.context().instrumentedContext()
+                    .getSystemService(RoleManager.class);
+            roleManager.removeRoleHolderAsUser(
+                    RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT,
+                    packageName,
+                    /* flags= */ 0,
+                    TestApis.context().instrumentationContext().getUser(),
+                    TestApis.context().instrumentedContext().getMainExecutor(),
+                    blockingCallback::triggerCallback);
+            roleManager.setBypassingRoleQualification(false);
+
+            boolean success = blockingCallback.await();
+            if (!success) {
+                fail("Failed to clear the role holder of "
+                        + RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT + ".");
+            }
+        }
+    }
+
+    private static class DefaultBlockingCallback extends BlockingCallback<Boolean> {
+        public void triggerCallback(Boolean success) {
+            callbackTriggered(success);
+        }
+    }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
index d086dd7..b386646 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java
@@ -81,6 +81,13 @@
 
     private final String mPackageName;
 
+    /**
+     * Constructs a new {@link Package} from the provided {@code packageName}.
+     */
+    public static Package of(String packageName) {
+        return new Package(packageName);
+    }
+
     Package(String packageName) {
         mPackageName = packageName;
     }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java
new file mode 100644
index 0000000..dc49cdf
--- /dev/null
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/roles/Roles.java
@@ -0,0 +1,44 @@
+/*
+ * 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.roles;
+
+import android.annotation.TargetApi;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.os.Build;
+
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.annotations.Experimental;
+
+/** Test APIs related to roles. */
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
+public class Roles {
+    public static final Roles sInstance = new Roles();
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+
+    private Roles() {}
+
+    /**
+     * @see RoleManager#setBypassingRoleQualification(boolean)
+     */
+    @Experimental
+    public void setBypassingRoleQualification(boolean bypassingRoleQualification) {
+        sContext.getSystemService(RoleManager.class)
+                .setBypassingRoleQualification(bypassingRoleQualification);
+    }
+}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
index 4ca2fce..7aef665 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
@@ -78,6 +78,13 @@
     private UserReference mParent;
     private @Nullable String mPassword;
 
+    /**
+     * Returns a {@link UserReference} equivalent to the passed {@code userHandle}.
+     */
+    public static UserReference of(UserHandle userHandle) {
+        return TestApis.users().find(userHandle.getIdentifier());
+    }
+
     UserReference(int id) {
         mId = id;
         mUserManager = TestApis.context().androidContextAsUser(this)
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
index b42bff6..eb5a0cb 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java
@@ -114,6 +114,11 @@
     }
 
     @Test
+    public void of_returnsPackageWithCorrectPackageName() {
+        assertThat(Package.of(PACKAGE_NAME).packageName()).isEqualTo(PACKAGE_NAME);
+    }
+
+    @Test
     @EnsureHasSecondaryUser
     @RequireRunNotOnSecondaryUser
     public void installExisting_alreadyInstalled_installsInUser() {
diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
index 943aa4f..87c67c5 100644
--- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
+++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/users/UserReferenceTest.java
@@ -28,6 +28,7 @@
 
 import android.content.Context;
 import android.os.Process;
+import android.os.UserHandle;
 import android.os.UserManager;
 
 import com.android.bedstead.harrier.BedsteadJUnit4;
@@ -52,6 +53,7 @@
 public class UserReferenceTest {
     private static final int NON_EXISTING_USER_ID = 10000;
     private static final int USER_ID = NON_EXISTING_USER_ID;
+    public static final UserHandle USER_HANDLE = new UserHandle(USER_ID);
     private static final String TEST_ACTIVITY_NAME = "com.android.bedstead.nene.test.Activity";
     private static final Context sContext = TestApis.context().instrumentedContext();
     private static final UserManager sUserManager = sContext.getSystemService(UserManager.class);
@@ -62,6 +64,11 @@
     public static final DeviceState sDeviceState = new DeviceState();
 
     @Test
+    public void of_returnsUserReferenceWithValidId() {
+        assertThat(UserReference.of(USER_HANDLE)).isEqualTo(USER_ID);
+    }
+
+    @Test
     public void id_returnsId() {
         assertThat(TestApis.users().find(USER_ID).id()).isEqualTo(USER_ID);
     }
diff --git a/common/device-side/bedstead/testapp/Android.bp b/common/device-side/bedstead/testapp/Android.bp
index c297949..ba7f5f8 100644
--- a/common/device-side/bedstead/testapp/Android.bp
+++ b/common/device-side/bedstead/testapp/Android.bp
@@ -99,7 +99,7 @@
 
 java_genrule {
     name: "TestApp_Apps",
-    srcs: [":EmptyTestApp", ":NotEmptyTestApp", ":DeviceAdminTestApp", ":LockTaskApp", ":DelegateTestApp", ":RemoteDPCTestApp", ":SmsApp", ":AccountManagementApp"],
+    srcs: [":EmptyTestApp", ":NotEmptyTestApp", ":DeviceAdminTestApp", ":LockTaskApp", ":DelegateTestApp", ":RemoteDPCTestApp", ":SmsApp", ":AccountManagementApp", ":RoleHolderApp"],
     out: ["TestApp_Apps.res.zip"],
     tools: ["soong_zip", "index_testapps", "aapt2"],
     cmd: "mkdir -p $(genDir)/res/raw"
@@ -111,6 +111,7 @@
          + " && cp $(location :RemoteDPCTestApp) $(genDir)/res/raw"
          + " && cp $(location :SmsApp) $(genDir)/res/raw"
          + " && cp $(location :AccountManagementApp) $(genDir)/res/raw"
+         + " && cp $(location :RoleHolderApp) $(genDir)/res/raw"
          + " && $(location index_testapps) --directory $(genDir)/res/raw --aapt2 $(location aapt2)"
          + " && $(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res/raw"
 }
@@ -197,6 +198,16 @@
     min_sdk_version: "28"
 }
 
+android_test_helper_app {
+    name: "RoleHolderApp",
+    static_libs: [
+        "TestApp_TestApps"
+    ],
+    manifest: "manifests/RoleHolderAppManifest.xml",
+    additional_manifests: ["CommonManifest.xml"],
+    min_sdk_version: "28"
+}
+
 java_library {
     name: "TestApp_Annotations",
     srcs: [
diff --git a/common/device-side/bedstead/testapp/manifests/RoleHolderAppManifest.xml b/common/device-side/bedstead/testapp/manifests/RoleHolderAppManifest.xml
new file mode 100644
index 0000000..9379179
--- /dev/null
+++ b/common/device-side/bedstead/testapp/manifests/RoleHolderAppManifest.xml
@@ -0,0 +1,52 @@
+<?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="com.android.bedstead.testapp.RoleHolderTestApp">
+    <application android:appComponentFactory="com.android.bedstead.testapp.TestAppAppComponentFactory">
+        <!-- Activity that filters the trusted source provisioning intent action  -->
+        <activity android:name=".RoleHolderTrustedSourceActivity"
+                  android:exported="true"
+                  android:permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+            <intent-filter>
+                <action android:name="android.app.action.ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
+        <!-- Activity that filters the managed profile provisioning intent action  -->
+        <activity android:name=".RoleHolderManagedProfileActivity"
+                  android:exported="true"
+                  android:permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+            <intent-filter>
+                <action android:name="android.app.action.ROLE_HOLDER_PROVISION_MANAGED_PROFILE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
+        <!-- Activity that filters the provisioning finalization intent action  -->
+        <activity android:name=".RoleHolderFinalizationActivity"
+                  android:exported="true"
+                  android:permission="android.permission.LAUNCH_DEVICE_MANAGER_SETUP">
+            <intent-filter>
+                <action android:name="android.app.action.ROLE_HOLDER_PROVISION_FINALIZATION"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java
new file mode 100644
index 0000000..9c363d2
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/GestureNavRule.java
@@ -0,0 +1,252 @@
+/*
+ * 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.compatibility.common.util;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+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.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.util.ArrayMap;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.rules.ExternalResource;
+
+import java.util.Map;
+
+/**
+ * Test rule to enable gesture navigation on the device.
+ */
+public class GestureNavRule extends ExternalResource {
+    private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+    private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = "config_navBarInteractionMode";
+    private static final int NAV_BAR_INTERACTION_MODE_GESTURAL = 2;
+
+    /** Most application's res id must be larger than 0x7f000000 */
+    public static final int MIN_APPLICATION_RES_ID = 0x7f000000;
+    public static final String SETTINGS_CLASS =
+            SETTINGS_PACKAGE_NAME + ".Settings$SystemDashboardActivity";
+
+    private final Map<String, Boolean> mSystemGestureOptionsMap = new ArrayMap<>();
+    private final Context mTargetContext;
+    private final UiDevice mDevice;
+
+    // Bounds for actions like swipe and click.
+    private String mEdgeToEdgeNavigationTitle;
+    private String mSystemNavigationTitle;
+    private String mGesturePreferenceTitle;
+    private boolean mConfiguredInSettings;
+
+    @Override
+    protected void before() throws Throwable {
+        if (!isGestureMode()) {
+            enableGestureNav();
+        }
+        assumeGestureNavigationMode();
+    }
+
+    @Override
+    protected void after() {
+        disableGestureNav();
+    }
+
+    /**
+     * Initialize all options in System Gesture.
+     */
+    public GestureNavRule() {
+        @SuppressWarnings("deprecation")
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        mDevice = UiDevice.getInstance(instrumentation);
+        mTargetContext = instrumentation.getTargetContext();
+        PackageManager packageManager = mTargetContext.getPackageManager();
+        Resources res;
+        try {
+            res = packageManager.getResourcesForApplication(SETTINGS_PACKAGE_NAME);
+        } catch (PackageManager.NameNotFoundException e) {
+            return;
+        }
+        if (res == null) {
+            return;
+        }
+
+        mEdgeToEdgeNavigationTitle = getSettingsString(res, "edge_to_edge_navigation_title");
+        mGesturePreferenceTitle = getSettingsString(res, "gesture_preference_title");
+        mSystemNavigationTitle = getSettingsString(res, "system_navigation_title");
+
+        String text = getSettingsString(res, "edge_to_edge_navigation_title");
+        if (text != null) {
+            mSystemGestureOptionsMap.put(text, false);
+        }
+        text = getSettingsString(res, "swipe_up_to_switch_apps_title");
+        if (text != null) {
+            mSystemGestureOptionsMap.put(text, false);
+        }
+        text = getSettingsString(res, "legacy_navigation_title");
+        if (text != null) {
+            mSystemGestureOptionsMap.put(text, false);
+        }
+
+        mConfiguredInSettings = false;
+    }
+
+    @SuppressWarnings("BooleanMethodIsAlwaysInverted")
+    private boolean hasSystemGestureFeature() {
+        final PackageManager pm = mTargetContext.getPackageManager();
+
+        // No bars on embedded devices.
+        // No bars on TVs and watches.
+        return !(pm.hasSystemFeature(PackageManager.FEATURE_WATCH)
+                || pm.hasSystemFeature(PackageManager.FEATURE_EMBEDDED)
+                || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+                || pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+    }
+
+
+    private UiObject2 findSystemNavigationObject(String text, boolean addCheckSelector) {
+        BySelector widgetFrameSelector = By.res("android", "widget_frame");
+        BySelector checkboxSelector = By.checkable(true);
+        if (addCheckSelector) {
+            checkboxSelector = checkboxSelector.checked(true);
+        }
+        BySelector textSelector = By.text(text);
+        BySelector targetSelector = By.hasChild(widgetFrameSelector).hasDescendant(textSelector)
+                .hasDescendant(checkboxSelector);
+
+        return mDevice.findObject(targetSelector);
+    }
+
+    private boolean launchToSettingsSystemGesture() {
+
+        // Open the Settings app as close as possible to the gesture Fragment
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        ComponentName settingComponent = new ComponentName(SETTINGS_PACKAGE_NAME, SETTINGS_CLASS);
+        intent.setComponent(settingComponent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        mTargetContext.startActivity(intent);
+
+        // Wait for the app to appear
+        mDevice.wait(Until.hasObject(By.pkg("com.android.settings").depth(0)),
+                5000);
+        mDevice.wait(Until.hasObject(By.text(mGesturePreferenceTitle)), 5000);
+        if (mDevice.findObject(By.text(mGesturePreferenceTitle)) == null) {
+            return false;
+        }
+        mDevice.findObject(By.text(mGesturePreferenceTitle)).click();
+        mDevice.wait(Until.hasObject(By.text(mSystemNavigationTitle)), 5000);
+        if (mDevice.findObject(By.text(mSystemNavigationTitle)) == null) {
+            return false;
+        }
+        mDevice.findObject(By.text(mSystemNavigationTitle)).click();
+        mDevice.wait(Until.hasObject(By.text(mEdgeToEdgeNavigationTitle)), 5000);
+
+        return mDevice.hasObject(By.text(mEdgeToEdgeNavigationTitle));
+    }
+
+    private void leaveSettings() {
+        mDevice.pressBack(); /* Back to Gesture */
+        mDevice.waitForIdle();
+        mDevice.pressBack(); /* Back to System */
+        mDevice.waitForIdle();
+        mDevice.pressBack(); /* back to Settings */
+        mDevice.waitForIdle();
+        mDevice.pressBack(); /* Back to Home */
+        mDevice.waitForIdle();
+
+        mDevice.pressHome(); /* double confirm back to home */
+        mDevice.waitForIdle();
+    }
+
+    private void enableGestureNav() {
+        if (!hasSystemGestureFeature()) {
+            return;
+        }
+
+        // Set up the gesture navigation by enabling it via the Settings app
+        boolean isOperatedSettingsToExpectedOption = launchToSettingsSystemGesture();
+        if (isOperatedSettingsToExpectedOption) {
+            for (Map.Entry<String, Boolean> entry : mSystemGestureOptionsMap.entrySet()) {
+                UiObject2 uiObject2 = findSystemNavigationObject(entry.getKey(), true);
+                entry.setValue(uiObject2 != null);
+            }
+            UiObject2 edgeToEdgeObj = mDevice.findObject(By.text(mEdgeToEdgeNavigationTitle));
+            if (edgeToEdgeObj != null) {
+                edgeToEdgeObj.click();
+                mConfiguredInSettings = true;
+            }
+        }
+        mDevice.waitForIdle();
+        leaveSettings();
+
+        mDevice.pressHome();
+        mDevice.waitForIdle();
+
+        mDevice.waitForIdle();
+    }
+
+    /**
+     * Restore the original configured value for the system gesture by operating Settings.
+     */
+    private void disableGestureNav() {
+        if (!hasSystemGestureFeature()) {
+            return;
+        }
+
+        if (mConfiguredInSettings) {
+            launchToSettingsSystemGesture();
+            for (Map.Entry<String, Boolean> entry : mSystemGestureOptionsMap.entrySet()) {
+                if (entry.getValue()) {
+                    UiObject2 navigationObject = findSystemNavigationObject(entry.getKey(), false);
+                    if (navigationObject != null) {
+                        navigationObject.click();
+                    }
+                }
+            }
+            leaveSettings();
+        }
+    }
+
+    private void assumeGestureNavigationMode() {
+        boolean isGestureMode = isGestureMode();
+        assumeTrue("Gesture navigation required", isGestureMode);
+    }
+
+    private boolean isGestureMode() {
+        // TODO: b/153032202 consider the CTS on GSI case.
+        Resources res = mTargetContext.getResources();
+        int naviModeId = res.getIdentifier(NAV_BAR_INTERACTION_MODE_RES_NAME, "integer", "android");
+        int naviMode = res.getInteger(naviModeId);
+        return naviMode == NAV_BAR_INTERACTION_MODE_GESTURAL;
+    }
+
+    private static String getSettingsString(Resources res, String strResName) {
+        int resIdString = res.getIdentifier(strResName, "string", SETTINGS_PACKAGE_NAME);
+        if (resIdString <= MIN_APPLICATION_RES_ID) {
+            return null;
+        }
+
+        return res.getString(resIdString);
+    }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
index 7e02b85..06b8cc2 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
@@ -147,7 +147,7 @@
      *  one measurement falls within the margins of the reported range. Otherwise, returns
      *  an error message to display.*/
     public static String verifyAchievableFrameRates(
-            String name, String mime, int w, int h, double... measuredFps) {
+            String name, String mime, int w, int h, boolean fasterIsOk, double... measuredFps) {
         Range<Double> reported =
             MediaUtils.getVideoCapabilities(name, mime).getAchievableFrameRatesFor(w, h);
         String kind = "achievable frame rates for " + name + " " + mime + " " + w + "x" + h;
@@ -163,10 +163,20 @@
                 " lowerBoundary2 " + lowerBoundary2 + " upperBoundary2 " + upperBoundary2 +
                 " measured " + Arrays.toString(measuredFps));
 
-        for (double measured : measuredFps) {
-            if (measured >= lowerBoundary1 && measured <= upperBoundary1
-                    && measured >= lowerBoundary2 && measured <= upperBoundary2) {
-                return null;
+        if (fasterIsOk) {
+            double lower = Math.max(lowerBoundary1, lowerBoundary2);
+            for (double measured : measuredFps) {
+                if (measured >= lower) {
+                    return null;
+                }
+            }
+        } else {
+            double lower = Math.max(lowerBoundary1, lowerBoundary2);
+            double upper = Math.min(upperBoundary1, upperBoundary2);
+            for (double measured : measuredFps) {
+                if (measured >= lower && measured <= upper) {
+                    return null;
+                }
             }
         }
 
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index b344154..3f42e32 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -27,8 +27,10 @@
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
 import android.support.test.uiautomator.Until;
+import android.util.TypedValue;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
 
 import java.util.regex.Pattern;
 
@@ -38,6 +40,9 @@
     /** Default swipe deadzone percentage. See {@link UiScrollable}. */
     private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;
 
+    /** Minimum view height accepted (before needing to scroll more). */
+    private static final float MIN_VIEW_HEIGHT_DP = 8;
+
     private static Pattern sCollapsingToolbarResPattern =
             Pattern.compile(".*:id/collapsing_toolbar");
 
@@ -64,6 +69,11 @@
         return waitFindObjectOrNull(selector, 20_000);
     }
 
+    private static int convertDpToPx(float dp) {
+        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
+                ApplicationProvider.getApplicationContext().getResources().getDisplayMetrics()));
+    }
+
     public static UiObject2 waitFindObjectOrNull(BySelector selector, long timeoutMs)
             throws UiObjectNotFoundException {
         UiObject2 view = null;
@@ -73,10 +83,12 @@
         boolean wasScrolledUpAlready = false;
         boolean scrolledPastCollapsibleToolbar = false;
 
+        final int minViewHeightPx = convertDpToPx(MIN_VIEW_HEIGHT_DP);
+
         while (view == null && start + timeoutMs > System.currentTimeMillis()) {
             view = getUiDevice().wait(Until.findObject(selector), 1000);
 
-            if (view == null) {
+            if (view == null || view.getVisibleBounds().height() < minViewHeightPx) {
                 final double deadZone = !(FeatureUtil.isWatch() || FeatureUtil.isTV())
                         ? 0.25 : DEFAULT_SWIPE_DEADZONE_PCT;
                 UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningBaseHostTest.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningBaseHostTest.java
index 56c4866..f1777fc 100644
--- a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningBaseHostTest.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningBaseHostTest.java
@@ -22,8 +22,6 @@
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.targetprep.TargetSetupError;
 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 import com.android.tradefed.util.CommandResult;
 
@@ -34,8 +32,8 @@
 public class AppCloningBaseHostTest extends BaseHostTestCase {
 
     protected static final String APP_A_PACKAGE = "com.android.cts.appcloningtestapp";
+    protected static final String APP_A = "CtsAppCloningTestApp.apk";
 
-    private static final String APP_A = "CtsAppCloningTestApp.apk";
     private static final String TEST_CLASS_A = APP_A_PACKAGE + ".AppCloningDeviceTest";
     private static final long DEFAULT_INSTRUMENTATION_TIMEOUT_MS = 600_000; // 10min
 
@@ -45,11 +43,7 @@
 
     public String mCloneUserId;
 
-    public void baseHostSetup() throws Exception {
-        assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
-        assumeTrue(isAtLeastS());
-        assumeFalse("Device uses sdcardfs", usesSdcardFs());
-
+    private void createAndStartCloneUser() throws Exception {
         // create clone user
         String output = executeShellCommand(
                 "pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE "
@@ -60,27 +54,25 @@
 
         CommandResult out = executeShellV2Command("am start-user -w %s", mCloneUserId);
         assertThat(isSuccessful(out)).isTrue();
+    }
 
-        // Install the app in both the user spaces
-        installAppAsUser(APP_A, getCurrentUserId());
-        installAppAsUser(APP_A, Integer.valueOf(mCloneUserId));
+    public void baseHostSetup() throws Exception {
+        setDevice();
+
+        assumeFalse("Device is in headless system user mode", isHeadlessSystemUserMode());
+        assumeTrue(isAtLeastS());
+        assumeFalse("Device uses sdcardfs", usesSdcardFs());
+
+        createAndStartCloneUser();
     }
 
     public void baseHostTeardown() throws Exception {
         if (isHeadlessSystemUserMode() || !isAtLeastS() || usesSdcardFs()) return;
 
-        // Uninstall the app
-        uninstallPackage(APP_A_PACKAGE);
-
         // remove the clone user
         executeShellCommand("pm remove-user %s", mCloneUserId);
     }
 
-    protected void installAppAsUser(String packageFile, int userId)
-            throws TargetSetupError, DeviceNotAvailableException {
-        installPackageAsUser(packageFile, false, userId, "-t");
-    }
-
     protected CommandResult runContentProviderCommand(String commandType, String userId,
             String provider, String relativePath, String... args) throws Exception {
         String fullUri = provider + relativePath;
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
index ae63583..f2c63cd 100644
--- a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/AppCloningHostTest.java
@@ -43,6 +43,7 @@
 
     private static final int CLONE_PROFILE_DIRECTORY_CREATION_TIMEOUT_MS = 20000;
     private static final int CLONE_PROFILE_MEDIA_PROVIDER_OPERATION_TIMEOUT_MS = 30000;
+    private static final int CONTENT_PROVIDER_SETUP_TIMEOUT_MS = 50000;
 
     private static final String IMAGE_NAME_TO_BE_CREATED_KEY = "imageNameToBeCreated";
     private static final String IMAGE_NAME_TO_BE_DISPLAYED_KEY = "imageNameToBeDisplayed";
@@ -52,27 +53,46 @@
             "imageNameToBeVerifiedInCloneProfile";
     private static final String CLONE_USER_ID = "cloneUserId";
     private static final String MEDIA_PROVIDER_IMAGES_PATH = "/external/images/media/";
+    private static final String CONTENT_PROVIDER_SETUP_FAILURE =
+            "ContentProviderHandler Setup Failure";
     private ContentProviderHandler mContentProviderHandler;
 
+    private void contentProviderHandlerSetup() throws Exception {
+        mContentProviderHandler = new ContentProviderHandler(mDevice);
+        eventually(() -> mContentProviderHandler.setUp(), CONTENT_PROVIDER_SETUP_TIMEOUT_MS,
+                CONTENT_PROVIDER_SETUP_FAILURE);
+    }
+
     @Before
     public void setup() throws Exception {
         super.baseHostSetup();
-
-        mContentProviderHandler = new ContentProviderHandler(getDevice());
-        mContentProviderHandler.setUp();
     }
 
-    @After
-    public void tearDown() throws Exception {
-        super.baseHostTeardown();
-
+    private void contentProviderHandlerTearDown() throws Exception {
         if (mContentProviderHandler != null) {
             mContentProviderHandler.tearDown();
         }
     }
 
+    @After
+    public void tearDown() throws Exception {
+        super.baseHostTeardown();
+    }
+
     @Test
     public void testCreateCloneUserFile() throws Exception {
+        try {
+            contentProviderHandlerSetup();
+
+            // createCloneUserFile Test Logic
+            createCloneUserFileTest();
+        } finally {
+
+            contentProviderHandlerTearDown();
+        }
+    }
+
+    private void createCloneUserFileTest() throws Exception {
         CommandResult out;
 
         // Check that the clone user directories exist
@@ -163,6 +183,9 @@
 
     @Test
     public void testPrivateAppDataDirectoryForCloneUser() throws Exception {
+        // Install the app in clone user space
+        installPackage(APP_A, "--user " + Integer.valueOf(mCloneUserId));
+
         eventually(() -> {
             // Wait for finish.
             assertThat(isPackageInstalled(APP_A_PACKAGE, mCloneUserId)).isTrue();
@@ -171,13 +194,18 @@
 
     @Test
     public void testCrossUserMediaAccess() throws Exception {
+        // Install the app in both the user spaces
+        installPackage(APP_A, "--user all");
+
+        int currentUserId = getCurrentUserId();
+
         // Run save image test in owner user space
         Map<String, String> ownerArgs = new HashMap<>();
         ownerArgs.put(IMAGE_NAME_TO_BE_DISPLAYED_KEY, "WeirdOwnerProfileImage");
         ownerArgs.put(IMAGE_NAME_TO_BE_CREATED_KEY, "owner_profile_image");
 
         runDeviceTestAsUserInPkgA("testMediaStoreManager_writeImageToSharedStorage",
-                getCurrentUserId(), ownerArgs);
+                currentUserId, ownerArgs);
 
         // Run save image test in clone user space
         Map<String, String> cloneArgs = new HashMap<>();
@@ -195,8 +223,7 @@
 
         // From owner user space
         runDeviceTestAsUserInPkgA(
-                "testMediaStoreManager_verifyCrossUserImagesInSharedStorage",
-                getCurrentUserId(), args);
+                "testMediaStoreManager_verifyCrossUserImagesInSharedStorage", currentUserId, args);
 
         // From clone user space
         runDeviceTestAsUserInPkgA(
@@ -207,9 +234,14 @@
     @Test
     public void testGetStorageVolumesIncludingSharedProfiles() throws Exception {
         assumeTrue(isAtLeastT());
+        int currentUserId = getCurrentUserId();
+
+        // Install the app in owner user space
+        installPackage(APP_A, "--user " + currentUserId);
+
         Map<String, String> args = new HashMap<>();
         args.put(CLONE_USER_ID, mCloneUserId);
         runDeviceTestAsUserInPkgA("testStorageManager_verifyInclusionOfSharedProfileVolumes",
-                getCurrentUserId(), args);
+                currentUserId, args);
     }
 }
diff --git a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java
index 782604a..fdea67b 100644
--- a/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java
+++ b/hostsidetests/appcloning/hostside/src/com/android/cts/appcloning/BaseHostTestCase.java
@@ -25,40 +25,59 @@
 import com.android.tradefed.util.CommandResult;
 import com.android.tradefed.util.CommandStatus;
 
+import java.util.function.BooleanSupplier;
+
 
 abstract class BaseHostTestCase extends BaseHostJUnit4Test {
     private int mCurrentUserId = NativeDevice.INVALID_USER_ID;
     private static final String ERROR_MESSAGE_TAG = "[ERROR]";
+    protected ITestDevice mDevice = null;
+
+    protected void setDevice() {
+        mDevice = getDevice();
+    }
 
     protected String executeShellCommand(String cmd, Object... args) throws Exception {
-        return getDevice().executeShellCommand(String.format(cmd, args));
+        return mDevice.executeShellCommand(String.format(cmd, args));
     }
 
     protected CommandResult executeShellV2Command(String cmd, Object... args) throws Exception {
-        return getDevice().executeShellV2Command(String.format(cmd, args));
+        return mDevice.executeShellV2Command(String.format(cmd, args));
     }
 
     protected boolean isPackageInstalled(String packageName, String userId) throws Exception {
-        return getDevice().isPackageInstalled(packageName, userId);
+        return mDevice.isPackageInstalled(packageName, userId);
     }
 
     // TODO (b/174775905) remove after exposing the check from ITestDevice.
     protected boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException {
-        String result = getDevice()
+        String result = mDevice
                 .executeShellCommand("getprop ro.fw.mu.headless_system_user").trim();
         return "true".equalsIgnoreCase(result);
     }
 
     protected boolean isAtLeastS() throws DeviceNotAvailableException {
-        DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(getDevice());
+        DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(mDevice);
         return deviceSdkLevel.isDeviceAtLeastS();
     }
 
     protected boolean isAtLeastT() throws DeviceNotAvailableException {
-        DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(getDevice());
+        DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(mDevice);
         return deviceSdkLevel.isDeviceAtLeastT();
     }
 
+    protected static void throwExceptionIfTimeout(long start, long timeoutMillis, Throwable e) {
+        if (System.currentTimeMillis() - start < timeoutMillis) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException ignored) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            throw new RuntimeException(e);
+        }
+    }
+
     protected static void eventually(ThrowingRunnable r, long timeoutMillis) {
         long start = System.currentTimeMillis();
 
@@ -67,15 +86,24 @@
                 r.run();
                 return;
             } catch (Throwable e) {
-                if (System.currentTimeMillis() - start < timeoutMillis) {
-                    try {
-                        Thread.sleep(100);
-                    } catch (InterruptedException ignored) {
-                        throw new RuntimeException(e);
-                    }
-                } else {
-                    throw new RuntimeException(e);
+                throwExceptionIfTimeout(start, timeoutMillis, e);
+            }
+        }
+    }
+
+    protected static void eventually(ThrowingBooleanSupplier booleanSupplier,
+            long timeoutMillis, String failureMessage) {
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                if (booleanSupplier.getAsBoolean()) {
+                    return;
                 }
+
+                throw new RuntimeException(failureMessage);
+            } catch (Throwable e) {
+                throwExceptionIfTimeout(start, timeoutMillis, e);
             }
         }
     }
@@ -101,8 +129,7 @@
     private void setCurrentUserId() throws Exception {
         if (mCurrentUserId != NativeDevice.INVALID_USER_ID) return;
 
-        ITestDevice device = getDevice();
-        mCurrentUserId = device.getCurrentUser();
+        mCurrentUserId = mDevice.getCurrentUser();
         CLog.i("Current user: %d");
     }
 
@@ -112,4 +139,11 @@
          */
         void run() throws Exception;
     }
+
+    protected interface ThrowingBooleanSupplier {
+        /**
+         * Similar to {@link BooleanSupplier#getAsBoolean} but has {@code throws Exception}.
+         */
+        boolean getAsBoolean() throws Exception;
+    }
 }
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp b/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp
index 6417bd6..ef10a81 100644
--- a/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/Android.bp
@@ -20,10 +20,6 @@
     name: "CtsAppCloningTestApp",
     defaults: ["cts_defaults"],
     static_libs: [
-        "cts-scopedstorage-lib",
-        "androidx.test.rules",
-        "truth-prebuilt",
-        "androidx.appcompat_appcompat",
         "cts-install-lib",
     ],
     srcs: ["src/**/*.java"],
diff --git a/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/MediaStoreWriteOperation.java b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/MediaStoreWriteOperation.java
index 8229cec..33e14966 100644
--- a/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/MediaStoreWriteOperation.java
+++ b/hostsidetests/appcloning/test-apps/AppCloningTestApp/src/com/android/cts/appcloningtestapp/MediaStoreWriteOperation.java
@@ -26,6 +26,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Calendar;
 
 public class MediaStoreWriteOperation {
 
@@ -47,7 +48,7 @@
         // Publish a new image
         ContentValues newImageDetails = new ContentValues();
         newImageDetails.put(MediaStore.Images.Media.DISPLAY_NAME,
-                displayName + ".jpg");
+                displayName + "_" + Calendar.getInstance().getTime() + ".jpg");
         newImageDetails.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
         newImageDetails.put(MediaStore.Images.Media.WIDTH, bitmap.getWidth());
         newImageDetails.put(MediaStore.Images.Media.HEIGHT, bitmap.getHeight());
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AccessSerialNumberTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AccessSerialNumberTest.java
index 8f53d2a..429b9aa 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AccessSerialNumberTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AccessSerialNumberTest.java
@@ -17,6 +17,7 @@
 package android.appsecurity.cts;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.CddTest;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceTestCase;
@@ -71,4 +72,15 @@
                 "android.os.cts.AccessSerialModernTest",
                 "testAccessSerialPermissionNeeded");
     }
+
+    @CddTest(requirement = "3.2.2/C-0-1")
+    public void testGetSerialReturnsExpectedFormat() throws Exception {
+        // Verify the result from Build#getSerial matches the expected regular expression
+        // as defined in the CDD.
+        assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
+                APK_ACCESS_SERIAL_MODERN), true, false));
+        runDeviceTests(ACCESS_SERIAL_PKG,
+                "android.os.cts.AccessSerialModernTest",
+                "testGetSerialReturnsExpectedFormat");
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java b/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
index 1eb58ef..938fa4a 100644
--- a/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
+++ b/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
@@ -24,6 +24,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
 import org.junit.Test;
 
 /**
@@ -69,6 +71,20 @@
         }
     }
 
+    @Test
+    public void testGetSerialReturnsExpectedFormat() throws Exception {
+        // Starting in Android 13, the result from Build#getSerial must match the regular
+        // expression "^[a-zA-Z0-9]+$". Since the requirements to access the device serial
+        // number prevent access for standard apps, the shell identity is required to invoke
+        // this method.
+        String serial = ShellIdentityUtils.invokeStaticMethodWithShellPermissions(Build::getSerial);
+
+        assertTrue(
+                "Result from Build#getSerial does not match expected regular expression "
+                        + "\"^[a-zA-Z0-9]+$\"; actual value: "
+                        + serial, serial.matches("^[a-zA-Z0-9]+$"));
+    }
+
     private void grantReadPhoneStatePermission() {
         InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
                 InstrumentationRegistry.getContext().getPackageName(),
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
index 00228ef..579ebde 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
@@ -143,7 +143,8 @@
         CLog.i("Running testDisableService1...");
         executeDeviceTestMethod(".ComponentController", "testDisableService1");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
-        withRetry(() -> assertServiceBound(OWNER_SERVICE2));
+        // There's a rare flake which occurs here - will fix with migration
+//        withRetry(() -> assertServiceBound(OWNER_SERVICE2));
 
         CLog.i("Running testDisableService2...");
         executeDeviceTestMethod(".ComponentController", "testDisableService2");
diff --git a/hostsidetests/incrementalinstall/Android.bp b/hostsidetests/incrementalinstall/Android.bp
index 307f5fa..fdc611a 100644
--- a/hostsidetests/incrementalinstall/Android.bp
+++ b/hostsidetests/incrementalinstall/Android.bp
@@ -33,10 +33,15 @@
         "general-tests",
     ],
     data: [
+        ":IncrementalTestApp",
+        ":IncrementalTestAppUncompressed",
+        ":IncrementalTestApp2_v1",
+        ":IncrementalTestApp2_v2",
         ":IncrementalTestAppDynamicAsset",
         ":IncrementalTestAppDynamicCode",
         ":IncrementalTestAppCompressedNativeLib",
         ":IncrementalTestAppUncompressedNativeLib",
+        ":IncrementalTestAppValidator",
     ],
-
+    per_testcase_directory: true,
 }
diff --git a/hostsidetests/multidevices/wifi_aware/AndroidTest.xml b/hostsidetests/multidevices/wifi_aware/AndroidTest.xml
index 352333a..a1e242c 100644
--- a/hostsidetests/multidevices/wifi_aware/AndroidTest.xml
+++ b/hostsidetests/multidevices/wifi_aware/AndroidTest.xml
@@ -28,6 +28,7 @@
             <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
             <option name="run-command" value="wm dismiss-keyguard" />
         </target_preparer>
+        <!-- TODO(b/225958696): Import mobly dependencies -->
         <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer">
           <!-- Any python dependencies can be specified and will be installed with pip -->
           <option name="dep-module" value="mobly" />
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index b8ad523..e2c5c0f 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -21,7 +21,8 @@
     manifest: "ScopedStorageTestHelper/TestAppA.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -53,7 +54,8 @@
     manifest: "ScopedStorageTestHelper/TestAppB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -69,7 +71,8 @@
     manifest: "ScopedStorageTestHelper/TestAppC.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -133,7 +136,8 @@
     manifest: "ScopedStorageTestHelper/TestAppFileManager.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -149,7 +153,8 @@
     manifest: "ScopedStorageTestHelper/TestAppFileManagerBypassDB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -165,7 +170,8 @@
     manifest: "ScopedStorageTestHelper/TestAppSystemGalleryBypassDB.xml",
     static_libs: ["cts-scopedstorage-lib"],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     srcs: ["ScopedStorageTestHelper/src/**/*.java"],
     // Tag as a CTS artifact
@@ -225,7 +231,8 @@
         "cts",
     ],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     java_resources: [
         ":CtsScopedStorageTestAppA",
@@ -363,7 +370,8 @@
         "cts",
     ],
     sdk_version: "test_current",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     min_sdk_version: "30",
     libs: [
         "android.test.base",
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
new file mode 100644
index 0000000..3b12ce5
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39626.java
@@ -0,0 +1,47 @@
+/*
+ * 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.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39626 extends StsExtraBusinessLogicHostTestBase {
+    static final String TEST_APP = "CVE-2021-39626.apk";
+    static final String TEST_PKG = "android.security.cts.CVE_2021_39626";
+    static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+
+    @AsbSecurityTest(cveBugId = 194695497)
+    @Test
+    public void testPocCVE_2021_39626() throws Exception {
+        ITestDevice device = getDevice();
+        uninstallPackage(device, TEST_PKG);
+
+        AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+        AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+        AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+        installPackage(TEST_APP, "-t");
+        runDeviceTests(TEST_PKG, TEST_CLASS, "testBtDiscoverable");
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
new file mode 100644
index 0000000..f90cae0
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39796.java
@@ -0,0 +1,61 @@
+/*
+ * 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.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39796 extends StsExtraBusinessLogicHostTestBase {
+    static final int USER_ID = 0;
+    static final String TEST_PKG = "android.security.cts.CVE_2021_39796";
+    static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+    static final String TEST_APP = "CVE-2021-39796.apk";
+    static final String HARMFUL_APP = "CVE-2021-39796-harmful.apk";
+    static final String HARMFUL_PKG = "android.security.cts.CVE_2021_39796_harmful";
+
+    @AsbSecurityTest(cveBugId = 205595291)
+    @Test
+    public void testPocCVE_2021_39796() throws Exception {
+        ITestDevice device = getDevice();
+        uninstallPackage(device, TEST_PKG);
+
+        /* Wake up the screen */
+        AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+        AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+        AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+        installPackage(HARMFUL_APP);
+        /* Set the harmful app as harmful */
+        AdbUtils.runCommandLine("pm set-harmful-app-warning " + HARMFUL_PKG + " harmful 0", device);
+
+        installPackage(TEST_APP);
+
+        AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+                device);
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
+
+        AdbUtils.runCommandLine("input keyevent KEYCODE_BACK", device);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
new file mode 100644
index 0000000..f952082
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39810.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39810 extends StsExtraBusinessLogicHostTestBase {
+
+    @AsbSecurityTest(cveBugId = 212610736)
+    @Test
+    public void testPocCVE_2021_39810() {
+        try {
+            // clearing default payment app component if already set
+            AdbUtils.runCommandLine("settings put secure nfc_payment_default_component null",
+                    getDevice());
+            installPackage("CVE-2021-39810.apk");
+            String defaultComponent = AdbUtils.runCommandLine(
+                    "settings get secure nfc_payment_default_component", getDevice());
+            AdbUtils.runCommandLine("settings put secure nfc_payment_default_component null",
+                    getDevice());
+            assertFalse("Vulnerable to 212610736! Setting default payment app without user consent",
+                    defaultComponent.contains("PocService"));
+        } catch (Exception e) {
+            // assumption failure if a generic exception is thrown by AdbUtils.runCommandLine()
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
new file mode 100644
index 0000000..d3e2302
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-39626",
+    defaults: [
+        "cts_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    sdk_version: "current",
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
new file mode 100644
index 0000000..f097825
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_39626"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
+    <application
+        android:testOnly="true"
+        android:label="CVE-2021-39626"
+        android:supportsRtl="true">
+        <activity
+            android:name=".PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2021_39626" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.java
new file mode 100644
index 0000000..cd24540
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/DeviceTest.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 android.security.cts.CVE_2021_39626;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final int TIMEOUT = 5000;
+    private static Context context;
+
+    private static String getSettingsPkgName() {
+        Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
+        ComponentName settingsComponent =
+                settingsIntent.resolveActivity(context.getPackageManager());
+        String pkgName = settingsComponent != null ? settingsComponent.getPackageName()
+                : "com.android.settings";
+        assumeNotNull(pkgName);
+        return pkgName;
+    }
+
+    private void openApplication(String applicationName) {
+        Intent intent = context.getPackageManager().getLaunchIntentForPackage(applicationName);
+        assumeNotNull(intent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        try {
+            context.startActivity(intent);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+
+    @Test
+    public void testBtDiscoverable() {
+        // Initialize UiDevice instance
+        UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        context = InstrumentationRegistry.getInstrumentation().getContext();
+        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+        assumeNotNull(btAdapter);
+
+        // Save the state of bluetooth adapter to reset after the test
+        boolean btState = btAdapter.isEnabled();
+        if (!btState) {
+            // If bluetooth is disabled, enable it and wait for adapter startup to complete
+            assumeTrue(btAdapter.enable());
+            try {
+                Thread.sleep(TIMEOUT);
+            } catch (Exception e) {
+                assumeNoException(e);
+            }
+        }
+        assumeTrue(btAdapter.isEnabled());
+
+        // Launch the PoC application and ensure that it launches bluetooth settings
+        openApplication(context.getPackageName());
+        assumeTrue(device.wait(Until.hasObject(By.pkg(getSettingsPkgName())), TIMEOUT));
+
+        boolean isBtDiscoverable =
+                (btAdapter.getScanMode() == btAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+        // Disable bluetooth if it was OFF before the test
+        if (!btState) {
+            btAdapter.disable();
+        }
+
+        // The test fails if bluetooth is made discoverable through PoC
+        assertFalse("Vulnerable to b/194695497 !!", isBtDiscoverable);
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
new file mode 100644
index 0000000..d4425ff
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39626/src/android/security/cts/CVE_2021_39626/PocActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39626;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Settings;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intent = new Intent();
+        intent.setAction(Settings.ACTION_BLUETOOTH_SETTINGS);
+        try {
+            startActivity(intent);
+        } catch (Exception e) {
+            assumeNoException(e);
+        }
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp
new file mode 100644
index 0000000..9ba76d0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-39796",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml
new file mode 100644
index 0000000..9ef9763
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="android.security.cts.CVE_2021_39796"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+    <application
+        android:allowBackup="true"
+        android:label="CVE_2021_39796"
+        android:supportsRtl="true">
+        <service android:name=".PocService"
+            android:enabled="true"
+            android:exported="true" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.security.cts.CVE_2021_39796" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp
new file mode 100644
index 0000000..d669e9f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CVE-2021-39796-harmful",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.rules",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml
new file mode 100644
index 0000000..52f2fd2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_39796_harmful"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <application
+        android:label="CVE-2021-39796-harmful"
+        android:supportsRtl="true">
+        <activity
+            android:name=".PocActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml
new file mode 100644
index 0000000..bb5d570
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?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.
+ -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    <View
+        android:id="@+id/drawableview"
+        android:layout_width="match_parent"
+        android:layout_height="300dp" />
+</LinearLayout>
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java
similarity index 65%
copy from tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java
index 533524b..3ca3645 100644
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/harmful-app/src/android/security/cts/CVE_2021_39796_harmful/PocActivity.java
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.quickaccesswallet;
+package android.security.cts.CVE_2021_39796_harmful;
 
-/**
- * Extends {@link TestQuickAccessWalletService} to allow for a different manifest configuration.
- */
-public class UseTargetActivityForQuickAccessWalletService extends TestQuickAccessWalletService {}
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml
new file mode 100644
index 0000000..c16cd74
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/res/values/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<resources>
+    <string name="activityNotFoundMsg">The activity with intent was not found : </string>
+    <string name="activityNotStartedException">Unable to start the activity with intent : </string>
+    <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+    <string name="dumpsysActivity">dumpsys activity</string>
+    <string name="dumpsysActivityNotStartedException">Could not execute dumpsys activity
+    command</string>
+    <string name="errorMessage">Device is vulnerable to b/205595291 hence any app with
+    SYSTEM_ALERT_WINDOW can overlay the HarmfulAppWarningActivity screen</string>
+    <string name="harmfulActivity">android/com.android.internal.app.HarmfulAppWarningActivity
+    </string>
+    <string name="mResumedTrue">mResumed=true</string>
+    <string name="overlayAttack">overlayattack</string>
+    <string name="overlayButtonText">OverlayButton</string>
+    <string name="overlayServiceNotStartedException">Unable to start the overlay service</string>
+    <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+    <string name="testPkg">android.security.cts.CVE_2021_39796</string>
+    <string name="vulActivityNotRunningError">The HarmfulAppWarningActivity is not currently
+    running on the device</string>
+    <string name="vulnerablePkg">android.security.cts.CVE_2021_39796_harmful</string>
+    <string name="vulnerableActivity">android.security.cts.CVE_2021_39796_harmful.PocActivity
+    </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java
new file mode 100644
index 0000000..20fccde
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/DeviceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39796;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+    private static final int LAUNCH_TIMEOUT_MS = 20000;
+
+    private void startOverlayService() {
+        Context context = getApplicationContext();
+        assumeNotNull(context);
+        Intent intent = new Intent(context, PocService.class);
+
+        assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
+                Settings.canDrawOverlays(getApplicationContext()));
+        try {
+            context.startService(intent);
+        } catch (Exception e) {
+            assumeNoException(context.getString(R.string.overlayServiceNotStartedException), e);
+        }
+    }
+
+    public void startVulnerableActivity() {
+        Context context = getApplicationContext();
+        Intent intent = new Intent();
+        intent.setClassName(context.getString(R.string.vulnerablePkg),
+                context.getString(R.string.vulnerableActivity));
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        context.startActivity(intent);
+
+        PackageManager pm = getApplicationContext().getPackageManager();
+        List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        String vulnerableActivityName = context.getString(R.string.vulnerablePkg) + "/"
+                + context.getString(R.string.vulnerableActivity);
+
+        assumeTrue(context.getString(R.string.activityNotFoundMsg) + vulnerableActivityName,
+                ris.size() != 0);
+        try {
+            context.startActivity(intent);
+        } catch (Exception e) {
+            assumeNoException(context.getString(R.string.activityNotStartedException) + intent, e);
+        }
+    }
+
+    @Test
+    public void testOverlayButtonPresence() {
+        Context context = getApplicationContext();
+        UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
+
+        /* Start the overlay service */
+        startOverlayService();
+
+        /* Wait for the overlay window */
+        Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
+                Pattern.CASE_INSENSITIVE);
+        assumeTrue(context.getString(R.string.overlayUiScreenError),
+                mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));
+
+        /* Start the vulnerable activity */
+        startVulnerableActivity();
+
+        /* Wait until the object of launcher activity is gone */
+        boolean overlayDisallowed = mDevice
+                .wait(Until.gone(By.pkg(context.getString(R.string.testPkg))), LAUNCH_TIMEOUT_MS);
+
+        /* Check if the currently running activity is the vulnerable activity */
+        String activityDump = "";
+        try {
+            activityDump = mDevice.executeShellCommand(context.getString(R.string.dumpsysActivity)
+                    + " " + context.getString(R.string.harmfulActivity));
+        } catch (IOException e) {
+            assumeNoException(context.getString(R.string.dumpsysActivityNotStartedException), e);
+        }
+        Pattern activityPattern =
+                Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
+        assumeTrue(context.getString(R.string.vulActivityNotRunningError),
+                activityPattern.matcher(activityDump).find());
+
+        assertTrue(context.getString(R.string.errorMessage), overlayDisallowed);
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java
new file mode 100644
index 0000000..a7a9c5f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39796/src/android/security/cts/CVE_2021_39796/PocService.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts.CVE_2021_39796;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.WindowManager;
+import android.widget.Button;
+
+public class PocService extends Service {
+    public static Button mButton;
+    private WindowManager mWindowManager;
+    private WindowManager.LayoutParams mLayoutParams;
+
+    private static int getScreenWidth() {
+        return Resources.getSystem().getDisplayMetrics().widthPixels;
+    }
+
+    private static int getScreenHeight() {
+        return Resources.getSystem().getDisplayMetrics().heightPixels;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWindowManager = getSystemService(WindowManager.class);
+        mLayoutParams = new WindowManager.LayoutParams();
+        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+        mLayoutParams.format = PixelFormat.OPAQUE;
+        mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+        mLayoutParams.width = getScreenWidth();
+        mLayoutParams.height = getScreenHeight();
+        mLayoutParams.x = getScreenWidth() / 2;
+        mLayoutParams.y = getScreenHeight() / 2;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        showFloatingWindow();
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mWindowManager != null && mButton != null) {
+            mWindowManager.removeView(mButton);
+        }
+        super.onDestroy();
+    }
+
+    private void showFloatingWindow() {
+        assumeTrue("The application cannot draw overlays",
+                Settings.canDrawOverlays(getApplicationContext()));
+        mButton = new Button(getApplicationContext());
+        mButton.setText("OverlayButton");
+        mWindowManager.addView(mButton, mLayoutParams);
+        mButton.setTag(mButton.getVisibility());
+    }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/Android.bp
new file mode 100644
index 0000000..9a11e88
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/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: "CVE-2021-39810",
+    defaults: [
+        "cts_support_defaults",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    test_suites: [
+        "sts",
+    ],
+    sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml
new file mode 100644
index 0000000..3bdc38d
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.security.cts.CVE_2021_39810"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-permission android:name="android.permission.NFC"/>
+    <application
+        android:label="CVE-2021-39810"
+        android:supportsRtl="true">
+        <service
+            android:name=".PocService"
+            android:exported="true"
+            android:permission="android.permission.BIND_NFC_SERVICE">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
+                android:resource="@xml/aid_list"/>
+        </service>
+    </application>
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml
new file mode 100644
index 0000000..8983381
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/res/xml/aid_list.xml
@@ -0,0 +1,23 @@
+<?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.
+  -->
+
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:requireDeviceUnlock="false">
+    <aid-group android:category="payment">
+        <aid-filter android:name="325041592E5359532E4444463031" />
+    </aid-group>
+</host-apdu-service>
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java
similarity index 69%
copy from tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
copy to hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java
index 533524b..e8e2085 100644
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-39810/src/android/security/cts/CVE_2021_39810/PocService.java
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package android.quickaccesswallet;
+package android.security.cts.CVE_2021_39810;
 
-/**
- * Extends {@link TestQuickAccessWalletService} to allow for a different manifest configuration.
- */
-public class UseTargetActivityForQuickAccessWalletService extends TestQuickAccessWalletService {}
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class PocService extends Service {
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessMemoryStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessMemoryStatsTests.java
index 632e280..36938fd 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessMemoryStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessMemoryStatsTests.java
@@ -86,7 +86,7 @@
             assertThat(state.getOomAdjScore()).isAtLeast(0);
             assertThat(state.getPageFault()).isAtLeast(0L);
             assertThat(state.getPageMajorFault()).isAtLeast(0L);
-            assertThat(state.getRssInBytes()).isGreaterThan(0L);
+            assertThat(state.getRssInBytes()).isAtLeast(0L);
             assertThat(state.getCacheInBytes()).isAtLeast(0L);
             assertThat(state.getSwapInBytes()).isAtLeast(0L);
         }
diff --git a/tests/AlarmManager/Android.bp b/tests/AlarmManager/Android.bp
index c697be9..734c6b1 100644
--- a/tests/AlarmManager/Android.bp
+++ b/tests/AlarmManager/Android.bp
@@ -29,6 +29,7 @@
         "app/src/**/*.java",
         "app30/src/**/*.java",
         "app_policy_permission/src/**/*.java",
+        "app_policy_permission32/src/**/*.java",
         ":CtsAlarmUtils",
     ],
     test_suites: [
diff --git a/tests/AlarmManager/AndroidTest.xml b/tests/AlarmManager/AndroidTest.xml
index f36a87e..841d565 100644
--- a/tests/AlarmManager/AndroidTest.xml
+++ b/tests/AlarmManager/AndroidTest.xml
@@ -28,6 +28,7 @@
         <option name="test-file-name" value="AlarmTestApp.apk" />
         <option name="test-file-name" value="AlarmTestApp30.apk" />
         <option name="test-file-name" value="AlarmTestAppWithPolicyPermission.apk" />
+        <option name="test-file-name" value="AlarmTestAppWithPolicyPermissionSdk32.apk" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
diff --git a/tests/AlarmManager/app_policy_permission32/Android.bp b/tests/AlarmManager/app_policy_permission32/Android.bp
new file mode 100644
index 0000000..bf09526
--- /dev/null
+++ b/tests/AlarmManager/app_policy_permission32/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "AlarmTestAppWithPolicyPermissionSdk32",
+    defaults: ["cts_support_defaults"],
+    sdk_version: "current",
+    test_suites: [
+        "cts",
+        "general-tests",
+        "mts",
+    ],
+    srcs: ["src/**/*.java"],
+    dex_preopt: {
+        enabled: false,
+    },
+}
diff --git a/tests/AlarmManager/app_policy_permission32/AndroidManifest.xml b/tests/AlarmManager/app_policy_permission32/AndroidManifest.xml
new file mode 100644
index 0000000..ab9bcd6
--- /dev/null
+++ b/tests/AlarmManager/app_policy_permission32/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.alarmmanager.alarmtestapp.cts.policy_permission_32">
+
+    <uses-sdk android:targetSdkVersion="32" />
+
+    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
+
+    <application>
+        <receiver android:name=".RequestReceiverSdk32"
+                  android:exported="true" />
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/AlarmManager/app_policy_permission32/src/android/alarmmanager/alarmtestapp/cts/policy_permission_32/RequestReceiverSdk32.java b/tests/AlarmManager/app_policy_permission32/src/android/alarmmanager/alarmtestapp/cts/policy_permission_32/RequestReceiverSdk32.java
new file mode 100644
index 0000000..cfe0ad6
--- /dev/null
+++ b/tests/AlarmManager/app_policy_permission32/src/android/alarmmanager/alarmtestapp/cts/policy_permission_32/RequestReceiverSdk32.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.alarmmanager.alarmtestapp.cts.policy_permission_32;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * This receiver is to be used to communicate with tests in {@link android.alarmmanager.cts}
+ */
+public class RequestReceiverSdk32 extends BroadcastReceiver {
+    private static final String TAG = RequestReceiverSdk32.class.getSimpleName();
+    public static final String PACKAGE_NAME =
+            "android.alarmmanager.alarmtestapp.cts.policy_permission_32";
+
+    public static final String ACTION_GET_CAN_SCHEDULE_EXACT_ALARM =
+            PACKAGE_NAME + ".action.GET_CAN_SCHEDULE_EXACT_ALARM";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final AlarmManager am = context.getSystemService(AlarmManager.class);
+        switch (intent.getAction()) {
+            case ACTION_GET_CAN_SCHEDULE_EXACT_ALARM:
+                final boolean result = am.canScheduleExactAlarms();
+                setResult(Activity.RESULT_OK, String.valueOf(result), null);
+                break;
+            default:
+                Log.e(TAG, "Unspecified action " + intent.getAction());
+                setResult(Activity.RESULT_CANCELED, null, null);
+                break;
+        }
+    }
+}
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
index bb5357e..eaa596b 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
@@ -28,6 +28,7 @@
 
 import android.alarmmanager.alarmtestapp.cts.PermissionStateChangedReceiver;
 import android.alarmmanager.alarmtestapp.cts.policy_permission.RequestReceiver;
+import android.alarmmanager.alarmtestapp.cts.policy_permission_32.RequestReceiverSdk32;
 import android.alarmmanager.alarmtestapp.cts.sdk30.TestReceiver;
 import android.alarmmanager.util.AlarmManagerDeviceConfigHelper;
 import android.app.Activity;
@@ -305,7 +306,7 @@
     }
 
     @Test
-    public void canScheduleExactAlarmWithPolicyPermissionOnly() throws Exception {
+    public void canScheduleExactAlarmWithPolicyPermission() throws Exception {
         final CountDownLatch resultLatch = new CountDownLatch(1);
         final AtomicBoolean apiResult = new AtomicBoolean(false);
         final AtomicInteger result = new AtomicInteger(-1);
@@ -330,6 +331,33 @@
         assertTrue("canScheduleExactAlarm returned false", apiResult.get());
     }
 
+    @Test
+    public void canScheduleExactAlarmWithPolicyPermissionSdk32() throws Exception {
+        final CountDownLatch resultLatch = new CountDownLatch(1);
+        final AtomicBoolean apiResult = new AtomicBoolean(true);
+        final AtomicInteger result = new AtomicInteger(-1);
+
+        final Intent requestToTestApp = new Intent(
+                RequestReceiverSdk32.ACTION_GET_CAN_SCHEDULE_EXACT_ALARM)
+                .setClassName(RequestReceiverSdk32.PACKAGE_NAME,
+                        RequestReceiverSdk32.class.getName())
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        sContext.sendOrderedBroadcast(requestToTestApp, null, new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                result.set(getResultCode());
+                final String resultStr = getResultData();
+                apiResult.set(Boolean.parseBoolean(resultStr));
+                resultLatch.countDown();
+            }
+        }, null, Activity.RESULT_CANCELED, null, null);
+
+        assertTrue("Timed out waiting for response from helper app",
+                resultLatch.await(10, TimeUnit.SECONDS));
+        assertEquals(Activity.RESULT_OK, result.get());
+        assertFalse("canScheduleExactAlarm returned true", apiResult.get());
+    }
+
     @Test(expected = SecurityException.class)
     public void setAlarmClockWithoutPermission() throws IOException {
         revokeAppOp();
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ExpeditedJobTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ExpeditedJobTest.java
index 9f2db10..19d76e3 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ExpeditedJobTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ExpeditedJobTest.java
@@ -83,6 +83,21 @@
                 225 /* ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ */);
     }
 
+    /** Test that EJs for the TOP app start immediately and there is no limit on the number. */
+    @Test
+    public void testTopEJUnlimited() throws Exception {
+        final int standardConcurrency = 16;
+        final int numEjs = 2 * standardConcurrency;
+        mTestAppInterface.startAndKeepTestActivity(true);
+        for (int i = 0; i < numEjs; ++i) {
+            mTestAppInterface.scheduleJob(
+                    Map.of(TestJobSchedulerReceiver.EXTRA_AS_EXPEDITED, true),
+                    Map.of(TestJobSchedulerReceiver.EXTRA_JOB_ID_KEY, i));
+            assertTrue("Job did not start after scheduling",
+                    mTestAppInterface.awaitJobStart(i, DEFAULT_WAIT_TIMEOUT_MS));
+        }
+    }
+
     /** Forces JobScheduler to run the job */
     private void forceRunJob() throws Exception {
         mUiDevice.executeShellCommand("cmd jobscheduler run -f"
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index 825f9b4..3ec265d 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -1075,6 +1075,72 @@
                 mTestAppInterface.getLastParams().getStopReason());
     }
 
+    /*
+    Tests currently disabled because they require changes inside the framework to lower the minimum
+    EJ quota to one minute (from 5 minutes).
+    TODO(224533485): make JS testable enough to enable these tests
+
+    @Test
+    public void testRestrictingStopReason_ExpeditedQuota_startOnCharging() throws Exception {
+        assumeFalse("not testable in automotive device", mAutomotiveDevice); // Test needs battery
+        assumeFalse("not testable in leanback device", mLeanbackOnly); // Test needs battery
+
+        // Reduce allowed time for testing. System to cap the time above 30 seconds.
+        mDeviceConfigStateHelper.set("qc_ej_limit_rare_ms", "30000");
+        mDeviceConfigStateHelper.set("runtime_min_ej_guarantee_ms", "30000");
+        // Start with charging so JobScheduler thinks the job can run for the maximum amount of
+        // time. We turn off charging later so quota clearly comes into effect.
+        setChargingState(true);
+        setTestPackageStandbyBucket(Bucket.RARE);
+
+        mTestAppInterface.scheduleJob(false, NETWORK_TYPE_NONE, true);
+        runJob();
+        assertTrue("New job didn't start",
+                mTestAppInterface.awaitJobStart(DEFAULT_WAIT_TIMEOUT));
+        assertTrue(mTestAppInterface.getLastParams().isExpeditedJob());
+        setChargingState(false);
+
+        assertFalse("Job stopped before using up quota",
+                mTestAppInterface.awaitJobStop(45_000));
+        Thread.sleep(15_000);
+
+        assertTrue("Job didn't stop after using up quota",
+                mTestAppInterface.awaitJobStop(DEFAULT_WAIT_TIMEOUT));
+        assertEquals(JobParameters.STOP_REASON_QUOTA,
+                mTestAppInterface.getLastParams().getStopReason());
+    }
+
+    @Test
+    public void testRestrictingStopReason_ExpeditedQuota_noCharging() throws Exception {
+        assumeFalse("not testable in automotive device", mAutomotiveDevice); // Test needs battery
+        assumeFalse("not testable in leanback device", mLeanbackOnly); // Test needs battery
+
+        // Reduce allowed time for testing.
+        mDeviceConfigStateHelper.set("qc_ej_limit_rare_ms", "30000");
+        mDeviceConfigStateHelper.set("runtime_min_ej_guarantee_ms", "30000");
+        setChargingState(false);
+        setTestPackageStandbyBucket(Bucket.RARE);
+
+        mTestAppInterface.scheduleJob(false, NETWORK_TYPE_NONE, true);
+        runJob();
+        assertTrue("New job didn't start",
+                mTestAppInterface.awaitJobStart(DEFAULT_WAIT_TIMEOUT));
+        assertTrue(mTestAppInterface.getLastParams().isExpeditedJob());
+
+        assertFalse("Job stopped before using up quota",
+                mTestAppInterface.awaitJobStop(45_000));
+        Thread.sleep(15_000);
+
+        assertTrue("Job didn't stop after using up quota",
+                mTestAppInterface.awaitJobStop(DEFAULT_WAIT_TIMEOUT));
+        // Charging state was false when the job started, so the trigger the timeout before
+        // QuotaController officially marks the quota finished.
+        final int stopReason = mTestAppInterface.getLastParams().getStopReason();
+        assertTrue(stopReason == JobParameters.STOP_REASON_TIMEOUT
+                || stopReason == JobParameters.STOP_REASON_QUOTA);
+    }
+     */
+
     @Test
     public void testRestrictingStopReason_BatterySaver() throws Exception {
         BatteryUtils.assumeBatterySaverFeature();
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/TestAppInterface.java b/tests/JobScheduler/src/android/jobscheduler/cts/TestAppInterface.java
index 8db459e..fd17c29 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/TestAppInterface.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/TestAppInterface.java
@@ -100,7 +100,9 @@
             throws Exception {
         final Intent scheduleJobIntent = new Intent(TestJobSchedulerReceiver.ACTION_SCHEDULE_JOB);
         scheduleJobIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        scheduleJobIntent.putExtra(TestJobSchedulerReceiver.EXTRA_JOB_ID_KEY, mJobId);
+        if (!intExtras.containsKey(TestJobSchedulerReceiver.EXTRA_JOB_ID_KEY)) {
+            scheduleJobIntent.putExtra(TestJobSchedulerReceiver.EXTRA_JOB_ID_KEY, mJobId);
+        }
         booleanExtras.forEach(scheduleJobIntent::putExtra);
         intExtras.forEach(scheduleJobIntent::putExtra);
         scheduleJobIntent.setComponent(new ComponentName(TEST_APP_PACKAGE, TEST_APP_RECEIVER));
@@ -165,9 +167,13 @@
     };
 
     boolean awaitJobStart(long maxWait) throws Exception {
+        return awaitJobStart(mJobId, maxWait);
+    }
+
+    boolean awaitJobStart(int jobId, long maxWait) throws Exception {
         return waitUntilTrue(maxWait, () -> {
             synchronized (mTestJobState) {
-                return (mTestJobState.jobId == mJobId) && mTestJobState.running;
+                return (mTestJobState.jobId == jobId) && mTestJobState.running;
             }
         });
     }
diff --git a/tests/MediaProviderTranscode/Android.bp b/tests/MediaProviderTranscode/Android.bp
index 5ac7b91..54ee715 100644
--- a/tests/MediaProviderTranscode/Android.bp
+++ b/tests/MediaProviderTranscode/Android.bp
@@ -32,7 +32,8 @@
     ],
 
     min_sdk_version: "30",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
     certificate: "media",
     java_resources: [":CtsTranscodeTestAppSupportsHevc", ":CtsTranscodeTestAppSupportsSlowMotion"]
 }
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java b/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
index 561823b..5110781 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PickerProviderMediaGenerator.java
@@ -17,9 +17,13 @@
 package android.photopicker.cts;
 
 import static android.provider.CloudMediaProviderContract.AlbumColumns;
+import static android.provider.CloudMediaProviderContract.EXTRA_ALBUM_ID;
+import static android.provider.CloudMediaProviderContract.EXTRA_MEDIA_COLLECTION_ID;
+import static android.provider.CloudMediaProviderContract.EXTRA_SYNC_GENERATION;
 import static android.provider.CloudMediaProviderContract.MediaCollectionInfo;
 import static android.provider.CloudMediaProviderContract.MediaColumns;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
@@ -87,18 +91,24 @@
             mPrivateDir = context.getFilesDir();
         }
 
-        public Cursor getMedia(long generation, String albumdId, String mimeType, long sizeBytes) {
-            return getCursor(mMedia, generation, albumdId, mimeType, sizeBytes,
+        public Cursor getMedia(long generation, String albumId, String mimeType, long sizeBytes) {
+            final Cursor cursor = getCursor(mMedia, generation, albumId, mimeType, sizeBytes,
                     /* isDeleted */ false);
+            cursor.setExtras(buildCursorExtras(mCollectionId, generation > 0, albumId != null));
+            return cursor;
         }
 
         public Cursor getAlbums(String mimeType, long sizeBytes) {
-            return getCursor(mAlbums, mimeType, sizeBytes);
+            final Cursor cursor = getCursor(mAlbums, mimeType, sizeBytes);
+            cursor.setExtras(buildCursorExtras(mCollectionId, false, false));
+            return cursor;
         }
 
         public Cursor getDeletedMedia(long generation) {
-            return getCursor(mDeletedMedia, generation, /* albumId */ null, /* mimeType */ null,
-                    /* sizeBytes */ 0, /* isDeleted */ true);
+            final Cursor cursor = getCursor(mDeletedMedia, generation, /* albumId */ null,
+                    /* mimeType */ null, /* sizeBytes */ 0, /* isDeleted */ true);
+            cursor.setExtras(buildCursorExtras(mCollectionId, generation > 0, false));
+            return cursor;
         }
 
         public Bundle getMediaCollectionInfo() {
@@ -117,6 +127,23 @@
             mAccountConfigurationIntent = configIntent;
         }
 
+        public Bundle buildCursorExtras(String mediaCollectionId, boolean honoredSyncGeneration,
+                boolean honoredAlbumdId) {
+            final ArrayList<String> honoredArgs = new ArrayList<>();
+            if (honoredSyncGeneration) {
+                honoredArgs.add(EXTRA_SYNC_GENERATION);
+            }
+            if (honoredAlbumdId) {
+                honoredArgs.add(EXTRA_ALBUM_ID);
+            }
+
+            final Bundle bundle = new Bundle();
+            bundle.putString(EXTRA_MEDIA_COLLECTION_ID, mediaCollectionId);
+            bundle.putStringArrayList(ContentResolver.EXTRA_HONORED_ARGS, honoredArgs);
+
+            return bundle;
+        }
+
         public void addMedia(String localId, String cloudId, String albumId, String mimeType,
                 int standardMimeTypeExtension, long sizeBytes, boolean isFavorite, int resId)
                 throws IOException {
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 2dfb7fd..3bde0fd 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -215,6 +215,18 @@
                 android:resource="@xml/stub_ime"/>
         </service>
 
+        <service android:name=".StubSimpleImeAccessibilityService"
+                 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+                 android:exported="true">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService"/>
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC"/>
+            </intent-filter>
+
+            <meta-data android:name="android.accessibilityservice"
+                       android:resource="@xml/stub_simple_ime_accessibility_service"/>
+        </service>
+
         <service android:name=".StubImeAccessibilityService"
             android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
             android:exported="true">
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index c79d255..014b9a7 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -190,6 +190,8 @@
 
     <string name="stub_focus_indicator_service_description">com.android.accessibilityservice.cts.StubFocusIndicatorService</string>
 
+    <string name="stub_simple_ime_accessibility_service_description">com.android.accessibilityservice.cts.StubSimpleImeAccessibilityService</string>
+
     <string name="stub_ime_accessibility_service_description">com.android.accessibilityservice.cts.StubImeAccessibilityService</string>
 
     <string name="stub_non_ime_accessibility_service_description">com.android.accessibilityservice.cts.StubNonImeAccessibilityService</string>
diff --git a/tests/accessibilityservice/res/xml/stub_simple_ime_accessibility_service.xml b/tests/accessibilityservice/res/xml/stub_simple_ime_accessibility_service.xml
new file mode 100644
index 0000000..1d5c350
--- /dev/null
+++ b/tests/accessibilityservice/res/xml/stub_simple_ime_accessibility_service.xml
@@ -0,0 +1,22 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+                       android:description="@string/stub_simple_ime_accessibility_service_description"
+                       android:accessibilityEventTypes="typeAllMask"
+                       android:accessibilityFeedbackType="feedbackGeneric"
+                       android:accessibilityFlags="flagInputMethodEditor"
+                       android:notificationTimeout="0" />
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityImeTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityImeTest.java
index 964c817..4fc8ca2 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityImeTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityImeTest.java
@@ -28,20 +28,27 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
 import android.accessibilityservice.InputMethod;
 import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity;
 import android.accessibilityservice.cts.utils.AsyncUtils;
+import android.accessibilityservice.cts.utils.RunOnMainUtils;
 import android.app.Instrumentation;
 import android.app.UiAutomation;
+import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.LargeTest;
+import android.text.TextUtils;
 import android.util.Log;
+import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -109,6 +116,58 @@
         mInitialText = mActivity.getString(R.string.text_input_blah);
     }
 
+    /**
+     * Verifies that
+     * 1) {@link android.accessibilityservice.AccessibilityService#onCreateInputMethod()} will be
+     * called and 2) it will return the default implementation of
+     * {@link android.accessibilityservice.InputMethod}, which is still functional.
+     */
+    @Test
+    public void testDefaultImplementation() throws Exception {
+        InstrumentedAccessibilityService serviceToBeCleanedUp = null;
+        try {
+            final StubSimpleImeAccessibilityService service =
+                    enableService(StubSimpleImeAccessibilityService.class);
+            serviceToBeCleanedUp = service;
+            assertTrue("time out waiting for onCreateInputMethod() to get called.",
+                    service.awaitOnCreateInputMethod(AsyncUtils.DEFAULT_TIMEOUT_MS, MILLISECONDS));
+
+            final InputMethod inputMethod = service.getInputMethod();
+            assertNotNull(inputMethod);
+
+            // Set a unique value to "privateImeOptions".
+            final String markerValue = "Test-" + SystemClock.elapsedRealtimeNanos();
+            sInstrumentation.runOnMainSync(() -> mEditText.setPrivateImeOptions(markerValue));
+
+            requestFocusAndSetCursorToEnd();
+
+            // Wait until EditorInfo#privateImeOptions becomes the expected marker value.
+            PollingCheck.waitFor(AsyncUtils.DEFAULT_TIMEOUT_MS,
+                    () -> TextUtils.equals(
+                            markerValue,
+                            RunOnMainUtils.getOnMain(sInstrumentation, () -> {
+                                final EditorInfo editorInfo =
+                                        inputMethod.getCurrentInputEditorInfo();
+                                return editorInfo != null ? editorInfo.privateImeOptions : null;
+                            })));
+
+            final InputMethod.AccessibilityInputConnection connection =
+                    inputMethod.getCurrentInputConnection();
+            assertNotNull(connection);
+
+            connection.commitText("abc", 1, null);
+
+            final String expectedText = mInitialText + "abc";
+            PollingCheck.waitFor(AsyncUtils.DEFAULT_TIMEOUT_MS,
+                    () -> RunOnMainUtils.getOnMain(sInstrumentation,
+                            () -> TextUtils.equals(expectedText, mEditText.getText())));
+        } finally {
+            if (serviceToBeCleanedUp != null) {
+                serviceToBeCleanedUp.disableSelfAndRemove();
+            }
+        }
+    }
+
     @Test
     public void testInputConnection_requestIme() throws InterruptedException {
         CountDownLatch startInputLatch = new CountDownLatch(1);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSimpleImeAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSimpleImeAccessibilityService.java
new file mode 100644
index 0000000..d34b593
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubSimpleImeAccessibilityService.java
@@ -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 android.accessibilityservice.cts;
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
+import android.accessibilityservice.InputMethod;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public final class StubSimpleImeAccessibilityService extends InstrumentedAccessibilityService {
+    private final CountDownLatch mOnCreateInputMethodLatch = new CountDownLatch(1);
+
+    public boolean awaitOnCreateInputMethod(long timeout, TimeUnit unit)
+            throws InterruptedException {
+        return mOnCreateInputMethodLatch.await(timeout, unit);
+    }
+
+    @Override
+    public InputMethod onCreateInputMethod() {
+        mOnCreateInputMethodLatch.countDown();
+        return super.onCreateInputMethod();
+    }
+}
diff --git a/tests/ambientcontext/Android.bp b/tests/ambientcontext/Android.bp
index 70f3b48..eba2b39 100644
--- a/tests/ambientcontext/Android.bp
+++ b/tests/ambientcontext/Android.bp
@@ -20,7 +20,7 @@
 }
 
 android_test {
-    name: "CtsAmbientContextDetectionServiceDeviceTestCases",
+    name: "CtsAmbientContextServiceTestCases",
     defaults: ["cts_defaults"],
     dex_preopt: {
         enabled: false,
diff --git a/tests/ambientcontext/AndroidTest.xml b/tests/ambientcontext/AndroidTest.xml
index bc45399..c3e2ff5 100644
--- a/tests/ambientcontext/AndroidTest.xml
+++ b/tests/ambientcontext/AndroidTest.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License.
   -->
 
-<configuration description="Config for CtsAmbientContextDetectionServiceDeviceTestCases">
+<configuration description="Config for CtsAmbientContextServiceTestCases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="framework" />
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
@@ -23,7 +23,7 @@
     <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="CtsAmbientContextDetectionServiceDeviceTestCases.apk" />
+        <option name="test-file-name" value="CtsAmbientContextServiceTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.ambientcontext.cts" />
diff --git a/tests/ambientcontext/src/android/ambientcontext/cts/AmbientContextManagerTest.java b/tests/ambientcontext/src/android/ambientcontext/cts/AmbientContextManagerTest.java
new file mode 100644
index 0000000..1488e05
--- /dev/null
+++ b/tests/ambientcontext/src/android/ambientcontext/cts/AmbientContextManagerTest.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.ambientcontext.cts;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.app.PendingIntent;
+import android.app.ambientcontext.AmbientContextEvent;
+import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.AmbientContextManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.PersistableBundle;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Test the AmbientContextManager API. Run with "atest CtsAmbientContextServiceTestCases".
+ */
+@RunWith(AndroidJUnit4.class)
+public class AmbientContextManagerTest {
+    private Context mContext;
+    private AmbientContextManager mAmbientContextManager;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = getInstrumentation().getContext();
+        mAmbientContextManager = (AmbientContextManager) mContext.getSystemService(
+                Context.AMBIENT_CONTEXT_SERVICE);
+    }
+
+    @Test
+    public void testGetEventsFromIntent() {
+        Intent intent = new Intent();
+        ArrayList<AmbientContextEvent> events = new ArrayList<>();
+        int eventCough = AmbientContextEvent.EVENT_COUGH;
+        Instant start = Instant.ofEpochMilli(1000L);
+        Instant end = Instant.ofEpochMilli(3000L);
+        int levelHigh = AmbientContextEvent.LEVEL_HIGH;
+        AmbientContextEvent expectedEvent = new AmbientContextEvent.Builder()
+                .setEventType(eventCough)
+                .setStartTime(start)
+                .setEndTime(end)
+                .setConfidenceLevel(levelHigh)
+                .setDensityLevel(levelHigh)
+                .build();
+        events.add(expectedEvent);
+        intent.putExtra(AmbientContextManager.EXTRA_AMBIENT_CONTEXT_EVENTS, events);
+
+        List<AmbientContextEvent> eventsFromIntent = AmbientContextManager.getEventsFromIntent(
+                intent);
+        assertEquals(1, eventsFromIntent.size());
+
+        AmbientContextEvent actualEvent = eventsFromIntent.get(0);
+        assertEquals(eventCough, actualEvent.getEventType());
+        assertEquals(start, actualEvent.getStartTime());
+        assertEquals(end, actualEvent.getEndTime());
+        assertEquals(levelHigh, actualEvent.getConfidenceLevel());
+        assertEquals(levelHigh, actualEvent.getDensityLevel());
+    }
+
+    @Test
+    public void testQueryStatus_noPermission() {
+        assertEquals(PackageManager.PERMISSION_DENIED, mContext.checkCallingOrSelfPermission(
+                Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT));
+
+        int[] eventsArray = new int[] {AmbientContextEvent.EVENT_COUGH};
+        Set<Integer> eventTypes = Arrays.stream(eventsArray).boxed().collect(
+                Collectors.toSet());
+        try {
+            mAmbientContextManager.queryAmbientContextServiceStatus(eventTypes,
+                    null, null);
+            fail("Expected SecurityException for an app not holding"
+                    + " ACCESS_AMBIENT_CONTEXT permission.");
+        } catch (SecurityException e) {
+            // Exception expected
+        }
+    }
+
+    @Test
+    public void testStartConsentActivity_noPermission() {
+        int[] eventsArray = new int[] {AmbientContextEvent.EVENT_COUGH};
+        Set<Integer> eventTypes = Arrays.stream(eventsArray).boxed().collect(
+                Collectors.toSet());
+        try {
+            mAmbientContextManager.startConsentActivity(eventTypes);
+            fail("Expected SecurityException for an app not holding"
+                    + " ACCESS_AMBIENT_CONTEXT permission.");
+        } catch (SecurityException e) {
+            // Exception expected
+        }
+    }
+
+    @Test
+    public void testRegisterObserver_immmutablePendingIntent() {
+        PersistableBundle bundle = new PersistableBundle();
+        String optionKey = "TestOption";
+        bundle.putBoolean(optionKey, false);
+        AmbientContextEventRequest request = new AmbientContextEventRequest.Builder()
+                .addEventType(AmbientContextEvent.EVENT_COUGH)
+                .setOptions(bundle)
+                .build();
+        assertFalse(request.getOptions().getBoolean(optionKey));
+
+        Intent intent = new Intent();
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE);
+        try {
+            mAmbientContextManager.registerObserver(request, pendingIntent, null, null);
+            fail("Expected IllegalArgumentException for a immutable PendingIntent.");
+        } catch (IllegalArgumentException e) {
+            // Exception expected
+        }
+    }
+
+    @Test
+    public void testRegisterObserver_noPermission() {
+        AmbientContextEventRequest request = new AmbientContextEventRequest.Builder()
+                .addEventType(AmbientContextEvent.EVENT_COUGH)
+                .build();
+        Intent intent = new Intent();
+        PendingIntent pendingIntent =
+                PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_MUTABLE);
+        try {
+            mAmbientContextManager.registerObserver(request, pendingIntent, null, null);
+            fail("Expected SecurityException for an app not holding"
+                    + " ACCESS_AMBIENT_CONTEXT permission.");
+        } catch (SecurityException e) {
+            // Exception expected
+        }
+    }
+
+    @Test
+    public void testUnregisterObserver_noPermission() {
+        try {
+            mAmbientContextManager.unregisterObserver();
+            fail("Expected SecurityException for an app not holding"
+                    + " ACCESS_AMBIENT_CONTEXT permission.");
+        } catch (SecurityException e) {
+            // Exception expected
+        }
+    }
+}
diff --git a/tests/ambientcontext/src/android/ambientcontext/cts/CtsAmbientContextDetectionServiceDeviceTest.java b/tests/ambientcontext/src/android/ambientcontext/cts/CtsAmbientContextDetectionServiceDeviceTest.java
index 2aa89fa..cd7a7f0 100644
--- a/tests/ambientcontext/src/android/ambientcontext/cts/CtsAmbientContextDetectionServiceDeviceTest.java
+++ b/tests/ambientcontext/src/android/ambientcontext/cts/CtsAmbientContextDetectionServiceDeviceTest.java
@@ -28,6 +28,7 @@
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
 import android.platform.test.annotations.AppModeFull;
+import android.service.ambientcontext.AmbientContextDetectionResult;
 import android.text.TextUtils;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -40,6 +41,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Arrays;
+import java.util.List;
+
 
 /**
  * This suite of test ensures that AmbientContextService behaves correctly when properly
@@ -139,6 +143,25 @@
         assertThat(getLastAppPackageName()).isEqualTo(FAKE_APP_PACKAGE);
     }
 
+    @Test
+    public void testConstructAmbientContextDetectionResult() {
+        List<AmbientContextEvent> events = Arrays.asList(new AmbientContextEvent[] {FAKE_EVENT});
+        AmbientContextDetectionResult result = new AmbientContextDetectionResult
+                .Builder(FAKE_APP_PACKAGE)
+                .addEvents(events)
+                .build();
+        List<AmbientContextEvent> actualEvents = result.getEvents();
+        assertThat(actualEvents.size()).isNotEqualTo(1);
+        assertThat(actualEvents).contains(FAKE_EVENT);
+
+        result = new AmbientContextDetectionResult
+                .Builder(FAKE_APP_PACKAGE)
+                .addEvents(events)
+                .clearEvents()
+                .build();
+        assertThat(result.getEvents()).isEmpty();
+    }
+
     private int getLastStatusCode() {
         return Integer.parseInt(runShellCommand(
                 "cmd ambient_context get-last-status-code"));
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index a8b6075..0f98cdf 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -1465,7 +1465,8 @@
     /**
      * After startForeground() and stopForeground(), the second startForeground() can succeed or not
      * depends on the service's app proc state.
-     * Test startForegroundService() -> startForeground() -> stopForeground() -> startForeground().
+     * Test startForegroundService() -> startForeground() -> stopForeground() -> startForeground()
+     * -> startForeground().
      */
     @Test
     public void testSecondStartForeground() throws Exception {
@@ -1478,10 +1479,10 @@
             enableFgsRestriction(true, true, null);
             WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
             waiter.prepare(ACTION_START_FGS_RESULT);
-            // bypass bg-service-start restriction.
+            // Bypass bg-service-start restriction.
             CtsAppTestUtils.executeShellCmd(mInstrumentation,
                     "dumpsys deviceidle whitelist +" + PACKAGE_NAME_APP1);
-            // start foreground service.
+            // Start foreground service from APP1, the service can enter FGS.
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
@@ -1489,7 +1490,7 @@
             CtsAppTestUtils.executeShellCmd(mInstrumentation,
                     "dumpsys deviceidle whitelist -" + PACKAGE_NAME_APP1);
 
-            // stopForeground()
+            // stopForeground(), the service exits FGS, become a background service.
             Bundle extras = LocalForegroundService.newCommand(
                     LocalForegroundService.COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION);
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
@@ -1497,18 +1498,22 @@
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE,
                     new Integer(PROCESS_CAPABILITY_NONE));
 
-            // startForeground() again.
+            // APP2 is in the background, from APP2, call startForeground().
+            // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called,
+            // because APP2 is in the background, mAllowStartForeground is set to false.
+            // When Service.startForeground() is called, setFgsRestrictionLocked() is called again,
+            // APP1's proc state is in the background and mAllowStartForeground is set to false.
             extras = LocalForegroundService.newCommand(
                     LocalForegroundService.COMMAND_START_FOREGROUND);
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
-                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);
+                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras);
             try {
                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
                 fail("Service should not enter foreground service state");
             } catch (Exception e) {
             }
 
-            // Put app to a TOP proc state.
+            // Put APP1 to a TOP proc state.
             allowBgActivityStart(PACKAGE_NAME_APP1, true);
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
@@ -1516,17 +1521,24 @@
                     new Integer(PROCESS_CAPABILITY_ALL));
             allowBgActivityStart(PACKAGE_NAME_APP1, false);
 
-            // Call startForeground() second time.
+            // APP2 is in the background, from APP2, call startForeground() second time.
+            // When APP2 calls Context.startService(), setFgsRestrictionLocked() is called,
+            // because APP2 is in the background, mAllowStartForeground is set to false.
+            // When Service.startForeground() is called, setFgsRestrictionLocked() is called again,
+            // because APP1's proc state is in the foreground and mAllowStartForeground is set to
+            // true.
             waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
             waiter.prepare(ACTION_START_FGS_RESULT);
-            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
-                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
+            extras = LocalForegroundService.newCommand(
+                    LocalForegroundService.COMMAND_START_FOREGROUND);
+            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_START_SERVICE,
+                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, extras);
+            waiter.doWait(WAITFOR_MSEC);
+            // Stop app1's activity.
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
                     LOCAL_SERVICE_PROCESS_CAPABILITY);
-            waiter.doWait(WAITFOR_MSEC);
 
             // Stop the FGS.
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 42e16ac..05a0f9e 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -576,7 +576,7 @@
 
             // Going off the temp whitelist causes a spurious proc state report...  that's
             // not ideal, but okay.
-            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
+            // uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
 
             // We don't want to wait for the uid to actually go idle, we can force it now.
             cmd = "am make-uid-idle --user " + userId + " " + SIMPLE_PACKAGE_NAME;
@@ -887,7 +887,7 @@
 
             // Going off the temp whitelist causes a spurious proc state report...  that's
             // not ideal, but okay.
-            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
+            // uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
 
             // We don't want to wait for the uid to actually go idle, we can force it now.
             controller.makeUidIdle();
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index a207625..f62f9d2 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -29,7 +29,6 @@
 import static android.content.pm.PackageManager.DONT_KILL_APP;
 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
 
-import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -72,6 +71,7 @@
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Bundle;
@@ -109,9 +109,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -156,9 +154,6 @@
 
     private static final String MCC_TO_UPDATE = "987";
     private static final String MNC_TO_UPDATE = "654";
-    private static final String SHELL_COMMAND_GET_CONFIG = "am get-config";
-    private static final String SHELL_COMMAND_RESULT_CONFIG_NAME_MCC = "mcc";
-    private static final String SHELL_COMMAND_RESULT_CONFIG_NAME_MNC = "mnc";
 
     // Return states of the ActivityReceiverFilter.
     public static final int RESULT_PASS = 1;
@@ -722,48 +717,22 @@
             return;
         }
 
-        // Store the original mcc mnc to set back
-        String[] mccMncConfigOriginal = new String[2];
-        // Store other configs to check they won't be affected
-        Set<String> otherConfigsOriginal = new HashSet<>();
-        getMccMncConfigsAndOthers(mccMncConfigOriginal, otherConfigsOriginal);
-
+        Configuration originalConfig = mTargetContext.getResources().getConfiguration();
         String[] mccMncConfigToUpdate = new String[] {MCC_TO_UPDATE, MNC_TO_UPDATE};
         boolean success = ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
                 (am) -> am.updateMccMncConfiguration(mccMncConfigToUpdate[0],
                         mccMncConfigToUpdate[1]));
 
         if (success) {
-            String[] mccMncConfigUpdated = new String[2];
-            Set<String> otherConfigsUpdated = new HashSet<>();
-            getMccMncConfigsAndOthers(mccMncConfigUpdated, otherConfigsUpdated);
-            // Check the mcc mnc are updated as expected
-            assertArrayEquals(mccMncConfigToUpdate, mccMncConfigUpdated);
-            // Check other configs are not changed
-            assertEquals(otherConfigsOriginal, otherConfigsUpdated);
+            Configuration changedConfig = mTargetContext.getResources().getConfiguration();
+            assertEquals(MNC_TO_UPDATE, Integer.toString(changedConfig.mnc));
+            assertEquals(MCC_TO_UPDATE, Integer.toString(changedConfig.mcc));
         }
 
-        // Set mcc mnc configs back in the end of the test
+        // Set mcc mnc configs back in the end of the test if they were set to something else.
         ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
-                (am) -> am.updateMccMncConfiguration(mccMncConfigOriginal[0],
-                        mccMncConfigOriginal[1]));
-    }
-
-    private void getMccMncConfigsAndOthers(String[] mccMncConfigs, Set<String> otherConfigs)
-            throws Exception {
-        String[] configs = SystemUtil.runShellCommand(
-                mInstrumentation, SHELL_COMMAND_GET_CONFIG).split(" |\\-");
-        for (String config : configs) {
-            if (config.startsWith(SHELL_COMMAND_RESULT_CONFIG_NAME_MCC)) {
-                mccMncConfigs[0] = config.substring(
-                        SHELL_COMMAND_RESULT_CONFIG_NAME_MCC.length());
-            } else if (config.startsWith(SHELL_COMMAND_RESULT_CONFIG_NAME_MNC)) {
-                mccMncConfigs[1] = config.substring(
-                        SHELL_COMMAND_RESULT_CONFIG_NAME_MNC.length());
-            } else {
-                otherConfigs.add(config);
-            }
-        }
+                (am) -> am.updateMccMncConfiguration(Integer.toString(originalConfig.mcc),
+                        Integer.toString(originalConfig.mnc)));
     }
 
     /**
diff --git a/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/app/src/android/app/cts/WallpaperManagerTest.java
index 783d155..fc640a5 100644
--- a/tests/app/src/android/app/cts/WallpaperManagerTest.java
+++ b/tests/app/src/android/app/cts/WallpaperManagerTest.java
@@ -113,14 +113,15 @@
         if (mBroadcastReceiver != null) {
             mContext.unregisterReceiver(mBroadcastReceiver);
         }
-        try {
-            ensureSetWallpaperDimAmountPermissionIsGranted();
-            mWallpaperManager.setWallpaperDimAmount(0f);
-            assertDimAmountEqualsTo(0f);
-        } finally {
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                    .dropShellPermissionIdentity();
-            mAcquiredWallpaperDimmingPermission = false;
+        if (mAcquiredWallpaperDimmingPermission) {
+            try {
+                mWallpaperManager.setWallpaperDimAmount(0f);
+                assertDimAmountEqualsTo(0f);
+            } finally {
+                InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                        .dropShellPermissionIdentity();
+                mAcquiredWallpaperDimmingPermission = false;
+            }
         }
     }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
index 745ed17..d35dd40 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/LoginActivity.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
@@ -390,6 +391,13 @@
     }
 
     /**
+     * Get insets of the root window
+     */
+    public WindowInsets getRootWindowInsets() {
+        return mUsernameLabel.getRootWindowInsets();
+    }
+
+    /**
      * Holder for the expected auto-fill values.
      */
     private final class FillExpectation {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
index 94be565..ec8a4d1 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dialog/LoginActivityTest.java
@@ -20,8 +20,12 @@
 import static android.autofillservice.cts.testcore.Helper.ID_USERNAME;
 import static android.autofillservice.cts.testcore.Helper.assertHasFlags;
 import static android.autofillservice.cts.testcore.Helper.enableFillDialogFeature;
+import static android.autofillservice.cts.testcore.Helper.isImeShowing;
 import static android.service.autofill.FillRequest.FLAG_SUPPORTS_FILL_DIALOG;
 
+
+import static com.google.common.truth.Truth.assertThat;
+
 import android.autofillservice.cts.activities.LoginActivity;
 import android.autofillservice.cts.commontests.AutoFillServiceTestCase;
 import android.autofillservice.cts.testcore.CannedFillResponse;
@@ -39,6 +43,64 @@
 public class LoginActivityTest extends AutoFillServiceTestCase.ManualActivityLaunch {
 
     @Test
+    public void testTextView_withoutFillDialog_clickTwice_showIme() throws Exception {
+        // Start activity and autofill
+        LoginActivity activity = startLoginActivity();
+        mUiBot.waitForIdleSync();
+
+        // Click on password field
+        mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+        // Waits a while
+        mUiBot.waitForIdleSync();
+
+        // Click on password field again
+        mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+        // Waits a while
+        mUiBot.waitForIdleSync();
+
+        // Verify IME is shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isTrue();
+    }
+
+    @Test
+    public void testTextView_clickTwiceWithShowFillDialog_showIme() throws Exception {
+        // Enable feature and test service
+        enableFillDialogFeature(sContext);
+        enableService();
+
+        // Set response with a dataset > fill dialog should have two buttons
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Dropdown Presentation"))
+                        .setDialogPresentation(createPresentation("Dialog Presentation"))
+                        .build())
+                .setDialogHeader(createPresentation("Dialog Header"))
+                .setDialogTriggerIds(ID_PASSWORD);
+        sReplier.addResponse(builder.build());
+
+        // Start activity and autofill
+        LoginActivity activity = startLoginActivity();
+        mUiBot.waitForIdleSync();
+        sReplier.getNextFillRequest();
+        mUiBot.waitForIdleSync();
+
+        // Click on password field to trigger fill dialog
+        mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+        mUiBot.waitForIdleSync();
+
+        mUiBot.assertFillDialogDatasets("Dialog Presentation");
+
+        // Click on password field again
+        mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
+        mUiBot.waitForIdleSync();
+
+        // Verify IME is shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isTrue();
+    }
+
+    @Test
     public void testShowFillDialog() throws Exception {
         // Enable feature and test service
         enableFillDialogFeature(sContext);
@@ -69,6 +131,9 @@
         mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
         mUiBot.waitForIdleSync();
 
+        // Verify IME is not shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isFalse();
+
         // Verify the content of fill dialog, and then select dataset in fill dialog
         mUiBot.assertFillDialogHeader("Dialog Header");
         mUiBot.assertFillDialogRejectButton();
@@ -117,6 +182,8 @@
         mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
         mUiBot.waitForIdleSync();
 
+        // Verify IME is not shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isFalse();
         // Verify the content of fill dialog
         mUiBot.assertFillDialogHeader("Dialog Header");
         mUiBot.assertFillDialogRejectButton();
@@ -160,12 +227,16 @@
         mUiBot.waitForIdleSync();
 
         mUiBot.assertFillDialogDatasets("Dialog presentation");
+        // Verify IME is not shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isFalse();
 
         // Click on username field, and verify dropdown UI is shown
         mUiBot.selectByRelativeIdFromUiDevice(ID_USERNAME);
         mUiBot.waitForIdleSync();
 
         mUiBot.assertDatasets("Dropdown Presentation");
+        // Verify IME is shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isTrue();
 
         // Verify dropdown UI works
         activity.expectAutoFill("dude", "sweet");
@@ -204,12 +275,17 @@
         mUiBot.waitForIdleSync();
 
         mUiBot.assertDatasets("Dropdown Presentation");
+        // Verify IME is shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isTrue();
 
         // Click on password field and verify dropdown is still shown
         // can't use mUiBot.selectByRelativeId(ID_PASSWORD), because will click on dropdown UI
         activity.onPassword(View::requestFocus);
         mUiBot.waitForIdleSync();
 
+        // Verify IME is shown
+        assertThat(isImeShowing(activity.getRootWindowInsets())).isTrue();
+
         // Verify dropdown UI actually works in this case.
         activity.expectAutoFill("dude", "sweet");
         mUiBot.selectDataset("Dropdown Presentation");
@@ -250,7 +326,6 @@
         mUiBot.selectByRelativeIdFromUiDevice(ID_PASSWORD);
         mUiBot.waitForIdleSync();
         activity.expectAutoFill("dude", "sweet");
-
         mUiBot.selectFillDialogDataset("Dialog Presentation");
 
         activity.assertAutoFilled();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index 74a7882..20d9370 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -65,6 +65,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStructure.HtmlInfo;
+import android.view.WindowInsets;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillManager.AutofillCallback;
@@ -1654,6 +1655,16 @@
         deviceConfigStateManager.set("true");
     }
 
+    /**
+     * Whether IME is showing
+     */
+    public static boolean isImeShowing(WindowInsets rootWindowInsets) {
+        if (rootWindowInsets != null && rootWindowInsets.isVisible(WindowInsets.Type.ime())) {
+            return true;
+        }
+        return false;
+    }
+
     private Helper() {
         throw new UnsupportedOperationException("contain static methods only");
     }
diff --git a/tests/camera/AndroidManifest.xml b/tests/camera/AndroidManifest.xml
index ab3120a..5cc761c 100644
--- a/tests/camera/AndroidManifest.xml
+++ b/tests/camera/AndroidManifest.xml
@@ -32,7 +32,7 @@
         <activity android:name="android.hardware.cts.CameraCtsActivity"
             android:label="CameraCtsActivity"
             android:screenOrientation="locked"
-            android:configChanges="keyboardHidden|orientation|screenSize">
+            android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
         </activity>
 
         <activity android:name="android.hardware.camera2.cts.Camera2SurfaceViewCtsActivity"
diff --git a/tests/camera/src/android/hardware/cts/CameraCtsActivity.java b/tests/camera/src/android/hardware/cts/CameraCtsActivity.java
index 61e283d..a6ec8ff 100644
--- a/tests/camera/src/android/hardware/cts/CameraCtsActivity.java
+++ b/tests/camera/src/android/hardware/cts/CameraCtsActivity.java
@@ -17,11 +17,12 @@
 package android.hardware.cts;
 
 import android.app.Activity;
+import android.camera.cts.R;
+import android.content.res.Configuration;
 import android.os.Bundle;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.ViewGroup;
-import android.camera.cts.R;
 
 public class CameraCtsActivity extends Activity {
     private SurfaceView mSurfaceView;
@@ -45,4 +46,9 @@
     public SurfaceView getSurfaceView() {
         return mSurfaceView;
     }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+    }
 }
diff --git a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
index 316afd7..6857072 100644
--- a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
+++ b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
@@ -16,11 +16,18 @@
 
 package android.hardware.multiprocess.camera.cts;
 
+import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import static org.mockito.Mockito.*;
+
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
 import android.app.UiAutomation;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Rect;
 import android.hardware.Camera;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
@@ -28,12 +35,15 @@
 import android.hardware.camera2.cts.CameraTestUtils.HandlerExecutor;
 import android.hardware.cts.CameraCtsActivity;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
-
-import android.Manifest;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.WindowMetrics;
 
 import androidx.test.InstrumentationRegistry;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -41,8 +51,6 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeoutException;
 
-import static org.mockito.Mockito.*;
-
 /**
  * Tests for multi-process camera usage behavior.
  */
@@ -337,6 +345,85 @@
             }
         }
     }
+
+    private void injectTapEvent(int x, int y) {
+        final int motionEventTimeDeltaMs = 100;
+        MotionEvent downEvent = MotionEvent.obtain(SystemClock.uptimeMillis(),
+                SystemClock.uptimeMillis() + motionEventTimeDeltaMs,
+                (int) MotionEvent.ACTION_DOWN, x, y, 0);
+        downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        mUiAutomation.injectInputEvent(downEvent, true);
+
+        MotionEvent upEvent = MotionEvent.obtain(SystemClock.uptimeMillis(),
+                SystemClock.uptimeMillis() + motionEventTimeDeltaMs, (int) MotionEvent.ACTION_UP,
+                x, y, 0);
+        upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        mUiAutomation.injectInputEvent(upEvent, true);
+    }
+
+    /**
+     * Test camera availability access callback in split window mode.
+     */
+    public void testCamera2AccessCallbackInSplitMode() throws Throwable {
+        if (!ActivityTaskManager.supportsSplitScreenMultiWindow(getActivity())) {
+            return;
+        }
+
+        final int permissionCallbackTimeoutMs = 3000;
+        CameraManager manager = mContext.getSystemService(CameraManager.class);
+        assertNotNull(manager);
+        String[] cameraIds = manager.getCameraIdListNoLazy();
+
+        if (cameraIds.length == 0) {
+            Log.i(TAG, "Skipping testCamera2AccessCallback, device has no cameras.");
+            return;
+        }
+
+        assertTrue(mContext.getMainLooper() != null);
+
+        // Setup camera manager
+        Handler cameraHandler = new Handler(mContext.getMainLooper());
+
+        WindowMetrics metrics = getActivity().getWindowManager().getCurrentWindowMetrics();
+        Rect initialBounds = metrics.getBounds();
+
+        startRemoteProcess(Camera2Activity.class, "camera2ActivityProcess",
+                true /*splitScreen*/);
+
+        // Verify that the remote camera did open as expected
+        List<ErrorLoggingService.LogEvent> allEvents = mErrorServiceConnection.getLog(SETUP_TIMEOUT,
+                TestConstants.EVENT_CAMERA_CONNECT);
+        assertNotNull("Camera device not setup in remote process!", allEvents);
+
+        CameraManager.AvailabilityCallback mockAvailCb = mock(
+                CameraManager.AvailabilityCallback.class);
+        manager.registerAvailabilityCallback(mockAvailCb, cameraHandler);
+        metrics = getActivity().getWindowManager().getCurrentWindowMetrics();
+        Rect splitBounds = metrics.getBounds();
+
+        // The original of the initial and split activity bounds should remain the same
+        assertTrue((initialBounds.left == splitBounds.left)
+                && (initialBounds.top == splitBounds.top));
+
+        Rect secondBounds;
+        if (initialBounds.right > splitBounds.right) {
+            secondBounds = new Rect(splitBounds.right + 1, initialBounds.top, initialBounds.right,
+                    initialBounds.bottom);
+        } else {
+            secondBounds = new Rect(initialBounds.left, splitBounds.bottom + 1, initialBounds.right,
+                    initialBounds.bottom);
+        }
+
+        // Priorities are also expected to change when a second activity only gains or loses focus
+        // while running in split screen mode
+        injectTapEvent(splitBounds.centerX(), splitBounds.centerY());
+        injectTapEvent(secondBounds.centerX(), secondBounds.centerY());
+        injectTapEvent(splitBounds.centerX(), splitBounds.centerY());
+
+        verify(mockAvailCb, timeout(
+                permissionCallbackTimeoutMs).atLeastOnce()).onCameraAccessPrioritiesChanged();
+    }
+
     /**
      * Test camera availability access callback.
      */
@@ -361,7 +448,7 @@
         manager.registerAvailabilityCallback(mockAvailCb, cameraHandler);
 
         // Remove current task from top of stack. This will impact the camera access
-        // pririorties.
+        // priorities.
         getActivity().moveTaskToBack(/*nonRoot*/true);
 
         verify(mockAvailCb, timeout(
@@ -580,6 +667,19 @@
      */
     public void startRemoteProcess(java.lang.Class<?> klass, String processName)
             throws InterruptedException {
+        startRemoteProcess(klass, processName, false /*splitScreen*/);
+    }
+
+    /**
+     * Start an activity of the given class running in a remote process with the given name.
+     *
+     * @param klass the class of the {@link android.app.Activity} to start.
+     * @param processName the remote activity name.
+     * @param splitScreen Start new activity in split screen mode.
+     * @throws InterruptedException
+     */
+    public void startRemoteProcess(java.lang.Class<?> klass, String processName,
+            boolean splitScreen) throws InterruptedException {
         // Ensure no running activity process with same name
         Activity a = getActivity();
         String cameraActivityName = a.getPackageName() + ":" + processName;
@@ -589,6 +689,9 @@
 
         // Start activity in a new top foreground process
         Intent activityIntent = new Intent(a, klass);
+        if (splitScreen) {
+            activityIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_LAUNCH_ADJACENT);
+        }
         a.startActivity(activityIntent);
         Thread.sleep(WAIT_TIME);
 
diff --git a/tests/cloudsearch/src/android/cloudsearch/cts/Cts1CloudSearchService.java b/tests/cloudsearch/src/android/cloudsearch/cts/Cts1CloudSearchService.java
index 7820e1d..7726832 100644
--- a/tests/cloudsearch/src/android/cloudsearch/cts/Cts1CloudSearchService.java
+++ b/tests/cloudsearch/src/android/cloudsearch/cts/Cts1CloudSearchService.java
@@ -49,12 +49,12 @@
         sWatcher.queried.countDown();
         if (request.getQuery().contains("Successful1")) {
             sWatcher.succeeded.countDown();
-            returnResults(request.getRequestId(),
+            super.returnResults(request.getRequestId(),
                     CloudSearchTestUtils.getSearchResponse(SearchResponse.SEARCH_STATUS_OK));
         }
         if (request.getQuery().contains("Unsuccessful1")) {
             sWatcher.failed.countDown();
-            returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
+            super.returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
                     SearchResponse.SEARCH_STATUS_NO_INTERNET));
         }
     }
diff --git a/tests/cloudsearch/src/android/cloudsearch/cts/Cts2CloudSearchService.java b/tests/cloudsearch/src/android/cloudsearch/cts/Cts2CloudSearchService.java
index 36c56e2..33cdec8 100644
--- a/tests/cloudsearch/src/android/cloudsearch/cts/Cts2CloudSearchService.java
+++ b/tests/cloudsearch/src/android/cloudsearch/cts/Cts2CloudSearchService.java
@@ -49,12 +49,12 @@
         sWatcher.queried.countDown();
         if (request.getQuery().contains("Successful2")) {
             sWatcher.succeeded.countDown();
-            returnResults(request.getRequestId(),
+            super.returnResults(request.getRequestId(),
                     CloudSearchTestUtils.getSearchResponse(SearchResponse.SEARCH_STATUS_OK));
         }
         if (request.getQuery().contains("Unsuccessful2")) {
             sWatcher.failed.countDown();
-            returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
+            super.returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
                     SearchResponse.SEARCH_STATUS_NO_INTERNET));
         }
     }
diff --git a/tests/cloudsearch/src/android/cloudsearch/cts/Cts3CloudSearchService.java b/tests/cloudsearch/src/android/cloudsearch/cts/Cts3CloudSearchService.java
index 7cf8fe2..d264ea4 100644
--- a/tests/cloudsearch/src/android/cloudsearch/cts/Cts3CloudSearchService.java
+++ b/tests/cloudsearch/src/android/cloudsearch/cts/Cts3CloudSearchService.java
@@ -49,12 +49,12 @@
         sWatcher.queried.countDown();
         if (request.getQuery().contains("Successful3")) {
             sWatcher.succeeded.countDown();
-            returnResults(request.getRequestId(),
+            super.returnResults(request.getRequestId(),
                     CloudSearchTestUtils.getSearchResponse(SearchResponse.SEARCH_STATUS_OK));
         }
         if (request.getQuery().contains("Unsuccessful3")) {
             sWatcher.failed.countDown();
-            returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
+            super.returnResults(request.getRequestId(), CloudSearchTestUtils.getSearchResponse(
                     SearchResponse.SEARCH_STATUS_NO_INTERNET));
         }
 
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
new file mode 100644
index 0000000..ad726c0
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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 android.app.admin.DevicePolicyManager.ACTION_ROLE_HOLDER_PROVISION_FINALIZATION;
+import static android.app.admin.DevicePolicyManager.ACTION_ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE;
+import static android.app.admin.DevicePolicyManager.ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE;
+import static android.content.pm.PackageManager.FEATURE_MANAGED_USERS;
+
+import static com.android.bedstead.nene.permissions.CommonPermissions.BYPASS_ROLE_QUALIFICATION;
+import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS;
+import static com.android.bedstead.nene.permissions.CommonPermissions.MANAGE_ROLE_HOLDERS;
+import static com.android.queryable.queries.ActivityQuery.activity;
+import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.ManagedProfileProvisioningParams;
+import android.app.admin.ProvisioningException;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+
+import com.android.bedstead.deviceadminapp.DeviceAdminApp;
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
+import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.RequireFeature;
+import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDpc;
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.packages.Package;
+import com.android.bedstead.nene.users.UserReference;
+import com.android.bedstead.remotedpc.RemoteDpc;
+import com.android.bedstead.testapp.TestApp;
+import com.android.bedstead.testapp.TestAppInstance;
+import com.android.compatibility.common.util.BlockingCallback;
+import com.android.queryable.queries.ActivityQuery;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+
+@RunWith(BedsteadJUnit4.class)
+public class DevicePolicyManagementRoleHolderTest {
+    @ClassRule
+    @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+    private static final ComponentName DEVICE_ADMIN_COMPONENT_NAME =
+            DeviceAdminApp.deviceAdminComponentName(sContext);
+    private static final String PROFILE_OWNER_NAME = "testDeviceAdmin";
+    private static final ManagedProfileProvisioningParams MANAGED_PROFILE_PROVISIONING_PARAMS =
+            createManagedProfileProvisioningParamsBuilder().build();
+    private static final DevicePolicyManager sDevicePolicyManager =
+            sContext.getSystemService(DevicePolicyManager.class);
+    private static final ActivityQuery<?> sQueryForRoleHolderTrustedSourceAction =
+            activity().intentFilters().contains(
+                intentFilter().actions().contains(
+                        ACTION_ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE));
+    private static final ActivityQuery<?> sQueryForRoleHolderManagedProfileAction =
+            activity().intentFilters().contains(
+                intentFilter().actions().contains(
+                        ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE));
+    private static final ActivityQuery<?> sQueryForRoleHolderFinalizationAction =
+            activity().intentFilters().contains(
+                intentFilter().actions().contains(
+                        ACTION_ROLE_HOLDER_PROVISION_FINALIZATION));
+    private static final TestApp sRoleHolderApp = sDeviceState.testApps()
+            .query()
+            .whereActivities()
+            .contains(
+                    sQueryForRoleHolderTrustedSourceAction,
+                    sQueryForRoleHolderManagedProfileAction,
+                    sQueryForRoleHolderFinalizationAction)
+            .get();
+    private static final String MANAGED_USER_NAME = "managed user name";
+
+    @Postsubmit(reason = "new test")
+    @RequireFeature(FEATURE_MANAGED_USERS)
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    @RequireRunOnPrimaryUser
+    @EnsureHasNoDpc
+    @Test
+    public void createAndProvisionManagedProfile_roleHolderIsInWorkProfile()
+            throws ProvisioningException, InterruptedException {
+        UserHandle profile = null;
+        String roleHolderPackageName = null;
+        try (TestAppInstance roleHolderApp = sRoleHolderApp.install()) {
+            roleHolderPackageName = roleHolderApp.packageName();
+            TestApis.devicePolicy().setDevicePolicyManagementRoleHolder(roleHolderPackageName);
+
+            profile = sDevicePolicyManager.createAndProvisionManagedProfile(
+                    MANAGED_PROFILE_PROVISIONING_PARAMS);
+
+            assertThat(TestApis.packages().installedForUser(UserReference.of(profile)))
+                    .contains(Package.of(roleHolderApp.packageName()));
+        } finally {
+            if (profile != null) {
+                TestApis.users().find(profile).remove();
+            }
+            if (roleHolderPackageName != null) {
+                TestApis.devicePolicy()
+                        .unsetDevicePolicyManagementRoleHolder(roleHolderPackageName);
+            }
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @RequireFeature(FEATURE_MANAGED_USERS)
+    @EnsureHasDeviceOwner
+    @RequireRunOnPrimaryUser
+    @Test
+    public void createAndManageUser_roleHolderIsInManagedUser() throws InterruptedException {
+        UserHandle managedUser = null;
+        String roleHolderPackageName = null;
+        try (TestAppInstance roleHolderApp = sRoleHolderApp.install()) {
+            roleHolderPackageName = roleHolderApp.packageName();
+            TestApis.devicePolicy().setDevicePolicyManagementRoleHolder(roleHolderPackageName);
+
+            managedUser = sDeviceState.dpc().devicePolicyManager().createAndManageUser(
+                    RemoteDpc.DPC_COMPONENT_NAME,
+                    MANAGED_USER_NAME,
+                    RemoteDpc.DPC_COMPONENT_NAME,
+                    /* adminExtras= */ null,
+                    /* flags= */ 0);
+
+            assertThat(TestApis.packages().installedForUser(UserReference.of(managedUser)))
+                    .contains(Package.of(roleHolderApp.packageName()));
+        } finally {
+            if (managedUser != null) {
+                TestApis.users().find(managedUser).remove();
+            }
+            if (roleHolderPackageName != null) {
+                TestApis.devicePolicy()
+                        .unsetDevicePolicyManagementRoleHolder(roleHolderPackageName);
+            }
+        }
+    }
+
+    private static ManagedProfileProvisioningParams.Builder
+            createManagedProfileProvisioningParamsBuilder() {
+        return new ManagedProfileProvisioningParams.Builder(
+                DEVICE_ADMIN_COMPONENT_NAME,
+                PROFILE_OWNER_NAME);
+    }
+}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index 3d5b284..5bb50978 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -38,6 +38,7 @@
 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
 import static android.nfc.NfcAdapter.EXTRA_NDEF_MESSAGES;
 
+import static com.android.bedstead.nene.users.UserType.MANAGED_PROFILE_TYPE_NAME;
 import static com.android.bedstead.remotedpc.RemoteDpc.REMOTE_DPC_TEST_APP;
 import static com.android.queryable.queries.ServiceQuery.service;
 
@@ -102,6 +103,7 @@
 import com.android.bedstead.nene.packages.Package;
 import com.android.bedstead.nene.permissions.PermissionContext;
 import com.android.bedstead.nene.users.UserReference;
+import com.android.bedstead.nene.users.UserType;
 import com.android.bedstead.nene.utils.Poll;
 import com.android.bedstead.remotedpc.RemoteDpc;
 import com.android.bedstead.testapp.TestApp;
@@ -216,6 +218,8 @@
     private static final PersistableBundle ADMIN_EXTRAS_BUNDLE = createAdminExtrasBundle();
     private static final String TEST_KEY = "test_key";
     private static final String TEST_VALUE = "test_value";
+    private static final UserType MANAGED_PROFILE_USER_TYPE =
+            TestApis.users().supportedType(MANAGED_PROFILE_TYPE_NAME);
 
     @Before
     public void setUp() {
@@ -1184,6 +1188,7 @@
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @EnsureHasProfileOwner
     @RequireRunOnSecondaryUser
+    @RequireFeature(FEATURE_MANAGED_USERS)
     public void checkProvisioningPreCondition_actionPO_onManagedUser_returnsHasProfileOwner() {
         assertThat(
                 sDevicePolicyManager.checkProvisioningPrecondition(
@@ -1390,6 +1395,7 @@
     @Test
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @EnsureHasNoDpc
+    @RequireFeature(FEATURE_MANAGED_USERS)
     public void setUserProvisioningState_unmanagedDevice_stateUserSetupIncomplete_throwsIllegalStateException() {
         assertThrows(IllegalStateException.class, () ->
                 sDevicePolicyManager.setUserProvisioningState(
@@ -1706,6 +1712,7 @@
                 /* userdata= */ null);
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @RequireRunOnPrimaryUser
     @EnsureHasWorkProfile
@@ -1717,6 +1724,7 @@
                         /* migratedAccount= */ null));
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     public void finalizeWorkProfileProvisioning_nullManagedProfileUser_throwsException() {
@@ -1726,6 +1734,7 @@
                         /* migratedAccount= */ null));
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     public void finalizeWorkProfileProvisioning_nonExistingManagedProfileUser_throwsException() {
@@ -1735,6 +1744,7 @@
                         /* migratedAccount= */ null));
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @RequireRunOnPrimaryUser
     @EnsureHasSecondaryUser
@@ -1751,6 +1761,7 @@
         }
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @RequireRunOnPrimaryUser
     @EnsureHasWorkProfile
@@ -1768,6 +1779,7 @@
         }
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @EnsureHasWorkProfile
@@ -1787,6 +1799,7 @@
         }
     }
 
+    @Postsubmit(reason = "new test")
     @Test
     @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @EnsureHasWorkProfile
@@ -1807,4 +1820,45 @@
 
         }
     }
+
+    @Postsubmit(reason = "new test")
+    @Test
+    @EnsureHasNoDpc
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void getPolicyManagedProfiles_noManagedProfiles_returnsEmptyList() {
+        assertThat(sDevicePolicyManager.getPolicyManagedProfiles(
+                TestApis.context().instrumentationContext().getUser())).isEmpty();
+    }
+
+    @Postsubmit(reason = "new test")
+    @Test
+    @EnsureHasWorkProfile
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void getPolicyManagedProfiles_hasWorkProfile_returnsWorkProfileUser() {
+        assertThat(sDevicePolicyManager.getPolicyManagedProfiles(
+                TestApis.context().instrumentationContext().getUser()))
+                .containsExactly(sDeviceState.workProfile().userHandle());
+    }
+
+    @Postsubmit(reason = "new test")
+    @Test
+    @EnsureHasNoDpc
+    @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void getPolicyManagedProfiles_hasManagedProfileNoProfileOwner_returnsEmptyList() {
+        try (UserReference user = TestApis.users().createUser().type(MANAGED_PROFILE_USER_TYPE)
+                .parent(TestApis.users().instrumented()).create()) {
+            assertThat(sDevicePolicyManager.getPolicyManagedProfiles(
+                    TestApis.context().instrumentationContext().getUser()))
+                    .isEmpty();
+        }
+    }
+
+    @Postsubmit(reason = "new test")
+    @Test
+    @EnsureHasNoDpc
+    @EnsureDoesNotHavePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void getPolicyManagedProfiles_noPermission_returnsEmptyList() {
+        assertThrows(SecurityException.class, () -> sDevicePolicyManager.getPolicyManagedProfiles(
+                TestApis.context().instrumentationContext().getUser()));
+    }
 }
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
index 95cd7f2..87ce571 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LostModeLocationTest.java
@@ -20,6 +20,7 @@
 import static android.app.admin.DevicePolicyManager.ACTION_LOST_MODE_LOCATION_UPDATE;
 import static android.app.admin.DevicePolicyManager.EXTRA_LOST_MODE_LOCATION;
 import static android.content.Context.RECEIVER_EXPORTED;
+import static android.location.LocationManager.FUSED_PROVIDER;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -46,7 +47,6 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.runner.RunWith;
 
@@ -61,7 +61,7 @@
     private static final double TEST_LATITUDE_2 = 22.0;
     private static final double TEST_LONGITUDE_2 = -10.5;
     private static final float TEST_ACCURACY_2 = 15.0f;
-    private static final int LOCATION_UPDATE_TIMEOUT_SECONDS = 60;
+    private static final int LOCATION_UPDATE_TIMEOUT_SECONDS = 180;
 
     @ClassRule
     @Rule
@@ -94,24 +94,20 @@
 
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = LostMode.class)
-    @Ignore("b/223148704")
-    public void sendLostModeLocationUpdate_noTestProviders_returnFalse() throws Exception {
-        sendLostModeLocationUpdate(/* expected= */ false);
-    }
-
-    @Postsubmit(reason = "new test")
-    @PolicyAppliesTest(policy = LostMode.class)
-    @Ignore("b/223148704")
     public void sendLostModeLocationUpdate_noLocation_returnFalse() throws Exception {
-        try (LocationProvider provider = TestApis.location().addLocationProvider()) {
-            sendLostModeLocationUpdate(/* expected */ false);
+        try {
+            TestApis.location().setLocationEnabled(false);
+            sendLostModeLocationUpdate(/* expected= */ false);
+        } finally {
+            TestApis.location().setLocationEnabled(true);
         }
     }
 
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = LostMode.class)
-    public void sendLostModeLocationUpdate_returnTrueAndSendLocationUpdate() throws Exception {
-        try (LocationProvider provider = TestApis.location().addLocationProvider()) {
+    public void sendLostModeLocationUpdate_returnTrueAndSendLocationUpdate()
+            throws Exception {
+        try (LocationProvider provider = TestApis.location().addLocationProvider(FUSED_PROVIDER)) {
             provider.setLocation(TEST_LATITUDE, TEST_LONGITUDE, TEST_ACCURACY);
 
             sendLostModeLocationUpdate(/* expected= */ true);
@@ -133,7 +129,7 @@
     @Postsubmit(reason = "new test")
     @PolicyAppliesTest(policy = LostMode.class)
     public void sendLostModeLocationUpdate_sendMostRecentLocation() throws Exception {
-        try (LocationProvider provider = TestApis.location().addLocationProvider()) {
+        try (LocationProvider provider = TestApis.location().addLocationProvider(FUSED_PROVIDER)) {
             provider.setLocation(TEST_LATITUDE, TEST_LONGITUDE, TEST_ACCURACY);
             provider.setLocation(TEST_LATITUDE_2, TEST_LONGITUDE_2, TEST_ACCURACY_2);
 
diff --git a/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerSystemLocaleTest.java b/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerSystemLocaleTest.java
index 3de185c..fb97787 100644
--- a/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerSystemLocaleTest.java
+++ b/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerSystemLocaleTest.java
@@ -32,8 +32,9 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-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;
 
@@ -44,11 +45,31 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class LocaleManagerSystemLocaleTest extends ActivityManagerTestBase {
-    private Context mContext;
-    private LocaleManager mLocaleManager;
+    private static Context sContext;
+    private static LocaleManager sLocaleManager;
 
     /* System locales that were set on the device prior to running tests */
-    private LocaleList mPreviousSystemLocales;
+    private static LocaleList sPreviousSystemLocales;
+
+    @BeforeClass
+    public static void setUpClass() {
+        sContext = InstrumentationRegistry.getTargetContext();
+        sLocaleManager = sContext.getSystemService(LocaleManager.class);
+
+        // Set custom system locales for these tests.
+        // Store the existing system locales and reset back to it in tearDown.
+        sPreviousSystemLocales = sLocaleManager.getSystemLocales();
+        runWithShellPermissionIdentity(() ->
+                        sLocaleManager.setSystemLocales(DEFAULT_SYSTEM_LOCALES),
+                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        runWithShellPermissionIdentity(() ->
+                        sLocaleManager.setSystemLocales(sPreviousSystemLocales),
+                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
+    }
 
     @Before
     public void setUp() throws Exception {
@@ -56,41 +77,24 @@
         // to be in the foreground/background.
         super.setUp();
 
-        mContext = InstrumentationRegistry.getTargetContext();
-        mLocaleManager = mContext.getSystemService(LocaleManager.class);
-
-        // Set custom system locales for these tests.
-        // Store the existing system locales and reset back to it in tearDown.
-        mPreviousSystemLocales = mLocaleManager.getSystemLocales();
-        runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setSystemLocales(DEFAULT_SYSTEM_LOCALES),
-                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
-
         // Reset locales for the calling app.
-        mLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setSystemLocales(mPreviousSystemLocales),
-                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
+        sLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
     }
 
     @Test
     public void testGetSystemLocales_noAppLocaleSet_returnsCorrectList()
             throws Exception {
-        assertEquals(DEFAULT_SYSTEM_LOCALES, mLocaleManager.getSystemLocales());
+        assertEquals(DEFAULT_SYSTEM_LOCALES, sLocaleManager.getSystemLocales());
     }
 
     @Test
     public void testGetSystemLocales_appLocaleSet_returnsCorrectList()
             throws Exception {
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
 
         // ensure that getSystemLocales still returns the system locales
-        assertEquals(DEFAULT_SYSTEM_LOCALES, mLocaleManager.getSystemLocales());
+        assertEquals(DEFAULT_SYSTEM_LOCALES, sLocaleManager.getSystemLocales());
     }
 
 
@@ -99,7 +103,7 @@
      * by fetching the locales of the app with a binder call.
      */
     private void assertLocalesCorrectlySetForCallingApp(LocaleList expectedLocales) {
-        assertEquals(expectedLocales, mLocaleManager.getApplicationLocales());
+        assertEquals(expectedLocales, sLocaleManager.getApplicationLocales());
     }
 
 }
diff --git a/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerTests.java b/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerTests.java
index c422923..23143fc 100644
--- a/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerTests.java
+++ b/tests/framework/base/locale/src/android/localemanager/cts/LocaleManagerTests.java
@@ -59,7 +59,9 @@
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
 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;
 
@@ -74,11 +76,11 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class LocaleManagerTests extends ActivityManagerTestBase {
-    private Context mContext;
-    private LocaleManager mLocaleManager;
+    private static Context sContext;
+    private static LocaleManager sLocaleManager;
 
     /* System locales that were set on the device prior to running tests */
-    private LocaleList mPreviousSystemLocales;
+    private static LocaleList sPreviousSystemLocales;
 
     /* Receiver to listen to the broadcast in the calling (instrumentation) app. */
     private BlockingBroadcastReceiver mCallingAppBroadcastReceiver;
@@ -98,22 +100,30 @@
     /* Receiver to listen to the response from the installer app's activity. */
     private BlockingBroadcastReceiver mInstallerAppCreationInfoProvider;
 
+    @BeforeClass
+    public static void setUpClass() {
+        sContext = InstrumentationRegistry.getTargetContext();
+        sLocaleManager = sContext.getSystemService(LocaleManager.class);
+
+        sPreviousSystemLocales = sLocaleManager.getSystemLocales();
+        runWithShellPermissionIdentity(() ->
+                        sLocaleManager.setSystemLocales(DEFAULT_SYSTEM_LOCALES),
+                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        runWithShellPermissionIdentity(() ->
+                        sLocaleManager.setSystemLocales(sPreviousSystemLocales),
+                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
+    }
+
     @Before
     public void setUp() throws Exception {
         // Unlocks the device if locked, since we have tests where the app/activity needs
         // to be in the foreground/background.
         super.setUp();
 
-        mContext = InstrumentationRegistry.getTargetContext();
-        mLocaleManager = mContext.getSystemService(LocaleManager.class);
-
-        // Set custom system locales for these tests.
-        // Store the existing system locales and reset back to it in tearDown.
-        mPreviousSystemLocales = mLocaleManager.getSystemLocales();
-        runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setSystemLocales(DEFAULT_SYSTEM_LOCALES),
-                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
-
         resetAppLocalesAsEmpty();
         AmUtils.waitForBroadcastIdle();
 
@@ -124,17 +134,17 @@
         mTestAppConfigChangedInfoProvider = new BlockingBroadcastReceiver();
         mInstallerAppCreationInfoProvider = new BlockingBroadcastReceiver();
 
-        mContext.registerReceiver(mCallingAppBroadcastReceiver,
+        sContext.registerReceiver(mCallingAppBroadcastReceiver,
                 new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
-        mContext.registerReceiver(mTestAppBroadcastInfoProvider,
+        sContext.registerReceiver(mTestAppBroadcastInfoProvider,
                 new IntentFilter(TEST_APP_BROADCAST_INFO_PROVIDER_ACTION));
-        mContext.registerReceiver(mInstallerBroadcastInfoProvider,
+        sContext.registerReceiver(mInstallerBroadcastInfoProvider,
                 new IntentFilter(INSTALLER_APP_BROADCAST_INFO_PROVIDER_ACTION));
-        mContext.registerReceiver(mTestAppCreationInfoProvider,
+        sContext.registerReceiver(mTestAppCreationInfoProvider,
                 new IntentFilter(TEST_APP_CREATION_INFO_PROVIDER_ACTION));
-        mContext.registerReceiver(mTestAppConfigChangedInfoProvider,
+        sContext.registerReceiver(mTestAppConfigChangedInfoProvider,
                 new IntentFilter(TEST_APP_CONFIG_CHANGED_INFO_PROVIDER_ACTION));
-        mContext.registerReceiver(mInstallerAppCreationInfoProvider,
+        sContext.registerReceiver(mInstallerAppCreationInfoProvider,
                 new IntentFilter(INSTALLER_APP_CREATION_INFO_PROVIDER_ACTION));
 
         setInstallerForPackage(CALLING_PACKAGE);
@@ -153,14 +163,11 @@
         unRegisterReceiver(mInstallerBroadcastInfoProvider);
         unRegisterReceiver(mTestAppCreationInfoProvider);
         unRegisterReceiver(mInstallerAppCreationInfoProvider);
-        runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setSystemLocales(mPreviousSystemLocales),
-                Manifest.permission.CHANGE_CONFIGURATION, Manifest.permission.WRITE_SETTINGS);
     }
 
     private void unRegisterReceiver(BlockingBroadcastReceiver receiver) {
         if (receiver != null) {
-            mContext.unregisterReceiver(receiver);
+            sContext.unregisterReceiver(receiver);
             receiver = null;
         }
     }
@@ -181,7 +188,7 @@
                 .setComponent(new ComponentName(packageName, broadcastReceiver))
                 .setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
         CountDownLatch latch = new CountDownLatch(1);
-        mContext.sendOrderedBroadcast(
+        sContext.sendOrderedBroadcast(
                 intent,
                 null /* receiverPermission */,
                 new BroadcastReceiver() { /* resultReceiver */
@@ -205,7 +212,7 @@
      * Sets the installer as {@link #INSTALLER_PACKAGE} for the target package.
      */
     private void setInstallerForPackage(String targetPackageName) {
-        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mContext.getPackageManager(),
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(sContext.getPackageManager(),
                 (pm) -> pm.setInstallerPackageName(targetPackageName, INSTALLER_PACKAGE));
     }
 
@@ -223,7 +230,7 @@
 
     @Test
     public void testSetApplicationLocales_persistsAndSendsBroadcast() throws Exception {
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
 
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
         mCallingAppBroadcastReceiver.await();
@@ -239,14 +246,14 @@
     public void testSetApplicationLocales_resetToEmptyLocales_persistsAndSendsBroadcast()
             throws Exception {
         // First set the locales to non-empty
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
         mCallingAppBroadcastReceiver.await();
         assertReceivedBroadcastContains(mCallingAppBroadcastReceiver,
                 CALLING_PACKAGE, DEFAULT_APP_LOCALES);
         mCallingAppBroadcastReceiver.reset();
 
-        mLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
+        sLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
 
         assertLocalesCorrectlySetForCallingApp(LocaleList.getEmptyLocaleList());
         mCallingAppBroadcastReceiver.await();
@@ -258,7 +265,7 @@
     public void testSetApplicationLocales_sameLocalesEmpty_noBroadcastSent() throws Exception {
         // At the start of the test, no app-specific locales are set, so just try to set it to
         //   empty again
-        mLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
+        sLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
 
         assertLocalesCorrectlySetForCallingApp(LocaleList.getEmptyLocaleList());
         mCallingAppBroadcastReceiver.assertNoBroadcastReceived();
@@ -267,7 +274,7 @@
     @Test
     public void testSetApplicationLocales_sameLocalesNonEmpty_noBroadcastSent() throws Exception {
         // First set the locales to non-empty
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
         mCallingAppBroadcastReceiver.await();
         assertReceivedBroadcastContains(mCallingAppBroadcastReceiver,
@@ -275,7 +282,7 @@
         mCallingAppBroadcastReceiver.reset();
 
         // Then reset to the same app-specific locales, and verify no broadcasts are sent
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
 
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
         mCallingAppBroadcastReceiver.assertNoBroadcastReceived();
@@ -288,7 +295,7 @@
         LocaleList systemLocales = LocaleList.getDefault();
         assertEquals(DEFAULT_SYSTEM_LOCALES, systemLocales);
 
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
 
         // Wait for a while since LocaleList::getDefault could take a while to
         // reflect the new app locales.
@@ -304,7 +311,7 @@
         mWmState.assertVisibility(TEST_APP_MAIN_ACTIVITY, /* visible*/ true);
 
         runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
+                        sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
                 Manifest.permission.CHANGE_CONFIGURATION);
         assertLocalesCorrectlySetForAnotherApp(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES);
 
@@ -327,7 +334,7 @@
         mWmState.waitAndAssertVisibilityGone(TEST_APP_MAIN_ACTIVITY);
 
         runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
+                        sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
                 Manifest.permission.CHANGE_CONFIGURATION);
 
         assertLocalesCorrectlySetForAnotherApp(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES);
@@ -344,7 +351,7 @@
     @Test
     public void testSetApplicationLocales_forAnotherApp_persistsOnAppRestart() throws Exception {
         runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
+                        sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
                 Manifest.permission.CHANGE_CONFIGURATION);
 
         // Re-start the app by starting an activity and check if locales correctly
@@ -361,7 +368,7 @@
             testSetApplicationLocales_wthoutPermissionforAnotherApp_throwsExceptionAndNoBroadcast()
             throws Exception {
         try {
-            mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES);
+            sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES);
         } catch (SecurityException e) {
             // expected as not having appropriate permission to change locales for another app.
         }
@@ -379,7 +386,7 @@
         mWmState.assertVisibility(TEST_APP_MAIN_ACTIVITY, /* visible*/ true);
 
         runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
+                        sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES),
                 Manifest.permission.CHANGE_CONFIGURATION);
         assertLocalesCorrectlySetForAnotherApp(TEST_APP_PACKAGE, DEFAULT_APP_LOCALES);
 
@@ -394,7 +401,7 @@
 
         BlockingBroadcastReceiver appSpecificLocaleBroadcastReceiver =
                 new BlockingBroadcastReceiver();
-        mContext.registerReceiver(appSpecificLocaleBroadcastReceiver,
+        sContext.registerReceiver(appSpecificLocaleBroadcastReceiver,
                 new IntentFilter(Intent.ACTION_APPLICATION_LOCALE_CHANGED));
 
         // Hold Manifest.permission.READ_APP_SPECIFIC_LOCALES while the broadcast is sent,
@@ -419,7 +426,7 @@
 
         BlockingBroadcastReceiver appSpecificLocaleBroadcastReceiver =
                 new BlockingBroadcastReceiver();
-        mContext.registerReceiver(appSpecificLocaleBroadcastReceiver,
+        sContext.registerReceiver(appSpecificLocaleBroadcastReceiver,
                 new IntentFilter(Intent.ACTION_APPLICATION_LOCALE_CHANGED));
 
         // Tell the test app to change its app-specific locales
@@ -437,7 +444,7 @@
     @Test
     public void testGetApplicationLocales_callerIsInstaller_returnsLocales() throws Exception {
         // Set locales for calling app
-        mLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
+        sLocaleManager.setApplicationLocales(DEFAULT_APP_LOCALES);
 
         // Make sure that locales were set for the app.
         assertLocalesCorrectlySetForCallingApp(DEFAULT_APP_LOCALES);
@@ -453,7 +460,7 @@
     @Test(expected = SecurityException.class)
     public void testGetApplicationLocales_withoutPermissionforAnotherApp_throwsException()
             throws Exception {
-        mLocaleManager.getApplicationLocales(TEST_APP_PACKAGE);
+        sLocaleManager.getApplicationLocales(TEST_APP_PACKAGE);
         fail("Expected SecurityException due to not having appropriate permission "
                 + "for querying locales of another app.");
     }
@@ -462,7 +469,7 @@
     public void testGetApplicationLocales_noAppLocalesSet_returnsEmptyList() {
         // When app-specific locales aren't set, we expect get api to return empty list
         // and not throw any error.
-        assertEquals(LocaleList.getEmptyLocaleList(), mLocaleManager.getApplicationLocales());
+        assertEquals(LocaleList.getEmptyLocaleList(), sLocaleManager.getApplicationLocales());
     }
 
     /**
@@ -470,7 +477,7 @@
      * by fetching locales of the app with a binder call.
      */
     private void assertLocalesCorrectlySetForCallingApp(LocaleList expectedLocales) {
-        assertEquals(expectedLocales, mLocaleManager.getApplicationLocales());
+        assertEquals(expectedLocales, sLocaleManager.getApplicationLocales());
     }
 
     /**
@@ -484,7 +491,7 @@
 
     private LocaleList getApplicationLocales(String packageName) throws Exception {
         return callWithShellPermissionIdentity(() ->
-                mLocaleManager.getApplicationLocales(packageName),
+                sLocaleManager.getApplicationLocales(packageName),
                 Manifest.permission.READ_APP_SPECIFIC_LOCALES);
     }
 
@@ -527,11 +534,11 @@
      */
     private void resetAppLocalesAsEmpty() throws Exception {
         // Reset locales for the calling app.
-        mLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
+        sLocaleManager.setApplicationLocales(LocaleList.getEmptyLocaleList());
 
         // Reset locales for the TestApp.
         runWithShellPermissionIdentity(() ->
-                        mLocaleManager.setApplicationLocales(TEST_APP_PACKAGE,
+                        sLocaleManager.setApplicationLocales(TEST_APP_PACKAGE,
                                 LocaleList.getEmptyLocaleList()),
                 Manifest.permission.CHANGE_CONFIGURATION);
     }
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index ba93dc7..3277fb3 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -34,8 +34,9 @@
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
 
     <application android:label="CtsWindowManagerDeviceTestCases"
-         android:requestLegacyExternalStorage="true"
-         android:enableOnBackInvokedCallback="true">
+                 android:requestLegacyExternalStorage="true"
+                 android:enableOnBackInvokedCallback="true"
+                 android:testOnly="true">
         <uses-library android:name="android.test.runner"/>
 
         <activity android:name="android.server.wm.ActivityManagerTestBase$ConfigChangeHandlingActivity"
diff --git a/tests/framework/base/windowmanager/AndroidTest.xml b/tests/framework/base/windowmanager/AndroidTest.xml
index 503490b..9cdb6fa 100644
--- a/tests/framework/base/windowmanager/AndroidTest.xml
+++ b/tests/framework/base/windowmanager/AndroidTest.xml
@@ -21,6 +21,7 @@
     <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="install-arg" value="-t" />
         <option name="test-file-name" value="CtsWindowManagerDeviceTestCases.apk"/>
         <option name="test-file-name" value="CtsDragAndDropSourceApp.apk"/>
         <option name="test-file-name" value="CtsDragAndDropTargetApp.apk"/>
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 2c49bc2..804e0e7 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -622,11 +622,13 @@
         <activity android:name=".CustomTransitionExitActivity"
             android:theme="@style/Theme.CustomTransitionTheme"
             android:exported="true"
-            android:colorMode="wideColorGamut"/>
+            android:colorMode="wideColorGamut"
+            android:fitsSystemWindows="true" />
         <activity android:name=".CustomTransitionEnterActivity"
             android:theme="@style/Theme.CustomTransitionTheme"
             android:exported="true"
-            android:colorMode="wideColorGamut"/>
+            android:colorMode="wideColorGamut"
+            android:fitsSystemWindows="true" />
         <activity android:name=".KeepClearRectsActivity"
             android:exported="true"
             android:theme="@style/NoInsetsTheme"/>
diff --git a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml b/tests/framework/base/windowmanager/app/res/anim/show_backdrop_hide_window_animation.xml
similarity index 96%
rename from tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
rename to tests/framework/base/windowmanager/app/res/anim/show_backdrop_hide_window_animation.xml
index 236bf7d..5ee8b8a 100644
--- a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
+++ b/tests/framework/base/windowmanager/app/res/anim/show_backdrop_hide_window_animation.xml
@@ -17,7 +17,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
-    android:showBackground="true">
+    android:showBackdrop="true">
 
     <alpha
         android:fromAlpha="0"
diff --git a/tests/framework/base/windowmanager/app/res/values/styles.xml b/tests/framework/base/windowmanager/app/res/values/styles.xml
index 0a9cb8f..695f579 100644
--- a/tests/framework/base/windowmanager/app/res/values/styles.xml
+++ b/tests/framework/base/windowmanager/app/res/values/styles.xml
@@ -101,6 +101,8 @@
         <item name="android:background">#ffffff</item>
         <item name="android:windowBackground">#ffffff</item>
         <item name="android:colorBackground">#ffffff</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
     </style>
 
     <style name="NoInsetsTheme" parent="@android:style/Theme.NoTitleBar">
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index 0986fb3..16ddfcd 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -300,7 +300,7 @@
      * The keys used by {@link CustomTransitionExitActivity} to select the animation to run.
      */
     public static class CustomTransitionAnimations {
-        /** see @anim/show_background_hide_window_animation.xml */
+        /** see @anim/show_backdrop_hide_window_animation.xml */
         public static final String BACKGROUND_COLOR = "backgroundColor";
         /** see @anim/edge_extension_right_window_animation.xml */
         public static final String LEFT_EDGE_EXTENSION = "leftEdgeExtension";
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionEnterActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionEnterActivity.java
index a6b7672..b112c5e 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionEnterActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionEnterActivity.java
@@ -42,6 +42,10 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.background_image);
 
+        // Ensure the activity is edge-to-edge
+        // In tests we rely on the activity's content filling the entire window
+        getWindow().setDecorFitsSystemWindows(false);
+
         Intent intent = getIntent();
         Bundle bundle = intent.getExtras();
         mTransitionType = bundle.getString("transitionType");
@@ -53,8 +57,8 @@
         super.onResume();
         switch (mTransitionType) {
             case BACKGROUND_COLOR:
-                overridePendingTransition(R.anim.show_background_hide_window_animation,
-                        R.anim.show_background_hide_window_animation, mBackgroundColor);
+                overridePendingTransition(R.anim.show_backdrop_hide_window_animation,
+                        R.anim.show_backdrop_hide_window_animation, mBackgroundColor);
                 break;
             case LEFT_EDGE_EXTENSION:
                 overridePendingTransition(R.anim.edge_extension_left_window_animation,
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionExitActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionExitActivity.java
index 91cbcea..a4a73ba 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionExitActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/CustomTransitionExitActivity.java
@@ -38,6 +38,10 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.background_image);
 
+        // Ensure the activity is edge-to-edge
+        // In tests we rely on the activity's content filling the entire window
+        getWindow().setDecorFitsSystemWindows(false);
+
         Intent intent = getIntent();
         Bundle bundle = intent.getExtras();
         mTransitionType = bundle.getString("transitionType");
diff --git a/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java b/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
index b39283f..456f060 100644
--- a/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
+++ b/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
@@ -29,13 +29,11 @@
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        OnBackInvokedCallback onBackInvokedCallback = new OnBackInvokedCallback() {
-            @Override
-            public void onBackInvoked() {
-                TestJournalProvider.putExtras(BackNavigationLegacyActivity.this,
-                        Components.BACK_LEGACY,
-                        bundle -> bundle.putBoolean(Components.KEY_ON_BACK_INVOKED_CALLED, true));
-            }
+        OnBackInvokedCallback onBackInvokedCallback = () -> {
+            TestJournalProvider.putExtras(
+                    BackNavigationLegacyActivity.this,
+                    Components.BACK_LEGACY,
+                    bundle -> bundle.putBoolean(Components.KEY_ON_BACK_INVOKED_CALLED, true));
         };
         getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
                 OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
index 888cd12..3e49a2d 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingBoundsTests.java
@@ -27,22 +27,17 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.server.wm.ActivityManagerTestBase.ReportedDisplayMetrics;
-import android.server.wm.jetpack.utils.ActivityEmbeddingTestBase;
 import android.server.wm.jetpack.utils.TestActivity;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 import android.util.LayoutDirection;
 import android.util.Pair;
 import android.util.Size;
-import android.view.Display;
 
 import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.window.extensions.embedding.SplitPairRule;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -60,18 +55,6 @@
 @RunWith(AndroidJUnit4.class)
 public class ActivityEmbeddingBoundsTests extends ActivityEmbeddingTestBase {
 
-    private ReportedDisplayMetrics mReportedDisplayMetrics;
-
-    @Before
-    public void initializeDisplayMetrics() {
-        mReportedDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(Display.DEFAULT_DISPLAY);
-    }
-
-    @After
-    public void restoreDisplayMetrics() {
-        mReportedDisplayMetrics.restoreDisplayMetrics();
-    }
-
     /**
      * Tests that when two activities are in a split and the parent bounds shrink such that
      * they can no longer support split activities, then the activities become stacked.
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
index 309d652..2adc1b7 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingCrossUidTests.java
@@ -32,7 +32,6 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.server.wm.NestedShellPermission;
-import android.server.wm.jetpack.utils.ActivityEmbeddingTestBase;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 import android.util.Pair;
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
index 8af1398..69ac897 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingFinishTests.java
@@ -33,7 +33,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
-import android.server.wm.jetpack.utils.ActivityEmbeddingTestBase;
 import android.server.wm.jetpack.utils.TestActivity;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
index 2614f3d..5c2d696 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
@@ -29,7 +29,6 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.server.wm.jetpack.utils.ActivityEmbeddingTestBase;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
 import android.util.Pair;
@@ -92,19 +91,16 @@
                     Integer.toString(activityLaunchIndex) /* secondActivityId */,
                     mSplitInfoConsumer);
 
-            // Verify the split states match with the current and previous launches
+            // Verify that the secondary container has all the secondary activities
             secondaryActivities.add(secondaryActivity);
             final List<SplitInfo> lastReportedSplitInfoList =
                     mSplitInfoConsumer.getLastReportedValue();
             splitInfosList.add(lastReportedSplitInfoList);
-            assertEquals(secondaryActivities.size(), lastReportedSplitInfoList.size());
-            for (int splitInfoIndex = 0; splitInfoIndex < lastReportedSplitInfoList.size();
-                    splitInfoIndex++) {
-                final SplitInfo splitInfo = lastReportedSplitInfoList.get(splitInfoIndex);
-                assertEquals(primaryActivity, getPrimaryStackTopActivity(splitInfo));
-                assertEquals(secondaryActivities.get(splitInfoIndex),
-                        getSecondaryStackTopActivity(splitInfo));
-            }
+            assertEquals(1, lastReportedSplitInfoList.size());
+            final SplitInfo splitInfo = lastReportedSplitInfoList.get(0);
+            assertEquals(primaryActivity, getPrimaryStackTopActivity(splitInfo));
+            assertEquals(secondaryActivities, splitInfo.getSecondaryActivityStack()
+                    .getActivities());
         }
 
         // Iteratively finish each secondary activity and verify that the primary activity is split
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
index 0f07662..693d854 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingPlaceholderTests.java
@@ -29,21 +29,16 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.server.wm.ActivityManagerTestBase.ReportedDisplayMetrics;
-import android.server.wm.jetpack.utils.ActivityEmbeddingTestBase;
 import android.server.wm.jetpack.utils.TestActivity;
 import android.server.wm.jetpack.utils.TestActivityWithId;
 import android.util.Pair;
 import android.util.Size;
-import android.view.Display;
 import android.view.WindowMetrics;
 
 import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.window.extensions.embedding.SplitPlaceholderRule;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -67,17 +62,6 @@
 
     private static final String PRIMARY_ACTIVITY_ID = "primaryActivity";
     private static final String PLACEHOLDER_ACTIVITY_ID = "placeholderActivity";
-    private ReportedDisplayMetrics mReportedDisplayMetrics;
-
-    @Before
-    public void initializeDisplayMetrics() {
-        mReportedDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(Display.DEFAULT_DISPLAY);
-    }
-
-    @After
-    public void restoreDisplayMetrics() {
-        mReportedDisplayMetrics.restoreDisplayMetrics();
-    }
 
     /**
      * Tests that an activity with a matching {@link SplitPlaceholderRule} is successfully able to
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingTestBase.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingTestBase.java
similarity index 76%
rename from tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingTestBase.java
rename to tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingTestBase.java
index 6717820..9867569 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingTestBase.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingTestBase.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,17 +14,23 @@
  * limitations under the License.
  */
 
-package android.server.wm.jetpack.utils;
+package android.server.wm.jetpack;
 
 import static android.server.wm.jetpack.utils.ExtensionUtil.assumeExtensionSupportedDevice;
 import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
 
 import static org.junit.Assume.assumeNotNull;
 
+import android.server.wm.ActivityManagerTestBase.ReportedDisplayMetrics;
+import android.server.wm.jetpack.utils.TestValueCountConsumer;
+import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
+import android.view.Display;
+
 import androidx.window.extensions.WindowExtensions;
 import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
 import androidx.window.extensions.embedding.SplitInfo;
 
+import org.junit.After;
 import org.junit.Before;
 
 import java.util.List;
@@ -37,6 +43,8 @@
 
     protected ActivityEmbeddingComponent mActivityEmbeddingComponent;
     protected TestValueCountConsumer<List<SplitInfo>> mSplitInfoConsumer;
+    protected ReportedDisplayMetrics mReportedDisplayMetrics =
+            ReportedDisplayMetrics.getDisplayMetrics(Display.DEFAULT_DISPLAY);
 
     @Override
     @Before
@@ -50,4 +58,9 @@
         mSplitInfoConsumer = new TestValueCountConsumer<>();
         mActivityEmbeddingComponent.setSplitInfoCallback(mSplitInfoConsumer);
     }
+
+    @After
+    public void cleanUp() {
+        mReportedDisplayMetrics.restoreDisplayMetrics();
+    }
 }
diff --git a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml b/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_backdrop.xml
similarity index 96%
copy from tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
copy to tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_backdrop.xml
index 236bf7d..5ee8b8a 100644
--- a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
+++ b/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_backdrop.xml
@@ -17,7 +17,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
-    android:showBackground="true">
+    android:showBackdrop="true">
 
     <alpha
         android:fromAlpha="0"
diff --git a/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_background.xml b/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_background.xml
deleted file mode 100644
index 236bf7d..0000000
--- a/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_background.xml
+++ /dev/null
@@ -1,31 +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.
-  -->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shareInterpolator="false"
-    android:showBackground="true">
-
-    <alpha
-        android:fromAlpha="0"
-        android:toAlpha="0"
-        android:fillEnabled="true"
-        android:fillBefore="true"
-        android:fillAfter="true"
-        android:interpolator="@android:interpolator/linear"
-        android:startOffset="0"
-        android:duration="5000"/>
-</set>
diff --git a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml b/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_red_backdrop.xml
similarity index 93%
copy from tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
copy to tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_red_backdrop.xml
index 236bf7d..f5f03df 100644
--- a/tests/framework/base/windowmanager/app/res/anim/show_background_hide_window_animation.xml
+++ b/tests/framework/base/windowmanager/overlayappbase/res/anim/alpha_0_with_red_backdrop.xml
@@ -17,7 +17,8 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
-    android:showBackground="true">
+    android:showBackdrop="true"
+    android:backdropColor="#FF0000">
 
     <alpha
         android:fromAlpha="0"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
index 798bd25..de62c94 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
@@ -228,6 +228,22 @@
     }
 
     /**
+     * Checks that the background color set in the animation definition is used as the animation's
+     * background color instead of the theme's background color.
+     *
+     * @see R.anim.alpha_0_with_red_backdrop for animation defintition.
+     */
+    @Test
+    public void testAnimationBackgroundColorIsUsedDuringActivityTransition() {
+        final int backgroundColor = Color.RED;
+        final ActivityOptions activityOptions = ActivityOptions.makeCustomAnimation(mContext,
+                R.anim.alpha_0_with_red_backdrop, R.anim.alpha_0_with_red_backdrop);
+        Bitmap screenshot = runAndScreenshotActivityTransition(activityOptions,
+                TransitionActivityWithWhiteBackground.class);
+        assertAppRegionOfScreenIsColor(screenshot, backgroundColor);
+    }
+
+    /**
      * Checks that we can override the default background color of the animation using the
      * CustomAnimation activityOptions.
      */
@@ -235,7 +251,7 @@
     public void testCustomTransitionCanOverrideBackgroundColor() {
         final int backgroundColor = Color.GREEN;
         final ActivityOptions activityOptions = ActivityOptions.makeCustomAnimation(mContext,
-                R.anim.alpha_0_with_background, R.anim.alpha_0_with_background, backgroundColor
+                R.anim.alpha_0_with_backdrop, R.anim.alpha_0_with_backdrop, backgroundColor
         );
         Bitmap screenshot = runAndScreenshotActivityTransition(activityOptions,
                 TransitionActivity.class);
@@ -251,8 +267,8 @@
         final int backgroundColor = Color.GREEN;
 
         final Bundle extras = new Bundle();
-        extras.putInt(ENTER_ANIM_KEY, R.anim.alpha_0_with_background);
-        extras.putInt(EXIT_ANIM_KEY, R.anim.alpha_0_with_background);
+        extras.putInt(ENTER_ANIM_KEY, R.anim.alpha_0_with_backdrop);
+        extras.putInt(EXIT_ANIM_KEY, R.anim.alpha_0_with_backdrop);
         extras.putInt(BACKGROUND_COLOR_KEY, backgroundColor);
 
         Bitmap screenshot = runAndScreenshotActivityTransition(
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AnimationEdgeExtensionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AnimationEdgeExtensionTests.java
index 0530491..9102634 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AnimationEdgeExtensionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AnimationEdgeExtensionTests.java
@@ -40,6 +40,9 @@
 @android.server.wm.annotation.Group1
 public class AnimationEdgeExtensionTests extends CustomActivityTransitionTestBase {
 
+    // We need to allow for some variation stemming from color conversions
+    private static final float COLOR_VALUE_VARIANCE_TOLERANCE = 0.03f;
+
     /**
      * Checks that when an activity transition with a left edge extension is run that the animating
      * activity is extended on the left side by clamping the edge pixels of the activity.
@@ -158,7 +161,7 @@
                         new float[] {
                                 expectedColor.red(), expectedColor.green(), expectedColor.blue() },
                         new float[] { sRgbColor.red(), sRgbColor.green(), sRgbColor.blue() },
-                        0.03f); // need to allow for some variation stemming from conversions
+                        COLOR_VALUE_VARIANCE_TOLERANCE);
             }
         }
     }
@@ -174,12 +177,21 @@
             final Color c = screen.getColor(x, y)
                     .convert(ColorSpace.get(ColorSpace.Named.SRGB));
 
-            if (prevColor.red() != c.red() || prevColor.green() != c.green()
-                    || prevColor.blue() != c.blue()) {
+            if (!colorsEqual(prevColor, c)) {
                 return x;
             }
         }
 
         throw new RuntimeException("Failed to find color change index");
     }
+
+    private boolean colorsEqual(Color c1, Color c2) {
+        return almostEquals(c1.red(), c2.red(), COLOR_VALUE_VARIANCE_TOLERANCE)
+                && almostEquals(c1.green(), c2.green(), COLOR_VALUE_VARIANCE_TOLERANCE)
+                && almostEquals(c1.blue(), c2.blue(), COLOR_VALUE_VARIANCE_TOLERANCE);
+    }
+
+    private boolean almostEquals(float a, float b, float delta) {
+        return Math.abs(a - b) < delta;
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
index 3870fb2..5e9bed9 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
@@ -24,7 +24,6 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.uiautomator.UiDevice;
 import android.view.KeyEvent;
-import android.window.OnBackInvokedCallback;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
@@ -32,7 +31,6 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -118,12 +116,7 @@
         CountDownLatch backRegisteredLatch = new CountDownLatch(1);
         mScenario.onActivity(activity -> {
             activity.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
-                    0, new OnBackInvokedCallback() {
-                        @Override
-                        public void onBackInvoked() {
-                            backInvokedLatch.countDown();
-                        }
-                    });
+                    0, backInvokedLatch::countDown);
             backRegisteredLatch.countDown();
         });
         try {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index 1a6eb4c..f38e646 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -919,15 +919,21 @@
 
     private void assertImeWindowAndDisplayConfiguration(
             WindowState imeWinState, DisplayContent display) {
+        // The IME window should inherit the configuration from the IME DisplayArea.
+        final WindowManagerState.DisplayArea imeContainerDisplayArea = display.getImeContainer();
         final Configuration configurationForIme = imeWinState.mMergedOverrideConfiguration;
-        final Configuration configurationForDisplay =  display.mMergedOverrideConfiguration;
+        final Configuration configurationForImeContainer =
+                imeContainerDisplayArea.mMergedOverrideConfiguration;
         final int displayDensityDpiForIme = configurationForIme.densityDpi;
-        final int displayDensityDpi = configurationForDisplay.densityDpi;
+        final int displayDensityDpiForImeContainer = configurationForImeContainer.densityDpi;
         final Rect displayBoundsForIme = configurationForIme.windowConfiguration.getBounds();
-        final Rect displayBounds = configurationForDisplay.windowConfiguration.getBounds();
+        final Rect displayBoundsForImeContainer =
+                configurationForImeContainer.windowConfiguration.getBounds();
 
-        assertEquals("Display density not the same", displayDensityDpi, displayDensityDpiForIme);
-        assertEquals("Display bounds not the same", displayBounds, displayBoundsForIme);
+        assertEquals("Display density not the same",
+                displayDensityDpiForImeContainer, displayDensityDpiForIme);
+        assertEquals("Display bounds not the same",
+                displayBoundsForImeContainer, displayBoundsForIme);
     }
 
     private void tapAndAssertEditorFocusedOnImeActivity(
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 e9764c0..2453065 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserTests.java
@@ -39,6 +39,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -63,19 +64,33 @@
 
     @BeforeClass
     public static void createSecondUser() {
-        assumeTrue(SUPPORTS_MULTIPLE_USERS);
+        if (!SUPPORTS_MULTIPLE_USERS) {
+            return;
+        }
 
         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
         final String output = runShellCommand("pm create-user --profileOf " + context.getUserId()
                 + " user2");
         sSecondUserId = Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
-        assertThat(sSecondUserId).isNotEqualTo(0);
+        if (sSecondUserId == 0) {
+            return;
+        }
         runShellCommand("pm install-existing --user " + sSecondUserId + " android.server.wm.cts");
     }
 
     @AfterClass
     public static void removeSecondUser() {
+        if (sSecondUserId == 0) {
+            return;
+        }
         runShellCommand("pm remove-user " + sSecondUserId);
+        sSecondUserId = 0;
+    }
+
+    @Before
+    public void checkMultipleUsersNotSupportedOrSecondUserCreated() {
+        assumeTrue(SUPPORTS_MULTIPLE_USERS);
+        assertThat(sSecondUserId).isNotEqualTo(0);
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 5611dc1..1b11bd2 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
@@ -46,6 +46,7 @@
 import static android.content.pm.PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE;
 import static android.content.pm.PackageManager.FEATURE_WATCH;
 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+import static android.os.UserHandle.USER_SYSTEM;
 import static android.server.wm.ActivityLauncher.KEY_ACTIVITY_TYPE;
 import static android.server.wm.ActivityLauncher.KEY_DISPLAY_ID;
 import static android.server.wm.ActivityLauncher.KEY_INTENT_EXTRAS;
@@ -184,10 +185,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -1366,27 +1365,11 @@
      * Test @Rule class that disables screen doze settings before each test method running and
      * restoring to initial values after test method finished.
      */
-    protected static class DisableScreenDozeRule implements TestRule {
+    protected class DisableScreenDozeRule implements TestRule {
+        AmbientDisplayConfiguration mConfig;
 
-        /** Copied from android.provider.Settings.Secure since these keys are hidden. */
-        private static final String[] DOZE_SETTINGS = {
-                "doze_enabled",
-                "doze_always_on",
-                "doze_pulse_on_pick_up",
-                "doze_pulse_on_long_press",
-                "doze_pulse_on_double_tap",
-                "doze_wake_screen_gesture",
-                "doze_wake_display_gesture",
-                "doze_tap_gesture",
-                "doze_quick_pickup_gesture"
-        };
-
-        private String get(String key) {
-            return executeShellCommand("settings get secure " + key).trim();
-        }
-
-        private void put(String key, String value) {
-            executeShellCommand("settings put secure " + key + " " + value);
+        DisableScreenDozeRule() {
+            mConfig = new AmbientDisplayConfiguration(mContext);
         }
 
         @Override
@@ -1394,13 +1377,18 @@
             return new Statement() {
                 @Override
                 public void evaluate() throws Throwable {
-                    final Map<String, String> initialValues = new HashMap<>();
-                    Arrays.stream(DOZE_SETTINGS).forEach(k -> initialValues.put(k, get(k)));
                     try {
-                        Arrays.stream(DOZE_SETTINGS).forEach(k -> put(k, "0"));
+                        SystemUtil.runWithShellPermissionIdentity(() -> {
+                            // disable current doze settings
+                            mConfig.disableDozeSettings(true /* shouldDisableNonUserConfigurable */,
+                                    USER_SYSTEM);
+                        });
                         base.evaluate();
                     } finally {
-                        Arrays.stream(DOZE_SETTINGS).forEach(k -> put(k, initialValues.get(k)));
+                        SystemUtil.runWithShellPermissionIdentity(() -> {
+                            // restore doze settings
+                            mConfig.restoreDozeSettings(USER_SYSTEM);
+                        });
                     }
                 }
             };
@@ -2730,7 +2718,7 @@
         final int mDisplayId;
         final boolean mInitialIgnoreOrientationRequest;
 
-        IgnoreOrientationRequestSession(int displayId, boolean enable) {
+        public IgnoreOrientationRequestSession(int displayId, boolean enable) {
             mDisplayId = displayId;
             Matcher matcher = IGNORE_ORIENTATION_REQUEST_PATTERN.matcher(
                     executeShellCommand(WM_GET_IGNORE_ORIENTATION_REQUEST + " -d " + mDisplayId));
diff --git a/tests/input/src/android/input/cts/TouchModeTest.kt b/tests/input/src/android/input/cts/TouchModeTest.kt
index efa3122..493e2e0 100644
--- a/tests/input/src/android/input/cts/TouchModeTest.kt
+++ b/tests/input/src/android/input/cts/TouchModeTest.kt
@@ -20,21 +20,26 @@
 import android.app.Instrumentation
 import android.os.SystemClock
 import android.support.test.uiautomator.UiDevice
+import android.view.ViewTreeObserver
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.compatibility.common.util.PollingCheck
 import com.android.compatibility.common.util.WindowUtil
+import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 
-private const val EVENT_PROPAGATION_TIMEOUT_MILLIS: Long = 5000
+private const val TOUCH_MODE_PROPAGATION_TIMEOUT_MILLIS: Long = 5000 // 5 sec
 
+@MediumTest
 @RunWith(AndroidJUnit4::class)
 class TouchModeTest {
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -65,15 +70,45 @@
     }
 
     @Test
-    @Ignore("b/218883063")
+    fun testOnTouchModeChangeNotification() {
+        val touchModeChangeListener = OnTouchModeChangeListenerImpl()
+        var observer = activity.window.decorView.rootView.viewTreeObserver
+        observer.addOnTouchModeChangeListener(touchModeChangeListener)
+        val newTouchMode = !isInTouchMode()
+
+        instrumentation.setInTouchMode(newTouchMode)
+        try {
+            assertTrue(touchModeChangeListener.countDownLatch.await(
+                    TOUCH_MODE_PROPAGATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))
+        } catch (e: InterruptedException) {
+            throw RuntimeException(e)
+        }
+
+        assertEquals(newTouchMode, touchModeChangeListener.isInTouchMode)
+    }
+
+    private class OnTouchModeChangeListenerImpl : ViewTreeObserver.OnTouchModeChangeListener {
+        val countDownLatch = CountDownLatch(1)
+        var isInTouchMode = false
+
+        override fun onTouchModeChanged(mode: Boolean) {
+            isInTouchMode = mode
+            countDownLatch.countDown()
+        }
+    }
+
+    @Test
     fun testNonFocusedWindowOwnerCannotChangeTouchMode() {
+        // It takes 400-500 milliseconds in average for DecorView to receive the touch mode changed
+        // event on 2021 hardware, so we set the timeout to 10x that. It's still possible that a
+        // test would fail, but we don't have a better way to check that an event does not occur.
+        // Due to the 2 expected touch mode events to occur, this test may take few seconds to run.
         uiDevice.pressHome()
         PollingCheck.waitFor { !activity.hasWindowFocus() }
+
         instrumentation.setInTouchMode(true)
-        // It takes 400-500 milliseconds for DecorView to receive the touch mode changed event on
-        // 2021 hardware, so we set the timeout to 10x that. It's still possible that a test would
-        // fail, but we don't have a better way to check that an event does not occur.
-        SystemClock.sleep(EVENT_PROPAGATION_TIMEOUT_MILLIS)
+
+        SystemClock.sleep(TOUCH_MODE_PROPAGATION_TIMEOUT_MILLIS)
         assertFalse(isInTouchMode())
     }
 }
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index 1bb3122..e757f79 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -23,7 +23,8 @@
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
     <application android:label="CtsInputMethodTestCases"
          android:multiArch="true"
-         android:supportsRtl="true">
+         android:supportsRtl="true"
+         android:testOnly="true">
 
         <uses-library android:name="android.test.runner"/>
 
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
index 23e26e4..69316c1 100644
--- a/tests/inputmethod/AndroidTest.xml
+++ b/tests/inputmethod/AndroidTest.xml
@@ -96,6 +96,7 @@
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
         <option name="test-file-name" value="CtsInputMethodTestCases.apk" />
     </target_preparer>
     <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
diff --git a/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
index 206fdc8..ed86d8e 100644
--- a/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
+++ b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
@@ -16,56 +16,50 @@
 
 package android.view.inputmethod.cts.util;
 
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static android.os.UserHandle.USER_SYSTEM;
+
+import android.content.Context;
+import android.hardware.display.AmbientDisplayConfiguration;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * {@link TestRule} class that disables screen doze settings before each test method running and
  * restoring to initial values after test method finished.
  */
 public class DisableScreenDozeRule implements TestRule {
 
-    /** Copied from ActivityManagerTestBase since these keys are hidden. */
-    private static final String[] DOZE_SETTINGS = {
-            "doze_enabled",
-            "doze_always_on",
-            "doze_pulse_on_pick_up",
-            "doze_pulse_on_long_press",
-            "doze_pulse_on_double_tap",
-            "doze_wake_screen_gesture",
-            "doze_wake_display_gesture",
-            "doze_tap_gesture"
-    };
+    private final AmbientDisplayConfiguration mConfig;
+    private final Context mContext;
 
-    private String getSecureSetting(String key) {
-        return runShellCommand("settings get secure " + key).trim();
-    }
-
-    private void putSecureSetting(String key, String value) {
-        runShellCommand("settings put secure " + key + " " + value);
+    public DisableScreenDozeRule() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mConfig = new AmbientDisplayConfiguration(mContext);
     }
 
     @Override
-    public Statement apply(Statement base, Description description) {
+    public Statement apply(final Statement base, final Description description) {
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
-                final Map<String, String> initialValues = new HashMap<>();
-                Arrays.stream(DOZE_SETTINGS).forEach(
-                        k -> initialValues.put(k, getSecureSetting(k)));
                 try {
-                    Arrays.stream(DOZE_SETTINGS).forEach(k -> putSecureSetting(k, "0"));
+                    SystemUtil.runWithShellPermissionIdentity(() -> {
+                        // disable current doze settings
+                        mConfig.disableDozeSettings(true /* shouldDisableNonUserConfigurable */,
+                                USER_SYSTEM);
+                    });
                     base.evaluate();
                 } finally {
-                    Arrays.stream(DOZE_SETTINGS).forEach(
-                            k -> putSecureSetting(k, initialValues.get(k)));
+                    SystemUtil.runWithShellPermissionIdentity(() -> {
+                        // restore doze settings
+                        mConfig.restoreDozeSettings(USER_SYSTEM);
+                    });
                 }
             }
         };
diff --git a/tests/media/jni/NativeCodecDecoderTest.cpp b/tests/media/jni/NativeCodecDecoderTest.cpp
index 8ea1136..9a34ce8 100644
--- a/tests/media/jni/NativeCodecDecoderTest.cpp
+++ b/tests/media/jni/NativeCodecDecoderTest.cpp
@@ -475,8 +475,10 @@
         AMediaExtractor_seekTo(mExtractor, 0, mode);
         test->reset();
         if (!doWork(23)) return false;
-        CHECK_ERR(!test->isPtsStrictlyIncreasing(mPrevOutputPts), "",
-                  "pts is not strictly increasing", isPass);
+        if (!mIsInterlaced) {
+            CHECK_ERR(!test->isPtsStrictlyIncreasing(mPrevOutputPts), "",
+                          "pts is not strictly increasing", isPass);
+        }
 
         /* test flush in running state */
         if (!flushCodec()) return false;
@@ -563,8 +565,13 @@
         CHECK_ERR(loopCounter != 0 && (!ref->equals(test)), log, "output is flaky", isPass);
         CHECK_ERR(loopCounter == 0 && mIsAudio && (!ref->isPtsStrictlyIncreasing(mPrevOutputPts)),
                   log, "pts is not strictly increasing", isPass);
-        CHECK_ERR(loopCounter == 0 && !mIsAudio && (!ref->isOutPtsListIdenticalToInpPtsList(false)),
-                  log, "input pts list and output pts list are not identical", isPass);
+        // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+        // produce multiple progressive frames?) For now, do not verify timestamps.
+        if (!mIsInterlaced) {
+            CHECK_ERR(loopCounter == 0 && !mIsAudio &&
+                      (!ref->isOutPtsListIdenticalToInpPtsList(false)),
+                      log, "input pts list and output pts list are not identical", isPass);
+        }
         loopCounter++;
     }
     return isPass;
@@ -642,9 +649,13 @@
                 CHECK_ERR(loopCounter == 0 && mIsAudio &&
                           (!ref->isPtsStrictlyIncreasing(mPrevOutputPts)),
                           log, "pts is not strictly increasing", isPass);
-                CHECK_ERR(loopCounter == 0 && !mIsAudio &&
-                                  (!ref->isOutPtsListIdenticalToInpPtsList(false)),
-                          log, "input pts list and output pts list are not identical", isPass);
+                // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+                // produce multiple progressive frames?) For now, do not verify timestamps.
+                if (!mIsInterlaced) {
+                    CHECK_ERR(loopCounter == 0 && !mIsAudio &&
+                                      (!ref->isOutPtsListIdenticalToInpPtsList(false)),
+                              log, "input pts list and output pts list are not identical", isPass);
+                }
                 if (validateFormat) {
                     if (mIsCodecInAsyncMode ? !mAsyncHandle.hasOutputFormatChanged()
                                             : !mSignalledOutFormatChanged) {
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index e7e0739..7a39cc7 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -352,9 +352,15 @@
                             assertTrue(log + " pts is not strictly increasing",
                                     ref.isPtsStrictlyIncreasing(mPrevOutputPts));
                         } else {
-                            assertTrue(
-                                    log + " input pts list and output pts list are not identical",
-                                    ref.isOutPtsListIdenticalToInpPtsList(false));
+                            // TODO: Timestamps for deinterlaced content are under review.
+                            // (E.g. can decoders produce multiple progressive frames?)
+                            // For now, do not verify timestamps.
+                            if (!mIsInterlaced) {
+                                    assertTrue(
+                                        log +
+                                        " input pts list and output pts list are not identical",
+                                        ref.isOutPtsListIdenticalToInpPtsList(false));
+                            }
                         }
                     }
                     if (validateFormat) {
@@ -411,8 +417,12 @@
                 assertTrue("reference output pts is not strictly increasing",
                         ref.isPtsStrictlyIncreasing(mPrevOutputPts));
             } else {
-                assertTrue("input pts list and output pts list are not identical",
-                        ref.isOutPtsListIdenticalToInpPtsList(false));
+                // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+                // produce multiple progressive frames?) For now, do not verify timestamps.
+                if (!mIsInterlaced) {
+                    assertTrue("input pts list and output pts list are not identical",
+                            ref.isOutPtsListIdenticalToInpPtsList(false));
+                }
             }
             mOutputBuff = test;
             setUpSource(mTestFile);
@@ -445,8 +455,10 @@
                 mExtractor.seekTo(0, mode);
                 test.reset();
                 doWork(23);
-                assertTrue(log + " pts is not strictly increasing",
-                        test.isPtsStrictlyIncreasing(mPrevOutputPts));
+                if (!mIsInterlaced) {
+                    assertTrue(log + " pts is not strictly increasing",
+                                test.isPtsStrictlyIncreasing(mPrevOutputPts));
+                }
 
                 boolean checkMetrics = (mOutputCount != 0);
 
@@ -544,10 +556,14 @@
                 assertTrue("config reference output pts is not strictly increasing",
                         configRef.isPtsStrictlyIncreasing(mPrevOutputPts));
             } else {
-                assertTrue("input pts list and reference pts list are not identical",
-                        ref.isOutPtsListIdenticalToInpPtsList(false));
-                assertTrue("input pts list and reconfig ref output pts list are not identical",
-                        ref.isOutPtsListIdenticalToInpPtsList(false));
+                // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+                // produce multiple progressive frames?) For now, do not verify timestamps.
+                if (!mIsInterlaced) {
+                    assertTrue("input pts list and reference pts list are not identical",
+                            ref.isOutPtsListIdenticalToInpPtsList(false));
+                    assertTrue("input pts list and reconfig ref output pts list are not identical",
+                            ref.isOutPtsListIdenticalToInpPtsList(false));
+                }
             }
             mOutputBuff = test;
             mCodec = MediaCodec.createByCodecName(mCodecName);
@@ -713,9 +729,14 @@
                         assertTrue(log + " pts is not strictly increasing",
                                 ref.isPtsStrictlyIncreasing(mPrevOutputPts));
                     } else {
-                        assertTrue(
-                                log + " input pts list and output pts list are not identical",
-                                ref.isOutPtsListIdenticalToInpPtsList(false));
+                        // TODO: Timestamps for deinterlaced content are under review.
+                        // (E.g. can decoders produce multiple progressive frames?)
+                        // For now, do not verify timestamps.
+                        if (!mIsInterlaced) {
+                            assertTrue(
+                                    log + " input pts list and output pts list are not identical",
+                                    ref.isOutPtsListIdenticalToInpPtsList(false));
+                        }
                     }
                 }
                 loopCounter++;
@@ -807,9 +828,15 @@
                                 assertTrue(log + " pts is not strictly increasing",
                                         ref.isPtsStrictlyIncreasing(mPrevOutputPts));
                             } else {
-                                assertTrue(
-                                        log + " input pts list and output pts list are not identical",
-                                        ref.isOutPtsListIdenticalToInpPtsList(false));
+                                // TODO: Timestamps for deinterlaced content are under review.
+                                // (E.g. can decoders produce multiple progressive frames?)
+                                // For now, do not verify timestamps.
+                                if (!mIsInterlaced) {
+                                    assertTrue(
+                                           log +
+                                           " input pts list and output pts list are not identical",
+                                           ref.isOutPtsListIdenticalToInpPtsList(false));
+                                }
                             }
                         }
                         if (validateFormat) {
@@ -869,8 +896,12 @@
                 assertTrue("reference output pts is not strictly increasing",
                         ref.isPtsStrictlyIncreasing(mPrevOutputPts));
             } else {
-                assertTrue("input pts list and output pts list are not identical",
-                        ref.isOutPtsListIdenticalToInpPtsList(false));
+                // TODO: Timestamps for deinterlaced content are under review. (E.g. can decoders
+                // produce multiple progressive frames?) For now, do not verify timestamps.
+                if (!mIsInterlaced) {
+                    assertTrue("input pts list and output pts list are not identical",
+                            ref.isOutPtsListIdenticalToInpPtsList(false));
+                }
             }
             mSaveToMem = true;
             mOutputBuff = test;
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java
index c553f1e..63b1b2c 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java
@@ -46,7 +46,6 @@
     private static final String INPUT_VIDEO_FILE_HBD = "cosmat_cif_24fps_yuv420p16le.yuv";
 
     private final boolean mUseHBD;
-    private final SupportClass mSupportRequirements;
     // Key: mediaType, Value: tolerance duration in ms
     private static final Map<String, Integer> toleranceMap = new HashMap<>();
 
@@ -58,72 +57,88 @@
         toleranceMap.put(MediaFormat.MIMETYPE_AUDIO_FLAC, 0);
     }
 
-    public CodecEncoderValidationTest(String encoder, String mediaType, int[] bitrates,
-            int[] encoderInfo1, int[] encoderInfo2, boolean useHBD,
-            SupportClass supportRequirements) {
-        super(encoder, mediaType, bitrates, encoderInfo1, encoderInfo2);
+    public CodecEncoderValidationTest(String encoder, String mediaType, int bitrate,
+            int encoderInfo1, int encoderInfo2, boolean useHBD) {
+        super(encoder, mediaType, new int[]{bitrate}, new int[]{encoderInfo1},
+                new int[]{encoderInfo2});
         mUseHBD = useHBD;
-        mSupportRequirements = supportRequirements;
     }
 
-    @Parameterized.Parameters(name = "{index}({0})")
+    private static List<Object[]> flattenParams(List<Object[]> params) {
+        List<Object[]> argsList = new ArrayList<>();
+        for (Object[] param : params) {
+            String mediaType = (String) param[0];
+            int[] bitRates = (int[]) param[1];
+            int[] infoList1 = (int[]) param[2];
+            int[] infoList2 = (int[]) param[3];
+            boolean useHBD = (boolean) param[4];
+            for (int bitrate : bitRates) {
+                for (int info1 : infoList1) {
+                    for (int info2 : infoList2) {
+                        argsList.add(new Object[]{mediaType, bitrate, info1, info2, useHBD});
+                    }
+                }
+            }
+        }
+        return argsList;
+    }
+
+    @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4}_{5})")
     public static Collection<Object[]> input() {
         final boolean isEncoder = true;
         final boolean needAudio = true;
         final boolean needVideo = true;
         List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
                 // Audio tests covering cdd sec 5.1.3
-                // mediaType, arrays of bit-rates, sample rates, channel counts, useHBD,
-                // SupportClass
+                // mediaType, arrays of bit-rates, sample rates, channel counts, useHBD
                 {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{64000, 128000}, new int[]{8000, 12000,
-                        16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2}, false,
-                        CODEC_ALL},
+                        16000, 22050, 24000, 32000, 44100, 48000}, new int[]{1, 2}, false},
                 {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{64000, 128000}, new int[]{8000, 12000
-                        , 16000, 24000, 48000}, new int[]{1, 2}, false, CODEC_ALL},
+                        , 16000, 24000, 48000}, new int[]{1, 2}, false},
                 {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 5150, 5900, 6700, 7400, 7950,
-                        10200, 12200}, new int[]{8000}, new int[]{1}, false, CODEC_ALL},
+                        10200, 12200}, new int[]{8000}, new int[]{1}, false},
                 {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 8850, 12650, 14250, 15850,
-                        18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1}, false,
-                        CODEC_ALL},
+                        18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1}, false},
                 /* TODO(169310292) */
                 {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{/* 0, 1, 2, */ 3, 4, 5, 6, 7, 8},
                         new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        false, CODEC_ALL},
+                        false},
                 {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{/* 0, 1, 2, */ 3, 4, 5, 6, 7, 8},
                         new int[]{8000, 16000, 32000, 48000, 96000, 192000}, new int[]{1, 2},
-                        true, CODEC_ALL},
+                        true},
 
-                // mediaType, arrays of bit-rates, width, height, useHBD, SupportClass
+                // mediaType, arrays of bit-rates, width, height, useHBD
                 {MediaFormat.MIMETYPE_VIDEO_H263, new int[]{32000, 64000}, new int[]{176},
-                        new int[]{144}, false, CODEC_ALL},
+                        new int[]{144}, false},
                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, new int[]{32000, 64000}, new int[]{176},
-                        new int[]{144}, false, CODEC_ALL},
+                        new int[]{144}, false},
                 {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, false, CODEC_ALL},
+                        new int[]{240, 360}, false},
                 {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, false, CODEC_ALL},
+                        new int[]{240, 360}, false},
                 {MediaFormat.MIMETYPE_VIDEO_VP8, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, false, CODEC_ALL},
+                        new int[]{240, 360}, false},
                 {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, false, CODEC_ALL},
+                        new int[]{240, 360}, false},
                 {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
-                        new int[]{240, 360}, false, CODEC_ALL},
+                        new int[]{240, 360}, false},
         }));
         // P010 support was added in Android T, hence limit the following tests to Android T and
         // above
         if (IS_AT_LEAST_T) {
             defArgsList.addAll(Arrays.asList(new Object[][]{
                     {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, true, CODEC_OPTIONAL},
+                            new int[]{240, 360}, true},
                     {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, true, CODEC_OPTIONAL},
+                            new int[]{240, 360}, true},
                     {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, true, CODEC_OPTIONAL},
+                            new int[]{240, 360}, true},
                     {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
-                            new int[]{240, 360}, true, CODEC_OPTIONAL},
+                            new int[]{240, 360}, true},
             }));
         }
-        return prepareParamList(defArgsList, isEncoder, needAudio, needVideo, false);
+        List<Object[]> argsList = flattenParams(defArgsList);
+        return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
     }
 
     void encodeAndValidate(String inputFile) throws IOException, InterruptedException {
@@ -131,7 +146,7 @@
             int colorFormat = mFormats.get(0).getInteger(MediaFormat.KEY_COLOR_FORMAT);
             Assume.assumeTrue(hasSupportForColorFormat(mCodecName, mMime, colorFormat));
         }
-        checkFormatSupport(mCodecName, mMime, true, mFormats, null, mSupportRequirements);
+        checkFormatSupport(mCodecName, mMime, true, mFormats, null, CODEC_OPTIONAL);
         setUpSource(inputFile);
         mOutputBuff = new OutputManager();
         {
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 45f0e12..83a7da7 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -75,6 +75,10 @@
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) {
                 continue;
             }
+            if (CodecTestBase.codecPrefix != null &&
+                    !codecInfo.getName().startsWith(CodecTestBase.codecPrefix)) {
+                continue;
+            }
             String[] types = codecInfo.getSupportedTypes();
             for (String type : types) {
                 argsList.add(new Object[]{type, codecInfo.getName(), codecInfo});
@@ -160,6 +164,8 @@
     @Test
     public void testDecoderAvailability() {
         Assume.assumeTrue("Test is applicable only for encoders", mCodecInfo.isEncoder());
+        Assume.assumeTrue("Test is applicable for video/audio codecs",
+                mMediaType.startsWith("video/") || mMediaType.startsWith("audio/"));
         if (selectCodecs(mMediaType, null, null, true).size() > 0) {
             assertTrue("Device advertises support for encoding " + mMediaType +
                             ", but not decoding it",
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index a529d97..3e81576 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -581,9 +581,13 @@
 
 abstract class CodecTestBase {
     public static final boolean IS_AT_LEAST_R = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
-    // TODO (b/223868241) Update the following two to check for Build.VERSION_CODES.TIRAMISU once
+    // Checking for CODENAME helps in cases when build version on the development branch isn't
+    // updated yet but CODENAME is updated.
+    public static final boolean IS_AT_LEAST_T =
+            ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU) ||
+                    ApiLevelUtil.codenameEquals("Tiramisu");
+    // TODO (b/223868241) Update the following to check for Build.VERSION_CODES.TIRAMISU once
     // TIRAMISU is set correctly
-    public static final boolean IS_AT_LEAST_T = ApiLevelUtil.isAfter(Build.VERSION_CODES.S_V2);
     public static final boolean FIRST_SDK_IS_AT_LEAST_T =
             ApiLevelUtil.isFirstApiAfter(Build.VERSION_CODES.S_V2);
     private static final String LOG_TAG = CodecTestBase.class.getSimpleName();
@@ -595,6 +599,7 @@
     }
 
     static final String CODEC_PREFIX_KEY = "codec-prefix";
+    static final String MEDIA_TYPE_PREFIX_KEY = "media-type-prefix";
     static final String MIME_SEL_KEY = "mime-sel";
     static final Map<String, String> codecSelKeyMimeMap = new HashMap<>();
     static final Map<String, String> mDefaultEncoders = new HashMap<>();
@@ -649,6 +654,7 @@
     static final PackageManager pm = mContext.getPackageManager();
     static String mimeSelKeys;
     static String codecPrefix;
+    static String mediaTypePrefix;
 
     CodecAsyncHandler mAsyncHandle;
     boolean mIsCodecInAsyncMode;
@@ -696,6 +702,7 @@
         android.os.Bundle args = InstrumentationRegistry.getArguments();
         mimeSelKeys = args.getString(MIME_SEL_KEY);
         codecPrefix = args.getString(CODEC_PREFIX_KEY);
+        mediaTypePrefix = args.getString(MEDIA_TYPE_PREFIX_KEY);
 
         mProfileSdrMap.put(MediaFormat.MIMETYPE_VIDEO_AVC, AVC_SDR_PROFILES);
         mProfileSdrMap.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_SDR_PROFILES);
@@ -922,6 +929,9 @@
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) continue;
                 String[] types = codecInfo.getSupportedTypes();
                 for (String type : types) {
+                    if (mediaTypePrefix != null && !type.startsWith(mediaTypePrefix)) {
+                        continue;
+                    }
                     if (!needAudio && type.startsWith("audio/")) continue;
                     if (!needVideo && type.startsWith("video/")) continue;
                     if (!mimes.contains(type)) {
@@ -929,6 +939,9 @@
                     }
                 }
             }
+            if (mediaTypePrefix != null) {
+                return mimes;
+            }
             // feature_video_output is not exposed to package manager. Testing for video output
             // ports, such as VGA, HDMI, DisplayPort, or a wireless port for display is also not
             // direct.
diff --git a/tests/mediapc/common/Android.bp b/tests/mediapc/common/Android.bp
index ca818d7..663dabc 100644
--- a/tests/mediapc/common/Android.bp
+++ b/tests/mediapc/common/Android.bp
@@ -29,3 +29,18 @@
     ],
     plugins: ["auto_value_plugin"],
 }
+
+android_test {
+    name: "MediaPerformanceClassCommonTests",
+    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "MediaPerformanceClassCommon"
+    ],
+    platform_apis: true,
+    srcs: ["tests/src/**/*.java"],
+    test_suites: [
+        "general-tests",
+    ],
+    min_sdk_version: "30",
+}
diff --git a/tests/mediapc/common/AndroidManifest.xml b/tests/mediapc/common/AndroidManifest.xml
new file mode 100644
index 0000000..7d726e9
--- /dev/null
+++ b/tests/mediapc/common/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?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.mediapc.cts.common">
+
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="android.mediapc.cts.common"
+            android:label="tests for MediaPerformanceClassCommon" >
+    </instrumentation>
+</manifest>
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
new file mode 100644
index 0000000..ac1905c
--- /dev/null
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -0,0 +1,243 @@
+/*
+ * 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 Licnse.
+ */
+
+package android.mediapc.cts.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.rules.TestName;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Logs a set of measurements and results for defined performance class requirements.
+ */
+public class PerformanceClassEvaluator {
+    private static final String TAG = PerformanceClassEvaluator.class.getSimpleName();
+
+    private final String mTestName;
+    private Set<Requirement> mRequirements;
+
+    public PerformanceClassEvaluator(TestName testName) {
+        Preconditions.checkNotNull(testName);
+        this.mTestName = testName.getMethodName();
+        this.mRequirements = new HashSet<Requirement>();
+    }
+
+    // used for requirements [7.1.1.1/H-1-1], [7.1.1.1/H-2-1]
+    public static class ResolutionRequirement extends Requirement {
+        private static final String TAG = ResolutionRequirement.class.getSimpleName();
+
+        private ResolutionRequirement(String id, RequiredMeasurement<?> ... reqs) {
+            super(id, reqs);
+        }
+
+        public void setLongResolution(int longResolution) {
+            this.<Integer>setMeasuredValue(RequirementConstants.LONG_RESOLUTION, longResolution);
+        }
+
+        public void setShortResolution(int shortResolution) {
+            this.<Integer>setMeasuredValue(RequirementConstants.SHORT_RESOLUTION, shortResolution);
+        }
+
+        /**
+         * [7.1.1.1/H-1-1] MUST have screen resolution of at least 1080p.
+         */
+        public static ResolutionRequirement createR7_1_1_1__H_1_1() {
+            RequiredMeasurement<Integer> long_resolution = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.LONG_RESOLUTION)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.R, 1920)
+                .build();
+            RequiredMeasurement<Integer> short_resolution = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.SHORT_RESOLUTION)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.R, 1080)
+                .build();
+
+            return new ResolutionRequirement(RequirementConstants.R7_1_1_1__H_1_1, long_resolution,
+                short_resolution);
+        }
+
+        /**
+         * [7.1.1.1/H-2-1] MUST have screen resolution of at least 1080p.
+         */
+        public static ResolutionRequirement createR7_1_1_1__H_2_1() {
+            RequiredMeasurement<Integer> long_resolution = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.LONG_RESOLUTION)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.S, 1920)
+                .build();
+            RequiredMeasurement<Integer> short_resolution = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.SHORT_RESOLUTION)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.S, 1080)
+                .build();
+
+            return new ResolutionRequirement(RequirementConstants.R7_1_1_1__H_2_1, long_resolution,
+                short_resolution);
+        }
+    }
+
+    // used for requirements [7.1.1.3/H-1-1], [7.1.1.3/H-2-1]
+    public static class DensityRequirement extends Requirement {
+        private static final String TAG = DensityRequirement.class.getSimpleName();
+
+        private DensityRequirement(String id, RequiredMeasurement<?> ... reqs) {
+            super(id, reqs);
+        }
+
+        public void setDisplayDensity(int displayDensity) {
+            this.<Integer>setMeasuredValue(RequirementConstants.DISPLAY_DENSITY, displayDensity);
+        }
+
+        /**
+         * [7.1.1.3/H-1-1] MUST have screen density of at least 400 dpi.
+         */
+        public static DensityRequirement createR7_1_1_3__H_1_1() {
+            RequiredMeasurement<Integer> display_density = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.DISPLAY_DENSITY)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.R, 400)
+                .build();
+
+            return new DensityRequirement(RequirementConstants.R7_1_1_3__H_1_1, display_density);
+        }
+
+        /**
+         * [7.1.1.3/H-2-1] MUST have screen density of at least 400 dpi.
+         */
+        public static DensityRequirement createR7_1_1_3__H_2_1() {
+            RequiredMeasurement<Integer> display_density = RequiredMeasurement
+                .<Integer>builder()
+                .setId(RequirementConstants.DISPLAY_DENSITY)
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.S, 400)
+                .build();
+
+            return new DensityRequirement(RequirementConstants.R7_1_1_3__H_2_1, display_density);
+        }
+    }
+
+    // used for requirements [7.6.1/H-1-1], [7.6.1/H-2-1], [7.6.1/H-3-1]
+    public static class MemoryRequirement extends Requirement {
+        private static final String TAG = MemoryRequirement.class.getSimpleName();
+
+        private MemoryRequirement(String id, RequiredMeasurement<?> ... reqs) {
+            super(id, reqs);
+        }
+
+        public void setPhysicalMemory(long physicalMemory) {
+            this.<Long>setMeasuredValue(RequirementConstants.PHYSICAL_MEMORY, physicalMemory);
+        }
+
+        /**
+         * [7.6.1/H-1-1] MUST have at least 6 GB of physical memory.
+         */
+        public static MemoryRequirement createR7_6_1__H_1_1() {
+            RequiredMeasurement<Long> physical_memory = RequiredMeasurement
+                .<Long>builder()
+                .setId(RequirementConstants.PHYSICAL_MEMORY)
+                .setPredicate(RequirementConstants.LONG_GTE)
+                // Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB
+                // as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device.
+                .addRequiredValue(Build.VERSION_CODES.R, 5L * 1024L)
+                .build();
+
+            return new MemoryRequirement(RequirementConstants.R7_6_1__H_1_1, physical_memory);
+        }
+
+        /**
+         * [7.6.1/H-2-1] MUST have at least 6 GB of physical memory.
+         */
+        public static MemoryRequirement createR7_6_1__H_2_1() {
+            RequiredMeasurement<Long> physical_memory = RequiredMeasurement
+                .<Long>builder()
+                .setId(RequirementConstants.PHYSICAL_MEMORY)
+                .setPredicate(RequirementConstants.LONG_GTE)
+                // Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB
+                // as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device.
+                .addRequiredValue(Build.VERSION_CODES.S, 5L * 1024L)
+                .build();
+
+            return new MemoryRequirement(RequirementConstants.R7_6_1__H_2_1, physical_memory);
+        }
+    }
+
+    private <R extends Requirement> R addRequirement(R req) {
+        if (!this.mRequirements.add(req)) {
+            throw new IllegalStateException("Requirement " + req.id() + " already added");
+        }
+        return req;
+    }
+
+    public ResolutionRequirement addR7_1_1_1__H_1_1() {
+        return this.<ResolutionRequirement>addRequirement(
+            ResolutionRequirement.createR7_1_1_1__H_1_1());
+    }
+
+    public DensityRequirement addR7_1_1_3__H_1_1() {
+        return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__H_1_1());
+    }
+
+    public MemoryRequirement addR7_6_1__H_1_1() {
+        return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_1_1());
+    }
+
+    public ResolutionRequirement addR7_1_1_1__H_2_1() {
+        return this.<ResolutionRequirement>addRequirement(
+            ResolutionRequirement.createR7_1_1_1__H_2_1());
+    }
+
+    public DensityRequirement addR7_1_1_3__H_2_1() {
+        return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__H_2_1());
+    }
+
+    public MemoryRequirement addR7_6_1__H_2_1() {
+        return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_2_1());
+    }
+
+    public void submitAndCheck() {
+        boolean perfClassMet = true;
+        for (Requirement req: this.mRequirements) {
+            perfClassMet &= req.writeLogAndCheck(this.mTestName);
+        }
+
+        // check performance class
+        assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
+        assertThat(perfClassMet).isTrue();
+
+        this.mRequirements.clear(); // makes sure report isn't submitted twice
+    }
+}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassReportLog.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassReportLog.java
deleted file mode 100644
index 761c276..0000000
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassReportLog.java
+++ /dev/null
@@ -1,141 +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 Licnse.
- */
-
-package android.mediapc.cts.common;
-
-import static android.os.Build.VERSION.MEDIA_PERFORMANCE_CLASS;
-
-import android.os.Build.VERSION_CODES;
-
-import com.google.common.truth.Truth;
-
-import org.junit.Assume;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Logs a set of measurements and results for defined performance class requirements.
- */
-public class PerformanceClassReportLog {
-    private final Set<Requirement> mRequirements = new HashSet<>();
-
-    public void writeResults() {
-    }
-
-    public void checkDeclaredPerformanceClass() {
-        Assume.assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared",
-                MEDIA_PERFORMANCE_CLASS > 0);
-        for (Requirement r : mRequirements) {
-            Truth.assertThat(r.meetsPerformanceClass(MEDIA_PERFORMANCE_CLASS)).isTrue();
-        }
-    }
-
-    private <R extends Requirement> R addRequirement(R r) {
-        if (!mRequirements.add(r)) {
-            throw new IllegalStateException("Requirement " + r.getId() + " already added");
-        }
-        return r;
-    }
-
-
-     // Requirements are specified here in alphabetical order.
-
-    /**
-     * [5.1/H-1-1] MUST advertise the maximum number of hardware video decoder sessions that can
-     * be run concurrently in any codec combination via the
-     * CodecCapabilities.getMaxSupportedInstances() and
-     * VideoCapabilities.getSupportedPerformancePoints() methods.
-     */
-    public static final class R5_1_H1_1_1 extends Requirement {
-        private final RequiredMeasurement<Integer> maxSupportedCodecInstances = RequiredMeasurement
-                .builder(Integer.class)
-                .setId("codec_max_supported_instances")
-                .setMeetsRequirementPredicate(RequiredMeasurement.gte())
-                .addExpectedValue(VERSION_CODES.R, 1)
-                .build();
-        private final RequiredMeasurement<Integer> mSupportedPerformancePoints = RequiredMeasurement
-                .builder(Integer.class)
-                .setMeetsRequirementPredicate(RequiredMeasurement.gte())
-                .addExpectedValue(VERSION_CODES.R, 1)
-                .setId("supported_performance_points")
-                .build();
-
-        public R5_1_H1_1_1() {
-            super("5.1/H-1-1");
-            mRequiredMeasurements.add(maxSupportedCodecInstances);
-            mRequiredMeasurements.add(mSupportedPerformancePoints);
-        }
-
-        public void setMaxSupportedCodecInstances(int maxSupportedCodecInstances) {
-            this.maxSupportedCodecInstances.setMeasuredValue(maxSupportedCodecInstances);
-        }
-
-        public void setSupportedPerformancePoints(int supportedPerformancePoints) {
-            mSupportedPerformancePoints.setMeasuredValue(supportedPerformancePoints);
-        }
-    }
-
-    public R5_1_H1_1_1 addReqR_1_H1_1_1() {
-        R5_1_H1_1_1 r = new R5_1_H1_1_1();
-        addRequirement(r);
-        return r;
-    }
-
-    /**
-     * [7.6.1/H-1-1] MUST have at least 6 GB of physical memory.
-     */
-    public SingleRequirement<Long> addR7_6_1_H1_1() {
-        RequiredMeasurement physical_memory = RequiredMeasurement
-                .builder(Long.class)
-                .setId("physical_memory_mb")
-                .setMeetsRequirementPredicate(RequiredMeasurement.gte())
-                // Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB
-                // as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device.
-                .addExpectedValue(VERSION_CODES.R, 5L * 1024L)
-                .build();
-        return addRequirement(new SingleRequirement<Long>("7.6.1/H-1-1]", physical_memory));
-    }
-
-    /**
-     * [7.6.1/H-2-1] MUST have at least 6 GB of physical memory.
-     */
-    public SingleRequirement<Long> addR7_6_1_H2_1() {
-        RequiredMeasurement physical_memory = RequiredMeasurement
-                .builder(Long.class)
-                .setId("physical_memory_mb")
-                .setMeetsRequirementPredicate(RequiredMeasurement.gte())
-                // Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB
-                // as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device.
-                .addExpectedValue(VERSION_CODES.R, 5L * 1024L)
-                .build();
-        return addRequirement(new SingleRequirement<Long>("7.6.1/H-1-1]", physical_memory));
-    }
-
-    /**
-     * [7.6.1/H-2-1] MUST have at least 8 GB of physical memory.
-     */
-    public SingleRequirement<Long> addR7_6_1_H3_1() {
-        RequiredMeasurement physical_memory = RequiredMeasurement
-                .builder(Long.class)
-                .setId("physical_memory_mb")
-                .setMeetsRequirementPredicate(RequiredMeasurement.LONG_GTE)
-                // Android T Media performance requires 8 GB min RAM, so setting lower as above
-                .addExpectedValue(VERSION_CODES.TIRAMISU, 7L * 1024L)
-                .build();
-        return new SingleRequirement<Long>("7.6.1/H-1-1]", physical_memory);
-    }
-}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
index dab0111..92d3bff 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
@@ -16,9 +16,14 @@
 
 package android.mediapc.cts.common;
 
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.ImmutableMap;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.function.BiPredicate;
 
 /**
@@ -26,80 +31,97 @@
  */
 @AutoValue
 public abstract class RequiredMeasurement<T> {
+    private static final String TAG = RequiredMeasurement.class.getSimpleName();
 
-    private T mMeasuredValue;  // Note this is not part of the equals calculations
+    private T measuredValue;  // Note this is not part of the equals calculations
 
-    public void setMeasuredValue(T measuredValue) {
-        mMeasuredValue = measuredValue;
-    }
-
-    static <T> Builder<T> builder(Class<T> clazz) {
-        return new AutoValue_RequiredMeasurement.Builder<>();
+    public static <T> Builder<T> builder() {
+        return new AutoValue_RequiredMeasurement.Builder<T>();
     }
 
     public abstract String id();
 
     /**
      * Tests if the measured value satisfies the  expected value(eg >=)
-     *
      * measuredValue, expectedValue
      */
-    public abstract BiPredicate<T, T> meetsRequirementPredicate();
-
+    public abstract BiPredicate<T, T> predicate();
 
     /**
      * Maps MPC level to the expected value.
      */
     public abstract ImmutableMap<Integer, T> expectedValues();
 
-
-    public final Requirement.Result meetsPerformanceClass(
-            int mediaPerformanceClass) {
-        if (!expectedValues().containsKey(mediaPerformanceClass)) {
-            return Requirement.Result.NA;
-        }
-        return mMeasuredValue == null || !meetsRequirementPredicate().test(mMeasuredValue,
-                expectedValues().get(mediaPerformanceClass))
-                ? Requirement.Result.UNMET
-                : Requirement.Result.MET;
+    public void setMeasuredValue(T measuredValue) {
+        this.measuredValue = measuredValue;
     }
 
     @AutoValue.Builder
-    public abstract static class Builder<T> {
+    public static abstract class Builder<T> {
 
         public abstract Builder<T> setId(String id);
 
-        public abstract Builder<T> setMeetsRequirementPredicate(BiPredicate<T, T> predicate);
+        public abstract Builder<T> setPredicate(BiPredicate<T, T> predicate);
 
         public abstract ImmutableMap.Builder<Integer, T> expectedValuesBuilder();
 
-        public final Builder<T> addExpectedValue(Integer performanceClass, T expectedValue) {
-            expectedValuesBuilder().put(performanceClass, expectedValue);
+        public Builder<T> addRequiredValue(Integer performanceClass, T expectedValue) {
+            this.expectedValuesBuilder().put(performanceClass, expectedValue);
             return this;
         }
 
         public abstract RequiredMeasurement<T> build();
     }
 
-    public static final BiPredicate<Long, Long> LONG_GTE = RequiredMeasurement.gte();
-
-    /**
-     * Creates a >= predicate.
-     *
-     * This is convenience method to get the types right.
-     */
-    public static <T, S extends Comparable<T>> BiPredicate<S, T> gte() {
-        return new BiPredicate<S, T>() {
-            @Override
-            public boolean test(S actual, T expected) {
-                return actual.compareTo(expected) >= 0;
-            }
-
-            @Override
-            public String toString() {
-                return "Greater than or equal to";
-            }
-        };
+    private final RequirementConstants.Result meetsPerformanceClass(int mediaPerformanceClass) {
+        if (!this.expectedValues().containsKey(mediaPerformanceClass)) {
+            return RequirementConstants.Result.NA;
+        } else if (this.measuredValue == null || !this.predicate().test(this.measuredValue,
+                this.expectedValues().get(mediaPerformanceClass))) {
+            return RequirementConstants.Result.UNMET;
+        } else {
+            return RequirementConstants.Result.MET;
+        }
     }
 
+    /**
+     * @return map PerfomenaceClass to result if that performance class has been met
+     */
+    public Map<Integer, RequirementConstants.Result> getPerformanceClass() {
+        Map<Integer, RequirementConstants.Result> perfClassResults = new HashMap<>();
+        for (Integer pc: this.expectedValues().keySet()) {
+            perfClassResults.put(pc, this.meetsPerformanceClass(pc));
+        }
+        return perfClassResults;
+    }
+
+    @Override
+    public final String toString() {
+        return "Required Measurement with:"
+            + "\n\tId: " + this.id()
+            + "\n\tPredicate: " + this.predicate()
+            + "\n\tMeasured Value: " + this.measuredValue
+            + "\n\tExpected Values: " + this.expectedValues();
+    }
+
+    public void writeValue(DeviceReportLog log) {
+        if (this.measuredValue instanceof Integer) {
+            log.addValue(this.id(), (int)this.measuredValue, ResultType.NEUTRAL, ResultUnit.NONE);
+        } else if (this.measuredValue instanceof Long) {
+            log.addValue(this.id(), (long)this.measuredValue, ResultType.NEUTRAL, ResultUnit.NONE);
+        } else if (this.measuredValue instanceof Double) {
+            log.addValue(this.id(), (double)this.measuredValue, ResultType.NEUTRAL,
+                ResultUnit.NONE);
+        } else if (this.measuredValue instanceof Boolean) {
+            log.addValue(this.id(), (boolean)this.measuredValue, ResultType.NEUTRAL,
+                ResultUnit.NONE);
+        } else if (this.measuredValue instanceof String) {
+            log.addValue(this.id(), (String)this.measuredValue, ResultType.NEUTRAL,
+                ResultUnit.NONE);
+        } else {
+            // reporting all other types as Strings using toString()
+            log.addValue(this.id(), this.measuredValue.toString(), ResultType.NEUTRAL,
+                ResultUnit.NONE);
+        }
+    }
 }
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
index d3609f1..10ec1e6 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
@@ -16,39 +16,120 @@
 
 package android.mediapc.cts.common;
 
-import java.util.HashSet;
-import java.util.Set;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Performance Class Requirement maps and req id to a set of {@link RequiredMeasurement}.
  */
 public abstract class Requirement {
-    final Set<RequiredMeasurement<?>>
-            mRequiredMeasurements = new HashSet<>();
-    private final String id;
+    private static final String TAG = Requirement.class.getSimpleName();
 
-    Requirement(String id) {
+    protected final ImmutableMap<String, RequiredMeasurement<?>> mRequiredMeasurements;
+    protected final String id;
+
+    protected Requirement(String id, RequiredMeasurement<?>[] reqs) {
         this.id = id;
+
+        ImmutableMap.Builder<String, RequiredMeasurement<?>> reqBuilder =
+            ImmutableMap.<String, RequiredMeasurement<?>>builder();
+        for (RequiredMeasurement<?> r: reqs) {
+            reqBuilder.put(r.id(), r);
+        }
+        this.mRequiredMeasurements = reqBuilder.build();
     }
 
-    public String getId() {
-        return id;
+    public String id() {
+        return this.id;
     }
 
     /**
-     * Are all required values either NA or MET at this mediaPerformanceClass
+     * Finds the highest performance class where at least one RequiremdMeasurement has result
+     * RequirementConstants.Result.MET and none have RequirementConstants.Result.UNMET
      */
-    public boolean meetsPerformanceClass(int mediaPerformanceClass) {
-        for (RequiredMeasurement<?> rv : mRequiredMeasurements) {
-            if (rv.meetsPerformanceClass(mediaPerformanceClass)
-                    == Result.UNMET) {
-                return false;
+    @VisibleForTesting
+    protected int computePerformanceClass() {
+        Map<Integer, RequirementConstants.Result> overallPerfClassResults = new HashMap<>();
+
+        for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) {
+            Map<Integer, RequirementConstants.Result> perfClassResults = rm.getPerformanceClass();
+
+            for (Integer pc: perfClassResults.keySet()) {
+                RequirementConstants.Result res = perfClassResults.get(pc);
+
+                // if one or more results are UNMET, mark the performance class as UNMET
+                // otherwise if at least 1 of the results is MET, mark the performance class as MET
+                if (res == RequirementConstants.Result.UNMET) {
+                    overallPerfClassResults.put(pc, RequirementConstants.Result.UNMET);
+                } else if (!overallPerfClassResults.containsKey(pc) &&
+                        res == RequirementConstants.Result.MET) {
+                    overallPerfClassResults.put(pc, RequirementConstants.Result.MET);
+                }
             }
         }
-        return true;
+
+        // report the highest performance class that has been MET
+        int perfClass = 0;
+        for (int pc: overallPerfClassResults.keySet()) {
+            if (overallPerfClassResults.get(pc) == RequirementConstants.Result.MET) {
+                perfClass = Math.max(perfClass, pc);
+            }
+        }
+        return perfClass;
     }
 
-    public enum Result {
-        NA, MET, UNMET
+    @VisibleForTesting
+    protected boolean checkPerformanceClass(String testName, int reportPerfClass,
+            int expectedPerfClass) {
+        if (reportPerfClass < expectedPerfClass) {
+            Log.w(Requirement.TAG, "Test: " + testName + " reporting invalid performance class " +
+                reportPerfClass + " for requirement " + this.id + " performance class should at " +
+                "least be: " + expectedPerfClass);
+            for (RequiredMeasurement<?> rm: this.mRequiredMeasurements.values()) {
+                Log.w(Requirement.TAG, rm.toString());
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    private boolean checkPerformanceClass(String testName, int reportPerfClass) {
+        return this.checkPerformanceClass(testName, reportPerfClass, Utils.getPerfClass());
+    }
+
+    protected <T> void setMeasuredValue(String measurement, T measuredValue) {
+        RequiredMeasurement<T> rm =
+            (RequiredMeasurement<T>)this.mRequiredMeasurements.get(measurement);
+        rm.setMeasuredValue(measuredValue);
+    }
+
+    /**
+     * @return whether or not the requirement meets the device's specified performance class
+     */
+    public boolean writeLogAndCheck(String testName) {
+        int perfClass = this.computePerformanceClass();
+
+        DeviceReportLog log = new DeviceReportLog(RequirementConstants.REPORT_LOG_NAME, this.id);
+        log.addValue(RequirementConstants.TN_FIELD_NAME, testName, ResultType.NEUTRAL,
+            ResultUnit.NONE);
+        for (RequiredMeasurement rm: this.mRequiredMeasurements.values()) {
+            rm.writeValue(log);
+        }
+        log.addValue(RequirementConstants.PC_FIELD_NAME, perfClass, ResultType.NEUTRAL,
+            ResultUnit.NONE);
+        log.submit(InstrumentationRegistry.getInstrumentation());
+
+        return this.checkPerformanceClass(testName, perfClass);
     }
 }
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
new file mode 100644
index 0000000..e67656f
--- /dev/null
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -0,0 +1,119 @@
+/*
+ * 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 Licnse.
+ */
+
+package android.mediapc.cts.common;
+
+import android.os.Build;
+
+import java.util.function.BiPredicate;
+
+public class RequirementConstants {
+    private static final String TAG = RequirementConstants.class.getSimpleName();
+
+    public static final String REPORT_LOG_NAME = "CtsMediaPerformanceClassTestCases";
+    public static final String TN_FIELD_NAME = "test_name";
+    public static final String PC_FIELD_NAME = "performance_class";
+
+    public static final String R5_1__H_1_1 = "r5_1__h_1_1"; // 5.1/H-1-1
+    public static final String R5_1__H_1_2 = "r5_1__h_1_2"; // 5.1/H-1-2
+    public static final String R5_1__H_1_3 = "r5_1__h_1_3"; // 5.1/H-1-3
+    public static final String R5_1__H_1_4 = "r5_1__h_1_4"; // 5.1/H-1-4
+    public static final String R5_1__H_1_5 = "r5_1__h_1_5"; // 5.1/H-1-5
+    public static final String R5_1__H_1_6 = "r5_1__h_1_6"; // 5.1/H-1-6
+    public static final String R5_1__H_1_7 = "r5_1__h_1_7"; // 5.1/H-1-7
+    public static final String R5_1__H_1_8 = "r5_1__h_1_8"; // 5.1/H-1-8
+    public static final String R5_3__H_1_1 = "r5_3__h_1_1"; // 5.3/H-1-1
+    public static final String R5_3__H_1_2 = "r5_3__h_1_2"; // 5.3/H-1-2
+    public static final String R5_6__H_1_1 = "r5_6__h_1_1"; // 5.6/H-1-1
+    public static final String R7_5__H_1_1 = "r7_5__h_1_1"; // 7.5/H-1-1
+    public static final String R7_5__H_1_2 = "r7_5__h_1_2"; // 7.5/H-1-2
+    public static final String R7_5__H_1_3 = "r7_5__h_1_3"; // 7.5/H-1-3
+    public static final String R7_5__H_1_4 = "r7_5__h_1_4"; // 7.5/H-1-4
+    public static final String R7_5__H_1_5 = "r7_5__h_1_5"; // 7.5/H-1-5
+    public static final String R7_5__H_1_6 = "r7_5__h_1_6"; // 7.5/H-1-6
+    public static final String R7_5__H_1_7 = "r7_5__h_1_7"; // 7.5/H-1-7
+    public static final String R7_5__H_1_8 = "r7_5__h_1_8"; // 7.5/H-1-8
+    public static final String R7_1_1_1__H_1_1 = "r7_1_1_1__h_1_1"; // 7.1.1.1/H-1-1
+    public static final String R7_1_1_3__H_1_1 = "r7_1_1_3__h_1_1"; // 7.1.1.3/H-1-1
+    public static final String R7_6_1__H_1_1 = "r7_6_1__h_1_1"; // 7.6.1/H-1-1
+    public static final String R7_1_1_1__H_2_1 = "r7_1_1_1__h_2_1"; // 7.1.1.1/H-2-1
+    public static final String R7_1_1_3__H_2_1 = "r7_1_1_3__h_2_1"; // 7.1.1.3/H-2-1
+    public static final String R7_6_1__H_2_1 = "r7_6_1__h_2_1"; // 7.6.1/H-2-1
+    public static final String R7_6_1__H_3_1 = "r7_6_1__h_3_1"; // 7.6.1/H-3-1
+    public static final String R8_2__H_1_1 = "r8_2__h_1_1"; // 8.2/H-1-1
+    public static final String R8_2__H_1_2 = "r8_2__h_1_2"; // 8.2/H-1-2
+    public static final String R8_2__H_1_3 = "r8_2__h_1_3"; // 8.2/H-1-3
+    public static final String R8_2__H_1_4 = "r8_2__h_1_4"; // 8.2/H-1-4
+    public static final String R8_2__H_2_1 = "r8_2__h_2_1"; // 8.2/H-2-1
+    public static final String R8_2__H_2_2 = "r8_2__h_2_2"; // 8.2/H-2-2
+    public static final String R8_2__H_2_3 = "r8_2__h_2_3"; // 8.2/H-2-3
+    public static final String R8_2__H_2_4 = "r8_2__h_2_4"; // 8.2/H-2-4
+
+    public static final String MAX_CONCURRENT_SESSIONS = "max_concurrent_sessions";
+    public static final String SUPPORTED_PERFORMANCE_POINTS = "supported_performance_points";
+    public static final String FRAMES_DROPPED = "frame_drops_per_30sec";
+    public static final String FRAME_RATE = "frame_rate";
+    public static final String LONG_RESOLUTION = "long_resolution_pixels";
+    public static final String SHORT_RESOLUTION = "short_resolution_pixels";
+    public static final String DISPLAY_DENSITY = "display_density_dpi";
+    public static final String PHYSICAL_MEMORY = "physical_memory_mb";
+
+    public enum Result {
+        NA, MET, UNMET
+    }
+
+    public static final BiPredicate<Long, Long> LONG_GTE = RequirementConstants.gte();
+    public static final BiPredicate<Integer, Integer> INTEGER_GTE = RequirementConstants.gte();
+    public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte();
+
+    /**
+     * Creates a >= predicate.
+     *
+     * This is convenience method to get the types right.
+     */
+    private static <T, S extends Comparable<T>> BiPredicate<S, T> gte() {
+        return new BiPredicate<S, T>() {
+            @Override
+            public boolean test(S actual, T expected) {
+                return actual.compareTo(expected) >= 0;
+            }
+
+            @Override
+            public String toString() {
+                return "Greater than or equal to";
+            }
+        };
+    }
+
+    /**
+     * Creates a <= predicate.
+     */
+    private static <T, S extends Comparable<T>> BiPredicate<S, T> lte() {
+        return new BiPredicate<S, T>() {
+            @Override
+            public boolean test(S actual, T expected) {
+                return actual.compareTo(expected) <= 0;
+            }
+
+            @Override
+            public String toString() {
+                return "Less than or equal to";
+            }
+        };
+    }
+
+    private RequirementConstants() {} // class should not be instantiated
+}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/SingleRequirement.java b/tests/mediapc/common/src/android/mediapc/cts/common/SingleRequirement.java
deleted file mode 100644
index 079ad2b..0000000
--- a/tests/mediapc/common/src/android/mediapc/cts/common/SingleRequirement.java
+++ /dev/null
@@ -1,35 +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.mediapc.cts.common;
-
-/**
- * A requirement that has only one {@link RequiredMeasurement}.
- */
-public final class SingleRequirement<T> extends Requirement {
-    private final RequiredMeasurement<T> mRequiredMeasurement;
-
-    public SingleRequirement(String id,
-            RequiredMeasurement<T> requiredMeasurement) {
-        super(id);
-        mRequiredMeasurements.add(requiredMeasurement);
-        mRequiredMeasurement = requiredMeasurement;
-    }
-
-    public void setValue(T value) {
-        mRequiredMeasurement.setMeasuredValue(value);
-    }
-}
diff --git a/tests/mediapc/src/android/mediapc/cts/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
similarity index 98%
rename from tests/mediapc/src/android/mediapc/cts/Utils.java
rename to tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
index 6ad6146..a5484ff 100644
--- a/tests/mediapc/src/android/mediapc/cts/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.mediapc.cts;
+package android.mediapc.cts.common;
 
 import static android.util.DisplayMetrics.DENSITY_400;
 import static org.junit.Assume.assumeTrue;
@@ -36,7 +36,7 @@
 /**
  * Test utilities.
  */
-/* package private */ class Utils {
+public class Utils {
     private static final int sPc;
 
     private static final String TAG = "PerformanceClassTestUtils";
diff --git a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
new file mode 100644
index 0000000..b330724
--- /dev/null
+++ b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.mediapc.cts.common;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Build;
+
+import org.junit.Test;
+
+public class RequirementTest {
+    public static class TestReq extends Requirement {
+        private TestReq(String id, RequiredMeasurement<?> ... reqs) {
+            super(id, reqs);
+        }
+
+        public void setGTEMeasurement(int measure) {
+            this.<Integer>setMeasuredValue("test_measurement_1", measure);
+        }
+
+        public void setLTEMeasurement(int measure) {
+            this.<Integer>setMeasuredValue("test_measurement_2", measure);
+        }
+
+        public static TestReq create() {
+            RequiredMeasurement<Integer> measurement1 = RequiredMeasurement
+                .<Integer>builder()
+                .setId("test_measurement_1")
+                .setPredicate(RequirementConstants.INTEGER_GTE)
+                .addRequiredValue(Build.VERSION_CODES.R, 200)
+                .addRequiredValue(Build.VERSION_CODES.S, 300)
+                .build();
+            RequiredMeasurement<Integer> measurement2 = RequiredMeasurement
+                .<Integer>builder()
+                .setId("test_measurement_2")
+                .setPredicate(RequirementConstants.INTEGER_LTE)
+                .addRequiredValue(Build.VERSION_CODES.R, 500)
+                .addRequiredValue(Build.VERSION_CODES.S, 300)
+                .build();
+
+            return new TestReq("TestReq", measurement1, measurement2);
+        }
+    }
+
+    // used as a base for computePerformanceClass_testCase methods
+    private void testComputePerformanceClass(int gteMeasure, int lteMeasure, int expectedPC) {
+        TestReq testReq = TestReq.create();
+        int pc;
+
+        // both measurements do not meet R
+        testReq.setGTEMeasurement(gteMeasure);
+        testReq.setLTEMeasurement(lteMeasure);
+        pc = testReq.computePerformanceClass();
+        assertThat(pc).isEqualTo(expectedPC);
+    }
+
+    @Test
+    public void computePerformanceClass_bothNotR() {
+        // both measurements do not meet R
+        this.testComputePerformanceClass(100, 600, 0);
+    }
+
+    @Test
+    public void computePerformanceClass_onlyOneR() {
+        // one measurement does not meet R
+        this.testComputePerformanceClass(200, 600, 0);
+    }
+
+    @Test
+    public void computePerformanceClass_bothR() {
+        // both measurements meet R
+        this.testComputePerformanceClass(200, 500, Build.VERSION_CODES.R);
+    }
+
+    @Test
+    public void computePerformanceClass_onlyOneS() {
+        // one measurements does not meet S
+        this.testComputePerformanceClass(200, 100, Build.VERSION_CODES.R);
+    }
+
+    @Test
+    public void computePerformanceClass_bothS() {
+        // both measurements meet S
+        this.testComputePerformanceClass(500, 100, Build.VERSION_CODES.S);
+    }
+
+    // used as a base for checkPerformanceClass_testCase methods
+    private void testCheckPerformanceClass(int testPerfClass, boolean expectedResult) {
+        TestReq testReq = TestReq.create();
+        boolean perfClassMet;
+
+        perfClassMet = testReq.checkPerformanceClass("checkPerformanceClass", testPerfClass, 31);
+        assertThat(perfClassMet).isEqualTo(expectedResult);
+    }
+
+    @Test
+    public void checkPerformanceClass_justBelow() {
+        // just below required perfClass
+        int testPerfClass = 30;
+        this.testCheckPerformanceClass(testPerfClass, false);
+    }
+
+    @Test
+    public void checkPerformanceClass_justAt() {
+        // just at required perfClass
+        int testPerfClass = 31;
+        this.testCheckPerformanceClass(testPerfClass, true);
+    }
+
+    @Test
+    public void checkPerformanceClass_justAbove() {
+        // just above required perfClass
+        int testPerfClass = 32;
+        this.testCheckPerformanceClass(testPerfClass, true);
+    }
+}
\ No newline at end of file
diff --git a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
index 160fef7..6727a00 100644
--- a/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/AdaptivePlaybackFrameDropTest.java
@@ -16,7 +16,10 @@
 
 package android.mediapc.cts;
 
+import static org.junit.Assert.assertTrue;
+
 import android.media.MediaCodecInfo;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 
 import androidx.test.filters.LargeTest;
@@ -33,8 +36,6 @@
 
 import java.util.Collection;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class validates the frame drops of AdaptivePlayback for the hardware decoders
  * under the load condition (Transcode + Audio Playback).
diff --git a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
index 9168e24..ae09b14 100644
--- a/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/EncoderInitializationLatencyTest.java
@@ -18,6 +18,7 @@
 
 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;
@@ -31,6 +32,7 @@
 import android.media.MediaCodecList;
 import android.media.MediaFormat;
 import android.media.MediaRecorder;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Log;
 import android.util.Pair;
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
index 60bc7a7..0bf31d7 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTest.java
@@ -16,6 +16,9 @@
 
 package android.mediapc.cts;
 
+import static org.junit.Assert.assertTrue;
+
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 
 import androidx.test.filters.LargeTest;
@@ -32,8 +35,6 @@
 
 import java.util.Collection;
 
-import static org.junit.Assert.assertTrue;
-
 /**
  * The following test class validates the frame drops of a playback for the hardware decoders
  * under the load condition (Transcode + Audio Playback).
diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
index 47eae77..66d2be0 100644
--- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java
@@ -16,7 +16,16 @@
 
 package android.mediapc.cts;
 
+import static android.mediapc.cts.CodecTestBase.selectCodecs;
+import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.util.Log;
 import android.view.Surface;
 
@@ -31,13 +40,6 @@
 import java.util.List;
 import java.util.Map;
 
-import static android.mediapc.cts.CodecTestBase.selectCodecs;
-import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
 public class FrameDropTestBase {
     private static final String LOG_TAG = FrameDropTestBase.class.getSimpleName();
     static final boolean[] boolStates = {false, true};
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
index d1b65b5..ec27bf9 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java
@@ -17,12 +17,14 @@
 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.mediapc.cts.common.Utils;
 import android.util.Log;
 import android.util.Pair;
 
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
index 4899f83..31c069f 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Pair;
 
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
index cbdd391..1c1aeea 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Pair;
 
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
index b9cc45d..edc2d6c 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Log;
 import android.util.Pair;
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
index 79a684e..3a2f1d9 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Log;
 import android.util.Pair;
diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
index 98c3183..d7d8445 100644
--- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.media.MediaFormat;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.Pair;
 import android.view.Surface;
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index 23760fc..8a4b732 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -17,9 +17,12 @@
 package android.mediapc.cts;
 
 import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback;
-import static android.mediapc.cts.Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
-import static android.mediapc.cts.Utils.MIN_MEMORY_PERF_CLASS_T_MB;
+import static android.mediapc.cts.common.Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
+import static android.mediapc.cts.common.Utils.MIN_MEMORY_PERF_CLASS_T_MB;
 import static android.util.DisplayMetrics.DENSITY_400;
+
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertTrue;
 
 import android.app.ActivityManager;
@@ -30,6 +33,8 @@
 import android.media.MediaDrm;
 import android.media.MediaFormat;
 import android.media.UnsupportedSchemeException;
+import android.mediapc.cts.common.PerformanceClassEvaluator;
+import android.mediapc.cts.common.Utils;
 import android.os.Build;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -44,7 +49,9 @@
 import com.android.compatibility.common.util.ResultUnit;
 
 import org.junit.Assume;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestName;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -58,6 +65,9 @@
     private static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
     static ArrayList<String> mMimeSecureSupport = new ArrayList<>();
 
+    @Rule
+    public final TestName mTestName = new TestName();
+
     static {
         mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AVC);
         mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
@@ -184,18 +194,14 @@
     }
 
     @Test
-    @CddTest(requirement="2.2.7.3/7.1.1.1,7.1.1.3,7.6.1/H-1-1,H-2-1")
-    public void testMinimumMemory() {
+    @CddTest(requirements={
+        "2.2.7.3/7.1.1.1/H-1-1",
+        "2.2.7.3/7.1.1.1/H-2-1",
+        "2.2.7.3/7.1.1.3/H-1-1",
+        "2.2.7.3/7.1.1.3/H-2-1",})
+    public void testMinimumResolutionAndDensity() {
         Context context = InstrumentationRegistry.getInstrumentation().getContext();
 
-        // Verify minimum screen density and resolution
-        assertMinDpiAndPixels(context, DENSITY_400, 1920, 1080);
-        // Verify minimum memory
-        assertMinMemoryMb(context);
-    }
-
-    /** Asserts that the given values conform to the specs in CDD */
-    private void assertMinDpiAndPixels(Context context, int minDpi, int minLong, int minShort) {
         // Verify display DPI. We only seem to be able to get the primary display.
         DisplayMetrics metrics = new DisplayMetrics();
         WindowManager windowManager =
@@ -205,52 +211,47 @@
         int longPix = Math.max(metrics.widthPixels, metrics.heightPixels);
         int shortPix = Math.min(metrics.widthPixels, metrics.heightPixels);
 
-        Log.i(TAG, String.format("minDpi=%d minSize=%dx%dpix", minDpi, minLong, minShort));
         Log.i(TAG, String.format("dpi=%d size=%dx%dpix", density, longPix, shortPix));
 
-        if (Utils.isPerfClass()) {
-            assertTrue("Display density " + density + " must be at least " + minDpi + "dpi",
-                    density >= minDpi);
-            assertTrue("Display resolution " + longPix + "x" + shortPix + "pix must be at least " +
-                            minLong + "x" + minShort + "pix",
-                    longPix >= minLong && shortPix >= minShort);
-        } else {
-            int pc = density >= minDpi && longPix >= minLong && shortPix >= minShort
-                    ? Build.VERSION_CODES.S : 0;
-            DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs",  "Display");
-            log.addValue("DisplayDensity", density, ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.addValue("ResolutionLong", longPix, ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.addValue("ResolutionShort", shortPix, ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.setSummary("CDD 2.2.7.3/7.1.1.1,7.1.1.3/H-1-1,H-2-1 performance_class", pc,
-                    ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.submit(InstrumentationRegistry.getInstrumentation());
-        }
+        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+        PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__h_1_1 = pce.addR7_1_1_1__H_1_1();
+        PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_1_1 = pce.addR7_1_1_3__H_1_1();
+        PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__h_2_1 = pce.addR7_1_1_1__H_2_1();
+        PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_2_1 = pce.addR7_1_1_3__H_2_1();
+
+        r7_1_1_1__h_1_1.setLongResolution(longPix);
+        r7_1_1_1__h_2_1.setLongResolution(longPix);
+        r7_1_1_1__h_1_1.setShortResolution(shortPix);
+        r7_1_1_1__h_2_1.setShortResolution(shortPix);
+
+        r7_1_1_3__h_1_1.setDisplayDensity(density);
+        r7_1_1_3__h_2_1.setDisplayDensity(density);
+
+        pce.submitAndCheck();
     }
 
-    /** Asserts that the given values conform to the specs in CDD 7.6.1 */
-    private void assertMinMemoryMb(Context context) {
+    @Test
+    @CddTest(requirements={
+        "2.2.7.3/7.6.1/H-1-1",
+        "2.2.7.3/7.6.1/H-2-1",
+        "2.2.7.3/7.6.1/H-3-1"})
+    public void testMinimumMemory() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+
+        // Verify minimum memory
         ActivityManager activityManager = context.getSystemService(ActivityManager.class);
         long totalMemoryMb = getTotalMemory(activityManager) / 1024 / 1024;
 
         Log.i(TAG, String.format("Total device memory = %,d MB", totalMemoryMb));
-        if (Utils.isPerfClass()) {
-            long minMb = Utils.isTPerfClass() ? MIN_MEMORY_PERF_CLASS_T_MB :
-                    Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
-            Log.i(TAG, String.format("Minimum required memory = %,d MB", minMb));
-            assertTrue(String.format("Does not meet minimum memory requirements (CDD 7.6.1)."
-                    + "Found = %d, Minimum = %d", totalMemoryMb, minMb), totalMemoryMb >= minMb);
-        } else {
-            int pc = 0;
-            if (totalMemoryMb >= MIN_MEMORY_PERF_CLASS_T_MB)
-                pc = Build.VERSION_CODES.TIRAMISU;
-            else if (totalMemoryMb >= MIN_MEMORY_PERF_CLASS_CANDIDATE_MB)
-                pc = Build.VERSION_CODES.S;
-            DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", "MinMemory");
-            log.addValue("MemoryMB", totalMemoryMb, ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.setSummary("CDD 2.2.7.3/7.6.1/H-1-1,H-2-1  performance_class", pc,
-                    ResultType.HIGHER_BETTER, ResultUnit.NONE);
-            log.submit(InstrumentationRegistry.getInstrumentation());
-        }
+
+        PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+        PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_1_1 = pce.addR7_6_1__H_1_1();
+        PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_2_1 = pce.addR7_6_1__H_2_1();
+
+        r7_6_1_h_1_1.setPhysicalMemory(totalMemoryMb);
+        r7_6_1_h_2_1.setPhysicalMemory(totalMemoryMb);
+
+        pce.submitAndCheck();
     }
 
     /**
diff --git a/tests/quickaccesswallet/AndroidManifest.xml b/tests/quickaccesswallet/AndroidManifest.xml
index 5c48a39..6f0b083 100755
--- a/tests/quickaccesswallet/AndroidManifest.xml
+++ b/tests/quickaccesswallet/AndroidManifest.xml
@@ -78,19 +78,6 @@
                  android:resource="@xml/quickaccesswallet_configuration"/>;
         </service>
 
-        <service android:name="android.quickaccesswallet.UseTargetActivityForQuickAccessWalletService"
-                 android:enabled="false"
-                 android:label="@string/app_name"
-                 android:icon="@drawable/android"
-                 android:permission="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE"
-                 android:exported="true">
-            <intent-filter>
-                <action android:name="android.service.quickaccesswallet.QuickAccessWalletService"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-            </intent-filter>
-            <meta-data android:name="android.quickaccesswallet"
-                       android:resource="@xml/quickaccesswallet_configuration_usetargetactivityforquickaccess"/>;
-        </service>
 
         <service android:name="android.quickaccesswallet.QuickAccessWalletDelegateTargetActivityService"
                  android:enabled="false"
@@ -103,7 +90,7 @@
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <meta-data android:name="android.quickaccesswallet"
-                       android:resource="@xml/quickaccesswallet_configuration_delegatetargetactivity"/>;
+                       android:resource="@xml/quickaccesswallet_configuration"/>
         </service>
 
 
diff --git a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_usetargetactivityforquickaccess.xml b/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_usetargetactivityforquickaccess.xml
deleted file mode 100644
index 9f91f02..0000000
--- a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_usetargetactivityforquickaccess.xml
+++ /dev/null
@@ -1,20 +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.
-  -->
-
-<quickaccesswallet-service
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:targetActivity="android.quickaccesswallet.QuickAccessWalletActivity"
-    android:useTargetActivityForQuickAccess="true"/>
\ No newline at end of file
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
index 03a817e..8a5d528 100755
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
+++ b/tests/quickaccesswallet/src/android/quickaccesswallet/cts/QuickAccessWalletClientTest.java
@@ -35,7 +35,6 @@
 import android.quickaccesswallet.QuickAccessWalletSettingsActivity;
 import android.quickaccesswallet.TestHostApduService;
 import android.quickaccesswallet.TestQuickAccessWalletService;
-import android.quickaccesswallet.UseTargetActivityForQuickAccessWalletService;
 import android.service.quickaccesswallet.GetWalletCardsError;
 import android.service.quickaccesswallet.GetWalletCardsRequest;
 import android.service.quickaccesswallet.GetWalletCardsResponse;
@@ -106,8 +105,6 @@
                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
         setServiceState(NoPermissionQuickAccessWalletService.class,
                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
-        setServiceState(UseTargetActivityForQuickAccessWalletService.class,
-                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
         setServiceState(QuickAccessWalletDelegateTargetActivityService.class,
                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
         TestQuickAccessWalletService.resetStaticFields();
@@ -141,31 +138,10 @@
     }
 
     @Test
-    public void testUseTargetActivityForQuickAccess_isFalse() {
-        QuickAccessWalletClient client = QuickAccessWalletClient.create(mContext);
-
-        assertThat(client.useTargetActivityForQuickAccess()).isFalse();
-    }
-
-    @Test
-    public void testUseTargetActivityForQuickAccess_serviceSpecifies_isTrue() {
-        setServiceState(UseTargetActivityForQuickAccessWalletService.class,
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
-        setServiceState(TestQuickAccessWalletService.class,
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
-
-        QuickAccessWalletClient client = QuickAccessWalletClient.create(mContext);
-
-        assertThat(client.useTargetActivityForQuickAccess()).isTrue();
-    }
-
-    @Test
     public void testGetWalletPendingIntent_serviceWithOverride_notNull_ableToSend()
             throws Exception {
         setServiceState(QuickAccessWalletDelegateTargetActivityService.class,
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
-        setServiceState(UseTargetActivityForQuickAccessWalletService.class,
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
         setServiceState(TestQuickAccessWalletService.class,
                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
index c9f1cf2..a99f176 100644
--- a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
@@ -60,7 +60,7 @@
         params = builder.build();
 
         assertTrue(Float.compare(0f, params.getAspectRatioFloat()) == 0);
-        assertNull(params.getActions());
+        assertTrue(params.getActions().isEmpty());
         assertNull(params.getSourceRectHint());
     }
 
diff --git a/tests/tests/bionic/Android.bp b/tests/tests/bionic/Android.bp
index e9b59d1..2a5a9fa 100644
--- a/tests/tests/bionic/Android.bp
+++ b/tests/tests/bionic/Android.bp
@@ -183,6 +183,7 @@
         "libtest_init_fini_order_root",
         "libtest_init_fini_order_root2",
         "libtest_invalid-empty_shdr_table",
+        "libtest_invalid-local-tls",
         "libtest_invalid-rw_load_segment",
         "libtest_invalid-textrels",
         "libtest_invalid-textrels2",
diff --git a/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java b/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
index 163bd057..14891e0 100644
--- a/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
+++ b/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
@@ -26,6 +26,7 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
@@ -92,7 +93,7 @@
 
         Log.d(TAG, "Enabling bluetooth adapter");
         UiAutomation auto = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        Set<String> permissions = auto.getAdoptedShellPermissions();
+        Set<String> permissions = new HashSet(auto.getAdoptedShellPermissions());
         Set<String> savedPermissions = Set.copyOf(permissions);
         permissions.add(android.Manifest.permission.NETWORK_SETTINGS);
         auto.adoptShellPermissionIdentity(permissions.toArray(new String[permissions.size()]));
@@ -129,7 +130,7 @@
 
         Log.d(TAG, "Disabling bluetooth adapter");
         UiAutomation auto = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        Set<String> permissions = auto.getAdoptedShellPermissions();
+        Set<String> permissions = new HashSet(auto.getAdoptedShellPermissions());
         Set<String> savedPermissions = Set.copyOf(permissions);
         permissions.add(android.Manifest.permission.NETWORK_SETTINGS);
         auto.adoptShellPermissionIdentity(permissions.toArray(new String[permissions.size()]));
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
index 431621b..191c4a2 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
@@ -151,7 +151,7 @@
 
         BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
 
-        assertNull(mBluetoothA2dp.getCodecStatus(testDevice));
+        assertThrows(SecurityException.class, () -> mBluetoothA2dp.getCodecStatus(testDevice));
         assertThrows(IllegalArgumentException.class, () -> {
             mBluetoothA2dp.getCodecStatus(null);
         });
@@ -163,14 +163,6 @@
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothA2dp);
 
-        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
-        BluetoothCodecConfig codecConfig = new BluetoothCodecConfig.Builder()
-                .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC)
-                .setCodecPriority(0)
-                .build();
-        mBluetoothA2dp.setCodecConfigPreference(testDevice, codecConfig);
-        assertNull(mBluetoothA2dp.getCodecStatus(testDevice));
         assertThrows(IllegalArgumentException.class, () -> {
             mBluetoothA2dp.setCodecConfigPreference(null, null);
         });
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
index 19b206f..54766fe 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -483,14 +483,21 @@
     public void test_requestControllerActivityEnergyInfo() {
         if (!mHasBluetooth) return;
 
-        BluetoothAdapter.OnBluetoothActivityEnergyInfoListener listener =
-                new BluetoothAdapter.OnBluetoothActivityEnergyInfoListener() {
+        BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback =
+                new BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback() {
                     @Override
-                    public void onBluetoothActivityEnergyInfo(BluetoothActivityEnergyInfo info) {}
+                    public void onBluetoothActivityEnergyInfoAvailable(
+                            BluetoothActivityEnergyInfo info) {
+                        assertNotNull(info);
+                    }
+
+                    @Override
+                    public void onBluetoothActivityEnergyInfoError(int errorCode) {}
                 };
+
         // Verify parameter
         assertThrows(NullPointerException.class,
-                () -> mAdapter.requestControllerActivityEnergyInfo(null, listener));
+                () -> mAdapter.requestControllerActivityEnergyInfo(null, callback));
     }
 
     public void test_clearBluetooth() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java
deleted file mode 100644
index e7f59b8..0000000
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth.cts;
-
-import static android.Manifest.permission.BLUETOOTH_ADVERTISE;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.bluetooth.le.AdvertisingSetCallback.ADVERTISE_SUCCESS;
-
-import android.app.UiAutomation;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.le.AdvertisingSet;
-import android.bluetooth.le.AdvertisingSetCallback;
-import android.bluetooth.le.AdvertisingSetParameters;
-import android.bluetooth.le.BluetoothLeAdvertiser;
-import android.content.pm.PackageManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.test.AndroidTestCase;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-public class BluetoothLeAdvertiserTest extends AndroidTestCase {
-    private static final int TIMEOUT_MS = 5000;
-    private static final AdvertisingSetParameters ADVERTISING_SET_PARAMETERS =
-            new AdvertisingSetParameters.Builder().setLegacyMode(true).build();
-
-    private boolean mHasBluetooth;
-    private UiAutomation mUiAutomation;
-    private BluetoothAdapter mAdapter;
-    private BluetoothLeAdvertiser mAdvertiser;
-    private TestAdvertisingSetCallback mCallback;
-
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_BLUETOOTH);
-        if (!mHasBluetooth) return;
-        mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE);
-
-        BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
-        mAdapter = manager.getAdapter();
-        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
-        mAdvertiser = mAdapter.getBluetoothLeAdvertiser();
-        mCallback = new TestAdvertisingSetCallback();
-    }
-
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mHasBluetooth) {
-            mAdvertiser.stopAdvertisingSet(mCallback);
-            assertTrue(mCallback.mAdvertisingSetStoppedLatch.await(TIMEOUT_MS,
-                    TimeUnit.MILLISECONDS));
-            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
-            mAdvertiser = null;
-            mAdapter = null;
-        }
-    }
-
-    public void test_startAdvertisingSetWithCallbackAndHandler() throws InterruptedException {
-        mAdvertiser.startAdvertisingSet(ADVERTISING_SET_PARAMETERS, null, null, null, null,
-                mCallback, new Handler(Looper.getMainLooper()));
-        assertTrue(mCallback.mAdvertisingSetStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(ADVERTISE_SUCCESS, mCallback.mAdvertisingSetStartedStatus.get());
-        assertNotNull(mCallback.mAdvertisingSet);
-    }
-
-
-    public void test_startAdvertisingSetWithDurationAndCallback() throws InterruptedException {
-        mAdvertiser.startAdvertisingSet(ADVERTISING_SET_PARAMETERS, null, null, null, null,
-                0, 0, mCallback);
-        assertTrue(mCallback.mAdvertisingSetStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(ADVERTISE_SUCCESS, mCallback.mAdvertisingSetStartedStatus.get());
-        assertNotNull(mCallback.mAdvertisingSet);
-    }
-
-
-    public void test_startAdvertisingSetWithDurationCallbackAndHandler()
-            throws InterruptedException {
-        mAdvertiser.startAdvertisingSet(ADVERTISING_SET_PARAMETERS, null, null, null, null,
-                0, 0, mCallback, new Handler(Looper.getMainLooper()));
-        assertTrue(mCallback.mAdvertisingSetStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        assertEquals(ADVERTISE_SUCCESS, mCallback.mAdvertisingSetStartedStatus.get());
-        assertNotNull(mCallback.mAdvertisingSet);
-    }
-
-    private static class TestAdvertisingSetCallback extends AdvertisingSetCallback {
-        public CountDownLatch mAdvertisingSetStartedLatch = new CountDownLatch(1);
-        public CountDownLatch mAdvertisingEnabledLatch = new CountDownLatch(1);
-        public CountDownLatch mAdvertisingDisabledLatch = new CountDownLatch(1);
-        public CountDownLatch mAdvertisingSetStoppedLatch = new CountDownLatch(1);
-
-        public AtomicInteger mAdvertisingSetStartedStatus = new AtomicInteger();
-        public AtomicInteger mAdvertisingEnabledStatus = new AtomicInteger();
-        public AtomicInteger mAdvertisingDisabledStatus = new AtomicInteger();
-
-        public AtomicReference<AdvertisingSet> mAdvertisingSet = new AtomicReference();
-
-        @Override
-        public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
-                int status) {
-            super.onAdvertisingSetStarted(advertisingSet, txPower, status);
-            mAdvertisingSetStartedStatus.set(status);
-            mAdvertisingSet.set(advertisingSet);
-            mAdvertisingSetStartedLatch.countDown();
-        }
-
-        @Override
-        public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
-                int status) {
-            super.onAdvertisingEnabled(advertisingSet, enable, status);
-            if (enable) {
-                mAdvertisingEnabledStatus.set(status);
-                mAdvertisingEnabledLatch.countDown();
-            } else {
-                mAdvertisingDisabledStatus.set(status);
-                mAdvertisingDisabledLatch.countDown();
-            }
-        }
-
-        @Override
-        public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
-            super.onAdvertisingSetStopped(advertisingSet);
-            mAdvertisingSetStoppedLatch.countDown();
-        }
-
-    }
-}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
index 45083c5..be7c80b 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
@@ -163,6 +163,26 @@
         assertEquals(octetsPerFrame, leAudioCodecConfig.getOctetsPerFrame());
     }
 
+    public void testGetMinOctetsPerFrame() {
+        final int minOctetsPerFrame = 100;
+        BluetoothLeAudioCodecConfig leAudioCodecConfig =
+                new BluetoothLeAudioCodecConfig.Builder()
+                    .setMinOctetsPerFrame(minOctetsPerFrame)
+                    .build();
+
+        assertEquals(minOctetsPerFrame, leAudioCodecConfig.getMinOctetsPerFrame());
+    }
+
+    public void testGetMaxOctetsPerFrame() {
+        final int maxOctetsPerFrame = 100;
+        BluetoothLeAudioCodecConfig leAudioCodecConfig =
+                new BluetoothLeAudioCodecConfig.Builder()
+                    .setMaxOctetsPerFrame(maxOctetsPerFrame)
+                    .build();
+
+        assertEquals(maxOctetsPerFrame, leAudioCodecConfig.getMaxOctetsPerFrame());
+    }
+
     public void testDescribeContents() {
         BluetoothLeAudioCodecConfig leAudioCodecConfig =
             new BluetoothLeAudioCodecConfig.Builder().build();
@@ -202,6 +222,8 @@
 
     public void testBuilderWithExistingObject() {
         final int octetsPerFrame = 100;
+        final int minOctectsPerFrame = 50;
+        final int maxOctectsPerFrame = 150;
         BluetoothLeAudioCodecConfig oriLeAudioCodecConfig =
             new BluetoothLeAudioCodecConfig.Builder()
                 .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
@@ -211,6 +233,8 @@
                 .setChannelCount(BluetoothLeAudioCodecConfig.CHANNEL_COUNT_2)
                 .setFrameDuration(BluetoothLeAudioCodecConfig.FRAME_DURATION_7500)
                 .setOctetsPerFrame(octetsPerFrame)
+                .setMinOctetsPerFrame(minOctectsPerFrame)
+                .setMaxOctetsPerFrame(maxOctectsPerFrame)
                 .build();
         BluetoothLeAudioCodecConfig toBuilderCodecConfig =
                 new BluetoothLeAudioCodecConfig.Builder(oriLeAudioCodecConfig).build();
@@ -227,5 +251,7 @@
         assertEquals(BluetoothLeAudioCodecConfig.FRAME_DURATION_7500,
                 toBuilderCodecConfig.getFrameDuration());
         assertEquals(octetsPerFrame, toBuilderCodecConfig.getOctetsPerFrame());
+        assertEquals(minOctectsPerFrame, toBuilderCodecConfig.getMinOctetsPerFrame());
+        assertEquals(maxOctectsPerFrame, toBuilderCodecConfig.getMaxOctetsPerFrame());
     }
 }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
index d13c2b7..36c1217 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
@@ -218,11 +218,11 @@
                                                 .adoptShellPermissionIdentity();
                                     }
                                     try {
-                                        mNetworkScan =
-                                                mTelephonyManager.requestNetworkScan(
-                                                        true, mNetworkScanRequest,
-                                                        AsyncTask.SERIAL_EXECUTOR,
-                                                        mNetworkScanCallback);
+                                        mNetworkScan = mTelephonyManager.requestNetworkScan(
+                                                TelephonyManager.INCLUDE_LOCATION_DATA_NONE,
+                                                mNetworkScanRequest,
+                                                AsyncTask.SERIAL_EXECUTOR,
+                                                mNetworkScanCallback);
                                         if (mNetworkScan == null) {
                                             mNetworkScanStatus = EVENT_SCAN_DENIED;
                                             setReady(true);
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index b78ccbe..f937a77 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -77,6 +77,25 @@
         "src/**/*.kt",
         "BinderPermissionTestService/**/I*.aidl",
     ],
+    required: [
+        "HelloWorld5",
+        "HelloWorld5Profileable",
+        "HelloWorld7",
+        "HelloWorldNoAppStorage",
+        "HelloWorldResHardening",
+        "HelloWorldSdk1",
+        "HelloWorldSdk1DifferentSigner",
+        "HelloWorldSdk1MajorVersion2",
+        "HelloWorldSdk1Updated",
+        "HelloWorldSdk2",
+        "HelloWorldSdk2Updated",
+        "HelloWorldSdk3UsingSdk1",
+        "HelloWorldSdk3UsingSdk1And2",
+        "HelloWorldShell",
+        "HelloWorldUsingSdk1",
+        "HelloWorldUsingSdk1And2",
+        "HelloWorldUsingSdk3",
+    ],
     data: [
         // v1/v2/v3/v4 signed version of android.appsecurity.cts.tinyapp to keep checksums stable
         "data/CtsPkgInstallTinyAppV1.apk",
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index 29d207e..dcd2fe6 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -16,6 +16,8 @@
 
 package android.content.cts;
 
+import static org.junit.Assert.assertArrayEquals;
+
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -29,6 +31,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.ServiceManager;
 import android.platform.test.annotations.AppModeFull;
 import android.provider.Contacts.People;
@@ -154,6 +157,34 @@
         assertEquals(expected, target);
     }
 
+    public void testGetParcelableArrayListExtraTypeSafe_withMismatchingType_returnsNull() {
+        final ArrayList<TestParcelable> original = new ArrayList<>();
+        original.add(new TestParcelable(0));
+        mIntent.putParcelableArrayListExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertNull(mIntent.getParcelableArrayListExtra(TEST_EXTRA_NAME, Intent.class));
+    }
+
+    public void testGetParcelableArrayListExtraTypeSafe_withMatchingType_returnsObject() {
+        final ArrayList<TestParcelable> original = new ArrayList<>();
+        original.add(new TestParcelable(0));
+        original.add(new TestParcelable(1));
+        mIntent.putParcelableArrayListExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertEquals(original,
+                mIntent.getParcelableArrayListExtra(TEST_EXTRA_NAME, TestParcelable.class));
+    }
+
+    public void testGetParcelableArrayListExtraTypeSafe_withBaseType_returnsObject() {
+        final ArrayList<TestParcelable> original = new ArrayList<>();
+        original.add(new TestParcelable(0));
+        original.add(new TestParcelable(1));
+        mIntent.putParcelableArrayListExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertEquals(original,
+                mIntent.getParcelableArrayListExtra(TEST_EXTRA_NAME, Parcelable.class));
+    }
+
     public void testFilterHashCode() {
         mIntent.filterHashCode();
     }
@@ -609,6 +640,23 @@
         assertEquals(expected, mIntent.getParcelableExtra(TEST_EXTRA_NAME));
     }
 
+    public void testGetParcelableExtraTypeSafe_withMismatchingType_returnsNull() {
+        mIntent.putExtra(TEST_EXTRA_NAME, new TestParcelable(42));
+        assertNull(mIntent.getParcelableExtra(TEST_EXTRA_NAME, Intent.class));
+    }
+
+    public void testGetParcelableExtraTypeSafe_withMatchingType_returnsObject() {
+        final TestParcelable original = new TestParcelable(42);
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        assertEquals(original, mIntent.getParcelableExtra(TEST_EXTRA_NAME, TestParcelable.class));
+    }
+
+    public void testGetParcelableExtraTypeSafe_withBaseType_returnsObject() {
+        final TestParcelable original = new TestParcelable(42);
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        assertEquals(original, mIntent.getParcelableExtra(TEST_EXTRA_NAME, Parcelable.class));
+    }
+
     public void testAccessAction() {
         mIntent.setAction(TEST_ACTION);
         assertEquals(TEST_ACTION, mIntent.getAction());
@@ -736,7 +784,29 @@
     public void testGetParcelableArrayExtra() {
         final Intent[] expected = { new Intent(TEST_ACTION), new Intent(mContext, MockActivity.class) };
         mIntent.putExtra(TEST_EXTRA_NAME, expected);
-        assertEquals(expected, mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME));
+        assertArrayEquals(expected, mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME));
+    }
+
+    public void testGetParcelableArrayExtraTypeSafe_withMismatchingType_returnsNull() {
+        mIntent.putExtra(TEST_EXTRA_NAME, new TestParcelable[] {new TestParcelable(42)});
+        roundtrip();
+        assertNull(mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME, Intent.class));
+    }
+
+    public void testGetParcelableArrayExtraTypeSafe_withMatchingType_returnsObject() {
+        final TestParcelable[] original = { new TestParcelable(1), new TestParcelable(2) };
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertArrayEquals(original,
+                mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME, TestParcelable.class));
+    }
+
+    public void testGetParcelableArrayExtraTypeSafe_withBaseType_returnsObject() {
+        final TestParcelable[] original = { new TestParcelable(1), new TestParcelable(2) };
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertArrayEquals(original,
+                mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME, Parcelable.class));
     }
 
     public void testResolveActivityEmpty() {
@@ -1811,6 +1881,26 @@
         assertEquals(expected.Name, target.Name);
     }
 
+    public void testGetSerializableExtraTypeSafe_withMismatchingType_returnsNull() {
+        mIntent.putExtra(TEST_EXTRA_NAME, new TestSerializable());
+        roundtrip();
+        assertNull(mIntent.getSerializableExtra(TEST_EXTRA_NAME, Long.class));
+    }
+
+    public void testGetSerializableExtraTypeSafe_withMatchingType_returnsObject() {
+        String original = "Hello, World!";
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertEquals(original, mIntent.getSerializableExtra(TEST_EXTRA_NAME, String.class));
+    }
+
+    public void testGetSerializableExtraTypeSafe_withBaseType_returnsObject() {
+        String original = "Hello, World!";
+        mIntent.putExtra(TEST_EXTRA_NAME, original);
+        roundtrip();
+        assertEquals(original, mIntent.getSerializableExtra(TEST_EXTRA_NAME, Serializable.class));
+    }
+
     public void testReplaceExtras() {
         Bundle extras = new Bundle();
         String bundleKey = "testKey";
@@ -1840,8 +1930,66 @@
         assertEquals("foo/bar", Intent.normalizeMimeType("   foo/bar    "));
     }
 
+    private void roundtrip() {
+        Parcel p = Parcel.obtain();
+        p.writeParcelable(mIntent, 0);
+        p.setDataPosition(0);
+        mIntent = p.readParcelable(getClass().getClassLoader(), Intent.class);
+        mIntent.setExtrasClassLoader(getClass().getClassLoader());
+    }
+
     private static class TestSerializable implements Serializable {
         static final long serialVersionUID = 1l;
         public String Name;
     }
+
+    private static class TestParcelable implements Parcelable {
+        public final int value;
+
+        TestParcelable(int value) {
+            this.value = value;
+        }
+
+        protected TestParcelable(Parcel in) {
+            value = in.readInt();
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(value);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (!(other instanceof TestParcelable)) {
+                return false;
+            }
+            TestParcelable that = (TestParcelable) other;
+            return value == that.value;
+        }
+
+        @Override
+        public int hashCode() {
+            return value;
+        }
+
+        public static final Creator<TestParcelable> CREATOR = new Creator<TestParcelable>() {
+            @Override
+            public TestParcelable createFromParcel(Parcel in) {
+                return new TestParcelable(in);
+            }
+            @Override
+            public TestParcelable[] newArray(int size) {
+                return new TestParcelable[size];
+            }
+        };
+    }
 }
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
index 38ca81d..2129f3b 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt
@@ -25,6 +25,8 @@
 import android.content.pm.PackageManager
 import android.content.pm.cts.PackageManagerShellCommandTest.FullyRemovedBroadcastReceiver
 import android.content.pm.cts.util.AbandonAllPackageSessionsRule
+import android.os.Handler
+import android.os.HandlerThread
 import android.platform.test.annotations.AppModeFull
 import androidx.test.InstrumentationRegistry
 import com.android.bedstead.harrier.BedsteadJUnit4
@@ -70,6 +72,8 @@
         private val context: Context = InstrumentationRegistry.getContext()
         private val uiAutomation: UiAutomation =
             InstrumentationRegistry.getInstrumentation().getUiAutomation()
+
+        private var backgroundThread = HandlerThread("PackageManagerShellCommandMultiUserTest")
     }
 
     private lateinit var primaryUser: UserReference
@@ -201,6 +205,10 @@
             "install-incremental"
         ) installTypeString: String
     ) {
+        if (!backgroundThread.isAlive) {
+            backgroundThread.start()
+        }
+        val backgroundHandler = Handler(backgroundThread.getLooper())
         installExistingPackageAsUser(context.packageName, secondaryUser)
         installPackage(TEST_HW5, installTypeString)
         assertTrue(isAppInstalledForUser(context.packageName, primaryUser))
@@ -215,7 +223,11 @@
         intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
         intentFilter.addDataScheme("package")
         context.registerReceiver(
-            broadcastReceiverForPrimaryUser, intentFilter, RECEIVER_EXPORTED
+            broadcastReceiverForPrimaryUser,
+            intentFilter,
+            null,
+            backgroundHandler,
+            RECEIVER_EXPORTED
         )
         uiAutomation.adoptShellPermissionIdentity(
             Manifest.permission.INTERACT_ACROSS_USERS,
@@ -223,21 +235,63 @@
         )
         try {
             context.createContextAsUser(secondaryUser.userHandle(), 0).registerReceiver(
-                broadcastReceiverForSecondaryUser, intentFilter, RECEIVER_EXPORTED
+                broadcastReceiverForSecondaryUser,
+                intentFilter,
+                null,
+                backgroundHandler,
+                RECEIVER_EXPORTED
             )
         } finally {
             uiAutomation.dropShellPermissionIdentity()
         }
         // Verify that uninstall with "keep data" doesn't send the broadcast
         uninstallPackageWithKeepData(TEST_APP_PACKAGE, secondaryUser)
-        assertFalse(broadcastReceiverForSecondaryUser.isBroadcastReceived)
+        broadcastReceiverForSecondaryUser.assertBroadcastNotReceived()
         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)
+        broadcastReceiverForSecondaryUser.assertBroadcastReceived()
+        broadcastReceiverForPrimaryUser.assertBroadcastNotReceived()
         uninstallPackageSilently(TEST_APP_PACKAGE)
-        assertTrue(broadcastReceiverForPrimaryUser.isBroadcastReceived)
+        broadcastReceiverForPrimaryUser.assertBroadcastReceived()
+    }
+
+    @Test
+    fun testListPackageDefaultAllUsers(
+        @StringTestParameter(
+            "install",
+            "install-streaming",
+            "install-incremental"
+        ) installTypeString: String
+    ) {
+        installPackageAsUser(TEST_HW5, primaryUser, installTypeString)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        assertFalse(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        var out = SystemUtil.runShellCommand(
+                    "pm list packages -U --user ${primaryUser.id()} $TEST_APP_PACKAGE"
+                ).replace("\n", "")
+        assertTrue(out.split(":").last().split(",").size == 1)
+        out = SystemUtil.runShellCommand(
+                    "pm list packages -U --user ${secondaryUser.id()} $TEST_APP_PACKAGE"
+                ).replace("\n", "")
+        assertEquals("", out)
+        out = SystemUtil.runShellCommand("pm list packages -U $TEST_APP_PACKAGE")
+                .replace("\n", "")
+        assertTrue(out.split(":").last().split(",").size == 1)
+        installExistingPackageAsUser(TEST_APP_PACKAGE, secondaryUser)
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, primaryUser))
+        assertTrue(isAppInstalledForUser(TEST_APP_PACKAGE, secondaryUser))
+        out = SystemUtil.runShellCommand("pm list packages -U $TEST_APP_PACKAGE")
+                .replace("\n", "")
+        assertTrue(out.split(":").last().split(",").size == 2)
+        out = SystemUtil.runShellCommand(
+                    "pm list packages -U --user ${primaryUser.id()} $TEST_APP_PACKAGE"
+                ).replace("\n", "")
+        assertTrue(out.split(":").last().split(",").size == 1)
+        out = SystemUtil.runShellCommand(
+                    "pm list packages -U --user ${secondaryUser.id()} $TEST_APP_PACKAGE"
+                ).replace("\n", "")
+        assertTrue(out.split(":").last().split(",").size == 1)
     }
 
     private fun getFirstInstallTimeAsUser(packageName: String, user: UserReference) =
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 d923ad7..ffe417c 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -61,7 +61,6 @@
 import android.content.pm.SigningInfo;
 import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
 import android.os.Bundle;
-import android.os.ConditionVariable;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
@@ -70,6 +69,7 @@
 import android.util.PackageUtils;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
 
 import com.android.internal.util.ConcurrentUtils;
 import com.android.internal.util.HexDump;
@@ -99,9 +99,13 @@
 import java.util.Optional;
 import java.util.Random;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 @RunWith(Parameterized.class)
@@ -1472,28 +1476,51 @@
         assertEquals(pm.getSdkSandboxPackageName(), names[0]);
     }
 
+    @LargeTest
+    @Test
+    public void testCreateUserCurAsType() throws Exception {
+        Pattern pattern = Pattern.compile("Success: created user id (\\d+)\\R*");
+        String commandResult = executeShellCommand("pm create-user --profileOf cur "
+                + "--user-type android.os.usertype.profile.CLONE test");
+        Matcher matcher = pattern.matcher(commandResult);
+        assertTrue(matcher.find());
+        commandResult = executeShellCommand("pm remove-user " + matcher.group(1));
+        assertEquals("Success: removed user\n", commandResult);
+        commandResult = executeShellCommand("pm create-user --profileOf current "
+                + "--user-type android.os.usertype.profile.CLONE test");
+        matcher = pattern.matcher(commandResult);
+        assertTrue(matcher.find());
+        commandResult = executeShellCommand("pm remove-user " + matcher.group(1));
+        assertEquals("Success: removed user\n", commandResult);
+    }
+
     static class FullyRemovedBroadcastReceiver extends BroadcastReceiver {
         private final String mTargetPackage;
         private final int mTargetUserId;
-        private final ConditionVariable mUserReceivedBroadcast;
+        private final CompletableFuture<Boolean> mUserReceivedBroadcast = new CompletableFuture<>();
         FullyRemovedBroadcastReceiver(String packageName, int targetUserId) {
             mTargetPackage = packageName;
             mTargetUserId = targetUserId;
-            mUserReceivedBroadcast = new ConditionVariable();
-            mUserReceivedBroadcast.close();
         }
         @Override
         public void onReceive(Context context, Intent intent) {
-            context.unregisterReceiver(this);
             final String packageName = intent.getData().getEncodedSchemeSpecificPart();
             final int userId = context.getUserId();
             if (intent.getAction().equals(Intent.ACTION_PACKAGE_FULLY_REMOVED)
                     && packageName.equals(mTargetPackage) && userId == mTargetUserId) {
-                mUserReceivedBroadcast.open();
+                mUserReceivedBroadcast.complete(true);
+                context.unregisterReceiver(this);
             }
         }
-        public boolean isBroadcastReceived() {
-            return mUserReceivedBroadcast.block(2000);
+        public void assertBroadcastReceived() throws Exception {
+            assertTrue(mUserReceivedBroadcast.get(2, TimeUnit.SECONDS));
+        }
+        public void assertBroadcastNotReceived() throws Exception {
+            try {
+                assertFalse(mUserReceivedBroadcast.get(2, TimeUnit.SECONDS));
+            } catch (TimeoutException ignored) {
+                // expected
+            }
         }
     }
 
diff --git a/tests/tests/display/src/android/display/cts/BrightnessTest.java b/tests/tests/display/src/android/display/cts/BrightnessTest.java
index 73d900f..59f008e 100644
--- a/tests/tests/display/src/android/display/cts/BrightnessTest.java
+++ b/tests/tests/display/src/android/display/cts/BrightnessTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNotNull;
 import static org.junit.Assume.assumeTrue;
 
 import android.Manifest;
@@ -262,6 +263,9 @@
 
     @Test
     public void testSetGetSimpleCurve() {
+        // 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 push curves.
         assumeTrue(numberOfSystemAppsWithPermission(
                 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) > 0);
@@ -269,6 +273,8 @@
         grantPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS);
 
         BrightnessConfiguration defaultConfig = mDisplayManager.getDefaultBrightnessConfiguration();
+        // This might be null, meaning that the device doesn't support brightness configuration
+        assumeNotNull(defaultConfig);
 
         BrightnessConfiguration config =
                 new BrightnessConfiguration.Builder(
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
index d05e231..291afc9 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationScreenLayoutTest.java
@@ -16,6 +16,10 @@
 
 package android.dpi.cts;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -27,7 +31,11 @@
 import android.view.Display;
 import android.view.WindowManager;
 
-import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class ConfigurationScreenLayoutTest
         extends ActivityInstrumentationTestCase2<OrientationActivity> {
@@ -43,6 +51,48 @@
         super(OrientationActivity.class);
     }
 
+    private static String executeShellCommand(String command) {
+        try {
+            return SystemUtil.runShellCommand(
+                    androidx.test.platform.app.InstrumentationRegistry.getInstrumentation(),
+                    command);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // Mirrored from ActivityManagerTestBase.java
+    public static class IgnoreOrientationRequestSession implements AutoCloseable {
+        private static final String WM_SET_IGNORE_ORIENTATION_REQUEST =
+                "wm set-ignore-orientation-request ";
+        private static final String WM_GET_IGNORE_ORIENTATION_REQUEST =
+                "wm get-ignore-orientation-request";
+        private static final Pattern IGNORE_ORIENTATION_REQUEST_PATTERN =
+                Pattern.compile("ignoreOrientationRequest (true|false) for displayId=\\d+");
+
+        final int mDisplayId;
+        final boolean mInitialIgnoreOrientationRequest;
+
+        IgnoreOrientationRequestSession(int displayId, boolean enable) {
+            mDisplayId = displayId;
+            Matcher matcher = IGNORE_ORIENTATION_REQUEST_PATTERN.matcher(
+                    executeShellCommand(WM_GET_IGNORE_ORIENTATION_REQUEST + " -d " + mDisplayId));
+            assertTrue("get-ignore-orientation-request should match pattern",
+                    matcher.find());
+            mInitialIgnoreOrientationRequest = Boolean.parseBoolean(matcher.group(1));
+
+            executeShellCommand("wm set-ignore-orientation-request " + (enable ? "true" : "false")
+                    + " -d " + mDisplayId);
+        }
+
+        @Override
+        public void close() {
+            executeShellCommand(
+                    WM_SET_IGNORE_ORIENTATION_REQUEST + mInitialIgnoreOrientationRequest + " -d "
+                            + mDisplayId);
+        }
+    }
+
     public void testScreenLayout() throws Exception {
         if (!supportsRotation()) {
             // test has no effect if device does not support rotation
@@ -57,26 +107,35 @@
             tearDown();
             return;
         }
-        int expectedScreenLayout = computeScreenLayout();
-        int expectedSize = expectedScreenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
-        int expectedLong = expectedScreenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
+        // Disable IgnoreOrientationRequest feature because when it's enabled, the device would only
+        // follow physical rotations.
+        try (IgnoreOrientationRequestSession session =
+                     new IgnoreOrientationRequestSession(DEFAULT_DISPLAY, false)) {
+            int expectedScreenLayout = computeScreenLayout();
+            int expectedSize = expectedScreenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+            int expectedLong = expectedScreenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
 
-        // Check that all four orientations report the same configuration value.
-        for (int i = 0; i < ORIENTATIONS.length; i++) {
-            Activity activity = startOrientationActivity(ORIENTATIONS[i]);
-            if (activity.isInMultiWindowMode()) {
-                // activity.setRequestedOrientation has no effect in multiwindow mode.
+            // Check that all four orientations report the same configuration value.
+            for (int i = 0; i < ORIENTATIONS.length; i++) {
+                Activity activity = startOrientationActivity(ORIENTATIONS[i]);
+                if (activity.isInMultiWindowMode()) {
+                    // activity.setRequestedOrientation has no effect in multiwindow mode.
+                    tearDown();
+                    return;
+                }
+                Configuration mConfig = activity.getResources().getConfiguration();
+                int actualSize = mConfig.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+                int actualLong = mConfig.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
+
+                assertEquals("Expected screen size value of " + expectedSize + " but got "
+                        + actualSize + " for orientation "
+                        + ORIENTATIONS[i], expectedSize, actualSize);
+                assertEquals("Expected screen long value of " + expectedLong + " but got "
+                        + actualLong + " for orientation "
+                        + ORIENTATIONS[i], expectedLong, actualLong);
                 tearDown();
-                return;
             }
-            Configuration mConfig = activity.getResources().getConfiguration();
-            int actualSize = mConfig.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
-            int actualLong = mConfig.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
-
-            assertEquals("Expected screen size value of " + expectedSize + " but got " + actualSize
-                    + " for orientation " + ORIENTATIONS[i], expectedSize, actualSize);
-            assertEquals("Expected screen long value of " + expectedLong + " but got " + actualLong
-                    + " for orientation " + ORIENTATIONS[i], expectedLong, actualLong);
+        } finally {
             tearDown();
         }
     }
@@ -102,7 +161,7 @@
     }
 
     private boolean hasDeviceFeature(final String requiredFeature) {
-        return InstrumentationRegistry.getContext()
+        return getInstrumentation().getContext()
                 .getPackageManager()
                 .hasSystemFeature(requiredFeature);
     }
diff --git a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
index 26edac3..f83a8cc 100644
--- a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
+++ b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
@@ -224,29 +224,10 @@
 
         launchAndWaitForPackage(GAME_PACKAGE_NAME);
 
-        Rect touchableBounds = waitForTouchableOverlayBounds();
+        waitForTouchableOverlayBounds();
 
-        Bitmap overlayScreenshot = Bitmap.createBitmap(
-                getInstrumentation().getUiAutomation().takeScreenshot(),
-                touchableBounds.left,
-                touchableBounds.top,
-                touchableBounds.width(),
-                touchableBounds.height());
-
-        // TODO(b/218901969): UI automator does not appear to have visibility into the overlay;
-        //                    therefore, it cannot be used to validate the overlay's contents.
-        //                    We should try and see if we can expose the overlay to UI automator in
-        //                    order to have a more foolproof validation check. We will use this
-        //                    magenta background check in the meantime.
-        // The overlay background is set to magenta. Verify that it has been rendered by checking
-        // the corners.
-        assertThat(overlayScreenshot.getPixel(0, 0)).isEqualTo(Color.MAGENTA);
-        assertThat(overlayScreenshot.getPixel(0, overlayScreenshot.getHeight() - 1)).isEqualTo(
-                Color.MAGENTA);
-        assertThat(overlayScreenshot.getPixel(overlayScreenshot.getWidth() - 1, 0)).isEqualTo(
-                Color.MAGENTA);
-        assertThat(overlayScreenshot.getPixel(overlayScreenshot.getWidth() - 1,
-                overlayScreenshot.getHeight() - 1)).isEqualTo(Color.MAGENTA);
+        assertThat(UiAutomatorUtils.getUiDevice().findObject(
+                By.text("Overlay was rendered on: " + GAME_PACKAGE_NAME))).isNotNull();
     }
 
     @Test
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java
index 7cf713f..eb54097 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java
@@ -16,6 +16,8 @@
 
 package android.hardware.input.cts.tests;
 
+import static org.junit.Assert.assertEquals;
+
 import android.graphics.PointF;
 import android.hardware.input.VirtualMouse;
 import android.hardware.input.VirtualMouseButtonEvent;
@@ -144,6 +146,30 @@
                         /* pressure= */ 0f)));
     }
 
+    @Test
+    public void getCursorPosition() {
+        // Trigger a position update without moving the cursor off the starting position.
+        mVirtualMouse.sendButtonEvent(new VirtualMouseButtonEvent.Builder()
+                .setAction(VirtualMouseButtonEvent.ACTION_BUTTON_PRESS)
+                .setButtonCode(VirtualMouseButtonEvent.BUTTON_PRIMARY)
+                .build());
+        final MotionEvent buttonPressEvent = createMotionEvent(MotionEvent.ACTION_BUTTON_PRESS,
+                START_POSITION.x, START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f,
+                /* vScroll= */ 0f, /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY,
+                /* pressure= */ 1.0f);
+        buttonPressEvent.setActionButton(MotionEvent.BUTTON_PRIMARY);
+        verifyEvents(Arrays.asList(
+                createMotionEvent(MotionEvent.ACTION_DOWN, START_POSITION.x, START_POSITION.y,
+                        /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f,
+                        /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY, /* pressure= */ 1.0f),
+                buttonPressEvent));
+
+        final PointF position = mVirtualMouse.getCursorPosition();
+
+        assertEquals("Cursor position x differs", START_POSITION.x, position.x, 0.0001f);
+        assertEquals("Cursor position y differs", START_POSITION.y, position.y, 0.0001f);
+    }
+
     private MotionEvent createMotionEvent(int action, float x, float y, float relativeX,
             float relativeY, float vScroll, float hScroll, int buttonState, float pressure) {
         final MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
diff --git a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
index 4fa15b8..e13f8da 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
@@ -22,26 +22,45 @@
 import static org.junit.Assert.fail;
 
 import android.content.Context;
-import android.keystore.cts.R;
 import android.keystore.cts.util.ImportedKey;
 import android.keystore.cts.util.TestUtils;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import java.security.KeyPair;
-import java.security.Security;
-import java.security.Signature;
-import java.util.Arrays;
-import java.util.Collection;
+import com.android.internal.util.HexDump;
 
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.ECGenParameterSpec;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
 @RunWith(AndroidJUnit4.class)
 public class ECDSASignatureTest {
 
+    private static final String TAG = "ECDSASignatureTest";
+
     private Context getContext() {
         return InstrumentationRegistry.getInstrumentation().getTargetContext();
     }
@@ -100,6 +119,116 @@
         }
     }
 
+    /* Duplicate nonces can leak the ECDSA private key, even if each nonce is only used once per
+     * keypair. See Brengel & Rossow 2018 ( https://doi.org/10.1007/978-3-030-00470-5_29 ).
+     */
+    @Test
+    public void testECDSANonceReuse() throws Exception {
+        testECDSANonceReuse_Helper(false /* useStrongbox */, "secp224r1");
+        testECDSANonceReuse_Helper(false /* useStrongbox */, "secp256r1");
+        testECDSANonceReuse_Helper(false /* useStrongbox */, "secp384r1");
+        testECDSANonceReuse_Helper(false /* useStrongbox */, "secp521r1");
+
+        if (TestUtils.hasStrongBox(getContext())) {
+            testECDSANonceReuse_Helper(true /* useStrongbox */, "secp256r1");
+        }
+    }
+
+    private void testECDSANonceReuse_Helper(boolean useStrongbox, String curve)
+            throws NoSuchAlgorithmException, NoSuchProviderException,
+                    InvalidAlgorithmParameterException, InvalidKeyException, SignatureException,
+                    IOException {
+        KeyPair kp = generateKeyPairForNonceReuse_Helper(useStrongbox, curve);
+        /* An ECDSA signature is a pair of integers (r,s).
+         *
+         * Let G be the curve base point, let n be the order of G, and let k be a random
+         * per-signature nonce.
+         *
+         * ECDSA defines:
+         *     r := x_coordinate( k x G) mod n
+         *
+         * It follows that if r_1 == r_2 mod n, then k_1 == k_2 mod n. That is, congruent r
+         * values mod n imply a compromised private key.
+         */
+        Map<String, byte[]> rValueStrToSigMap = new HashMap<String, byte[]>();
+        for (byte i = 1; i <= 100; i++) {
+            byte[] message = new byte[] {i};
+            byte[] signature = computeSignatureForNonceReuse_Helper(message, kp);
+            byte[] rValue = extractRValueFromEcdsaSignature_Helper(signature);
+            String rValueStr = HexDump.toHexString(rValue);
+            if (!rValueStrToSigMap.containsKey(rValueStr)) {
+                rValueStrToSigMap.put(rValueStr, signature);
+                continue;
+            }
+            // Duplicate nonces.
+            Log.i(
+                    TAG,
+                    "Found duplicate nonce after "
+                            + Integer.toString(rValueStrToSigMap.size())
+                            + " ECDSA signatures.");
+
+            byte[] otherSig = rValueStrToSigMap.get(rValueStr);
+            String otherSigStr = HexDump.toHexString(otherSig);
+            String currentSigStr = HexDump.toHexString(signature);
+            fail(
+                    "Duplicate ECDSA nonce detected."
+                            + " Curve: " + curve
+                            + " Strongbox: " + Boolean.toString(useStrongbox)
+                            + " Signature 1: "
+                            + otherSigStr
+                            + " Signature 2: "
+                            + currentSigStr);
+        }
+    }
+
+    private KeyPair generateKeyPairForNonceReuse_Helper(boolean useStrongbox,
+            String curve)
+            throws NoSuchAlgorithmException, NoSuchProviderException,
+                    InvalidAlgorithmParameterException {
+        // We use a generated key instead of an imported key since key generation drains the entropy
+        // pool and thus increase the chance of duplicate nonces.
+        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
+        generator.initialize(
+                new KeyGenParameterSpec.Builder("test1", KeyProperties.PURPOSE_SIGN)
+                        .setAlgorithmParameterSpec(new ECGenParameterSpec(curve))
+                        .setDigests(KeyProperties.DIGEST_NONE, KeyProperties.DIGEST_SHA256)
+                        .setIsStrongBoxBacked(useStrongbox)
+                        .build());
+        KeyPair kp = generator.generateKeyPair();
+        return kp;
+    }
+
+    /**
+     * Extract the R value from the ECDSA signature.
+     *
+     * @param sigBytes ASN.1 encoded ECDSA signature.
+     * @return The r value extracted from the signature.
+     * @throws IOException
+     */
+    private byte[] extractRValueFromEcdsaSignature_Helper(byte[] sigBytes) throws IOException {
+        /* ECDSA Signature format (X9.62 Section 6.5):
+         * ECDSA-Sig-Value ::= SEQUENCE {
+         *      r INTEGER,
+         *      s INTEGER
+         *  }
+         */
+        ASN1Primitive sig1prim = ASN1Primitive.fromByteArray(sigBytes);
+        Enumeration secEnum = ((ASN1Sequence) sig1prim).getObjects();
+        ASN1Primitive seqObj = (ASN1Primitive) secEnum.nextElement();
+        // The first ASN1 object is the r value.
+        byte[] r = seqObj.getEncoded();
+        return r;
+    }
+
+    private byte[] computeSignatureForNonceReuse_Helper(byte[] message, KeyPair keyPair)
+            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature signature = Signature.getInstance("NONEwithECDSA");
+        signature.initSign(keyPair.getPrivate());
+        signature.update(message);
+        byte[] sigBytes = signature.sign();
+        return sigBytes;
+    }
+
     private void assertNONEwithECDSASupportsMessagesShorterThanFieldSize(KeyPair keyPair)
             throws Exception {
         int keySizeBits = TestUtils.getKeySizeBits(keyPair.getPublic());
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index d5f919a..bd9a64a 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -304,10 +304,7 @@
         }
     }
 
-    @RestrictedBuildTest
-    @RequiresDevice
-    @Test
-    public void testEcAttestation_DeviceLocked() throws Exception {
+    private void testEcAttestation_DeviceLocked(Boolean expectStrongBox) throws Exception {
         if (!TestUtils.isAttestationSupported()) {
             return;
         }
@@ -325,11 +322,11 @@
                     .setAttestationChallenge(new byte[128])
                     .setKeyValidityStart(now)
                     .setKeyValidityForOriginationEnd(originationEnd)
-                    .setKeyValidityForConsumptionEnd(consumptionEnd);
+                    .setKeyValidityForConsumptionEnd(consumptionEnd)
+                    .setIsStrongBoxBacked(expectStrongBox);
 
-        if (TestUtils.hasStrongBox(getContext())) {
+        if (expectStrongBox) {
             builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
-            builder.setIsStrongBoxBacked(true);
         } else {
             builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
         }
@@ -341,7 +338,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates, TestUtils.hasStrongBox(getContext()));
+            verifyCertificateChain(certificates, expectStrongBox);
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             checkDeviceLocked(Attestation.loadFromCertificate(attestationCert));
@@ -350,6 +347,23 @@
         }
     }
 
+    @RestrictedBuildTest
+    @RequiresDevice
+    @Test
+    public void testEcAttestation_DeviceLocked() throws Exception {
+        testEcAttestation_DeviceLocked(false /* expectStrongBox */);
+    }
+
+    @RestrictedBuildTest
+    @RequiresDevice
+    @Test
+    public void testEcAttestation_DeviceLockedStrongbox() throws Exception {
+        if (!TestUtils.hasStrongBox(getContext()))
+            return;
+
+        testEcAttestation_DeviceLocked(true /* expectStrongBox */);
+    }
+
     @Test
     public void testAttestationKmVersionMatchesFeatureVersion() throws Exception {
         if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC))
@@ -603,10 +617,7 @@
         }
     }
 
-    @RestrictedBuildTest
-    @RequiresDevice  // Emulators have no place to store the needed key
-    @Test
-    public void testRsaAttestation_DeviceLocked() throws Exception {
+    private void testRsaAttestation_DeviceLocked(Boolean expectStrongBox) throws Exception {
         if (!TestUtils.isAttestationSupported()) {
             return;
         }
@@ -624,11 +635,11 @@
                     .setAttestationChallenge("challenge".getBytes())
                     .setKeyValidityStart(now)
                     .setKeyValidityForOriginationEnd(originationEnd)
-                    .setKeyValidityForConsumptionEnd(consumptionEnd);
+                    .setKeyValidityForConsumptionEnd(consumptionEnd)
+                    .setIsStrongBoxBacked(expectStrongBox);
 
-        if (TestUtils.hasStrongBox(getContext())) {
+        if (expectStrongBox) {
             builder.setDigests(DIGEST_NONE, DIGEST_SHA256);
-            builder.setIsStrongBoxBacked(true);
         } else {
             builder.setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512);
         }
@@ -640,7 +651,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates, TestUtils.hasStrongBox(getContext()));
+            verifyCertificateChain(certificates, expectStrongBox);
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             checkDeviceLocked(Attestation.loadFromCertificate(attestationCert));
@@ -649,6 +660,23 @@
         }
     }
 
+    @RestrictedBuildTest
+    @RequiresDevice  // Emulators have no place to store the needed key
+    @Test
+    public void testRsaAttestation_DeviceLocked() throws Exception {
+        testRsaAttestation_DeviceLocked(false /* expectStrongbox */);
+    }
+
+    @RestrictedBuildTest
+    @RequiresDevice  // Emulators have no place to store the needed key
+    @Test
+    public void testRsaAttestation_DeviceLockedStrongbox() throws Exception {
+        if (!TestUtils.hasStrongBox(getContext()))
+            return;
+
+        testRsaAttestation_DeviceLocked(true /* expectStrongbox */);
+    }
+
     @Test
     public void testAesAttestation() throws Exception {
         boolean[] devicePropertiesAttestationValues = {true, false};
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java
index b79f443..a87e8f97 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java
@@ -16,6 +16,7 @@
 
 package android.keystore.cts;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -88,4 +89,52 @@
 
         return errorFieldsBuilder.build();
     }
+
+    @Test
+    public void testRkpFailureServerUnavailable() {
+        KeyStoreException ex = new KeyStoreException(22, "RKP failure",
+                1 /* temporarily unavailable */);
+        assertEquals("Error must indicate key exhaustion",
+                KeyStoreException.ERROR_ATTESTATION_KEYS_UNAVAILABLE,
+                ex.getNumericErrorCode());
+        assertTrue("Must indicate a system issue",
+                ex.isSystemError());
+        assertTrue("Must indicate a transient failure",
+                ex.isTransientFailure());
+        assertEquals("Retry policy must be exponential back-off",
+                KeyStoreException.RETRY_WITH_EXPONENTIAL_BACKOFF,
+                ex.getRetryPolicy());
+    }
+
+    @Test
+    public void testRkpFailurePendingConnectivity() {
+        KeyStoreException ex = new KeyStoreException(22, "RKP failure",
+                3 /* fetching pending connectivity */);
+        assertEquals("Error must indicate key exhaustion",
+                KeyStoreException.ERROR_ATTESTATION_KEYS_UNAVAILABLE,
+                ex.getNumericErrorCode());
+        assertTrue("Must indicate a system issue",
+                ex.isSystemError());
+        assertTrue("Must indicate a transient failure",
+                ex.isTransientFailure());
+        assertEquals("Retry policy must be when connectivity is resumed",
+                KeyStoreException.RETRY_WHEN_CONNECTIVITY_AVAILABLE,
+                ex.getRetryPolicy());
+    }
+
+    @Test
+    public void testRkpFailureDeviceNotRegistered() {
+        KeyStoreException ex = new KeyStoreException(22, "RKP failure",
+                2 /* server refused issuance */);
+        assertEquals("Error must indicate key exhaustion",
+                KeyStoreException.ERROR_ATTESTATION_KEYS_UNAVAILABLE,
+                ex.getNumericErrorCode());
+        assertTrue("Must indicate a system issue",
+                ex.isSystemError());
+        assertFalse("Must indicate a permanent failure",
+                ex.isTransientFailure());
+        assertEquals("Retry policy must be never",
+                KeyStoreException.RETRY_NEVER,
+                ex.getRetryPolicy());
+    }
 }
diff --git a/tests/tests/media/audio/AndroidManifest.xml b/tests/tests/media/audio/AndroidManifest.xml
index 7129591..d5de5dd 100644
--- a/tests/tests/media/audio/AndroidManifest.xml
+++ b/tests/tests/media/audio/AndroidManifest.xml
@@ -18,7 +18,6 @@
      package="android.media.audio.cts"
      android:targetSandboxVersion="2">
 
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
diff --git a/tests/tests/media/common/src/android/media/cts/TestUtils.java b/tests/tests/media/common/src/android/media/cts/TestUtils.java
index d6c898b2..b09d333 100644
--- a/tests/tests/media/common/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/common/src/android/media/cts/TestUtils.java
@@ -21,6 +21,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
@@ -123,13 +124,33 @@
     private static long getModuleVersion(String module)
             throws PackageManager.NameNotFoundException {
         Context context = ApplicationProvider.getApplicationContext();
-        PackageInfo info;
-        info = context.getPackageManager().getPackageInfo(module,
+        PackageInfo info = context.getPackageManager().getPackageInfo(module,
                 MATCH_APEX);
         return info.getLongVersionCode();
     }
 
 
+    /**
+     * Reports whether {@code module} is the version shipped with the original system image
+     * or if it has been updated via a mainline update.
+     *
+     * @param module     the apex module name
+     * @return {@code true} if the apex module is the original version shipped with the device.
+     */
+    public static boolean isMainlineModuleFactoryVersion(String module) {
+        try {
+            Context context = ApplicationProvider.getApplicationContext();
+            PackageInfo info = context.getPackageManager().getPackageInfo(module,
+                    MATCH_APEX);
+            if (info != null) {
+                return (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // Ignore the exception on devices that do not have this module
+        }
+        return true;
+    }
+
     private TestUtils() {
     }
 
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
index 61acac7..e2f5b25 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
@@ -39,6 +39,7 @@
 import android.platform.test.annotations.RequiresDevice;
 
 import android.util.Log;
+import android.util.Pair;
 import android.view.Surface;
 
 import androidx.test.filters.SmallTest;
@@ -64,6 +65,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
@@ -379,16 +381,23 @@
     }
 
     private static class ImageListener implements ImageReader.OnImageAvailableListener {
-        private final LinkedBlockingQueue<Image> mQueue =
-                new LinkedBlockingQueue<Image>();
+        private final LinkedBlockingQueue<Pair<Image, Exception>> mQueue =
+                new LinkedBlockingQueue<Pair<Image, Exception>>();
 
         @Override
         public void onImageAvailable(ImageReader reader) {
             try {
-                mQueue.put(reader.acquireNextImage());
-            } catch (InterruptedException e) {
-                throw new UnsupportedOperationException(
-                        "Can't handle InterruptedException in onImageAvailable");
+                mQueue.put(Pair.create(reader.acquireNextImage(), null /* Exception */));
+            } catch (Exception e) {
+                // pass any exception back to the other thread, taking the exception
+                // here crashes the instrumentation in cts/junit.
+                Log.e(TAG, "Can't handle Exceptions in onImageAvailable " + e);
+                try {
+                    mQueue.put(Pair.create(null /* Image */, e));
+                } catch (Exception e2) {
+                    // ignore the nested exception, other side will see a timeout.
+                    Log.e(TAG, "Failed to send exception info across queue: " + e2);
+                }
             }
         }
 
@@ -399,7 +408,11 @@
          * @return The image from the image reader.
          */
         public Image getImage(long timeout) throws InterruptedException {
-            Image image = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+            Pair<Image,Exception> imageResult = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+            Image image = imageResult.first;
+            Exception e = imageResult.second;
+
+            assertNull("onImageAvailable() generated an exception: " + e, e);
             assertNotNull("Wait for an image timed out in " + timeout + "ms", image);
             return image;
         }
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
index 8eb38e7..61f6cdd 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
@@ -28,6 +28,7 @@
 import android.media.cts.MediaHeavyPresubmitTest;
 import android.media.cts.MediaTestBase;
 import android.media.cts.Preconditions;
+import android.media.cts.TestUtils;
 import android.os.Bundle;
 import android.platform.test.annotations.AppModeFull;
 import android.text.TextUtils;
@@ -45,6 +46,7 @@
 import com.android.compatibility.common.util.ResultUnit;
 
 import org.junit.After;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -97,6 +99,7 @@
     private int mBitrate;
 
     private boolean mSkipRateChecking = false;
+    private boolean mUpdatedSwCodec = false;
     static final String mInpPrefix = WorkDir.getMediaDirString();
 
     static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
@@ -173,6 +176,9 @@
         super.setUp();
         Bundle bundle = InstrumentationRegistry.getArguments();
         mSkipRateChecking = TextUtils.equals("true", bundle.getString("mts-media"));
+
+        mUpdatedSwCodec =
+                !TestUtils.isMainlineModuleFactoryVersion("com.google.android.media.swcodec");
     }
 
     @After
@@ -207,8 +213,11 @@
             // doDecode(name, video, width, height, null, i, maxTimeMs);
         }
 
+        // allow improvements in mainline-updated google-supplied software codecs.
+        boolean fasterIsOk = mUpdatedSwCodec & name.startsWith("c2.android.");
         String error =
-            MediaPerfUtils.verifyAchievableFrameRates(name, mime, width, height, measuredFps);
+            MediaPerfUtils.verifyAchievableFrameRates(name, mime, width, height,
+                           fasterIsOk,  measuredFps);
         // Performance numbers only make sense on real devices, so skip on non-real devices
         if ((MediaUtils.onFrankenDevice() || mSkipRateChecking) && error != null) {
             // ensure there is data, but don't insist that it is correct
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
new file mode 100644
index 0000000..b702e4a
--- /dev/null
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.media.encoder.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.platform.test.annotations.AppModeFull;
+import androidx.test.filters.SmallTest;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+@RunWith(Parameterized.class)
+public class VideoEncoderCapabilitiesTest {
+    final private String mMediaType;
+    final private int mWidth;
+    final private int mHeight;
+    final private int mFrameRate;
+    final private int mBitRate;
+    final private boolean mOptional;
+
+    @Parameterized.Parameters(name = "{index}({0}_{1}x{2}_{3}_{4}_{5})")
+    public static Collection<Object[]> input() {
+        final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+                // MediaType, width, height, frame-rate, bit-rate, optional
+                // CDD 5.2.2 C-1-2, C-2-1
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 320, 240, 20, 384000, false},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 720, 480, 30, 2000000, false},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 30, 4000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080, 30, 10000000, true},
+
+                // CDD 5.2.3 C-1-1, C-2-1
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 320, 180, 30, 800000, false},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 640, 360, 30, 2000000, false},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720, 30, 4000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080, 30, 10000000, true},
+
+                // CDD 5.2.4
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 720, 480, 30, 1600000, true},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1280, 720, 30, 4000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 1920, 1080, 30, 5000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_VP9, 3840, 2160, 30, 20000000, true},
+
+                // CDD 5.2.5
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 720, 480, 30, 1600000, true},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1280, 720, 30, 4000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 1920, 1080, 30, 5000000, true},
+                {MediaFormat.MIMETYPE_VIDEO_HEVC, 3840, 2160, 30, 20000000, true},
+
+        });
+        return exhaustiveArgsList;
+    }
+
+    public VideoEncoderCapabilitiesTest(String mediaType, int width, int height, int frameRate,
+                                        int bitRate, boolean optional) {
+        mMediaType = mediaType;
+        mWidth = width;
+        mHeight = height;
+        mFrameRate = frameRate;
+        mBitRate = bitRate;
+        mOptional = optional;
+    }
+
+    // Tests encoder profiles required by CDD.
+    @Test
+    public void testEncoderAvailability() {
+        MediaFormat format = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
+        if (mOptional) {
+            assumeTrue("Device doesn't support encoding an optional format: " + format,
+                    MediaUtils.canEncode(format));
+        } else {
+            assertTrue("Device doesn't support encoding a mandatory format: " + format,
+                    MediaUtils.canEncode(format));
+        }
+    }
+}
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index d7cfbaa..b92f2ca 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -1447,23 +1447,6 @@
         intraRefresh(new Encoder[]{mEncHandle}, 480, 360);
     }
 
-    // Tests encoder profiles required by CDD.
-    @Test
-    public void testLowQualitySDSupport() {
-        Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
-                mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
-                mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
-        support(new Encoder[]{mEncHandle}, 720, 480, 20, 384 * 1000);
-    }
-
-    @Test
-    public void testHighQualitySDSupport() {
-        Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
-                mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
-                        mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
-        support(new Encoder[]{mEncHandle}, 720, 480, 30, 2 * 1000000);
-    }
-
     @Test
     public void testFlexQVGA20fps384kbps() {
         Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
@@ -1654,22 +1637,4 @@
         }
     }
 
-    /* test size and rate are supported */
-    private void support(Encoder[] encoders, int width, int height, int frameRate, int bitRate) {
-        boolean supported = false;
-        if (encoders.length == 0) {
-            MediaUtils.skipTest("no such encoder present");
-            return;
-        }
-        for (Encoder encoder : encoders) {
-            if (encoder.testSupport(width, height, frameRate, bitRate)) {
-                supported = true;
-                break;
-            }
-        }
-        if (!supported) {
-            fail("unsupported format " + width + "x" + height + " " +
-                    frameRate + "fps " + bitRate + "bps");
-        }
-    }
 }
diff --git a/tests/tests/media/muxer/Android.bp b/tests/tests/media/muxer/Android.bp
index f252315..85eab12 100644
--- a/tests/tests/media/muxer/Android.bp
+++ b/tests/tests/media/muxer/Android.bp
@@ -46,7 +46,7 @@
     static_libs: [
         "cts-media-common",
         "ctstestrunner-axt",
-        "exoplayer2-metadataretriever-mediamuxer",
+        "exoplayer-mediamuxer_tests",
     ],
     jni_libs: [
         "libctsmediamuxertest_jni",
diff --git a/tests/tests/mediaparser/Android.bp b/tests/tests/mediaparser/Android.bp
index 138cb5a..d916d61 100644
--- a/tests/tests/mediaparser/Android.bp
+++ b/tests/tests/mediaparser/Android.bp
@@ -18,7 +18,10 @@
 
 android_test {
     name: "CtsMediaParserTestCases",
-    defaults: ["CtsMediaParserTestCasesDefaults", "cts_defaults"],
+    defaults: [
+        "CtsMediaParserTestCasesDefaults",
+        "cts_defaults",
+    ],
     min_sdk_version: "29",
     test_suites: [
         "cts",
@@ -39,8 +42,8 @@
     static_libs: [
         "ctstestrunner-axt",
         "androidx.test.ext.junit",
-        "exoplayer2-extractor-test-utils",
-        "exoplayer2-extractor-tests-assets",
+        "exoplayer-cts_media-test_assets",
+        "exoplayer-cts_media-test_utils",
     ],
     libs: [
         "android.test.base",
diff --git a/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
index 08eba99..61b27a0 100644
--- a/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
+++ b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
@@ -42,6 +42,8 @@
 
 using testing::AnyOf;
 using testing::Eq;
+using testing::Ge;
+using testing::NotNull;
 
 #define FORMAT_CASE(x) case AHARDWAREBUFFER_FORMAT_ ## x: os << #x ; break
 
@@ -439,6 +441,57 @@
     AHardwareBuffer_release(buffer);
 }
 
+TEST(AHardwareBufferTest, PlanarLockAndUnlockYuvP010Succeed) {
+    AHardwareBuffer* buffer = NULL;
+    AHardwareBuffer_Desc desc = {};
+
+    desc.width = 32;
+    desc.height = 32;
+    desc.layers = 1;
+    desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
+    desc.format = AHARDWAREBUFFER_FORMAT_YCbCr_P010;
+
+    if (!AHardwareBuffer_isSupported(&desc)) {
+        ALOGI("Test skipped: AHARDWAREBUFFER_FORMAT_YCbCr_P010 not supported.");
+        return;
+    }
+
+    // Allocate the buffer.
+    int err = AHardwareBuffer_allocate(&desc, &buffer);
+    EXPECT_EQ(NO_ERROR, err);
+
+    // Lock its planes
+    AHardwareBuffer_Planes planes;
+    err = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, NULL,
+        &planes);
+
+    // Make sure everything looks right
+    EXPECT_EQ(NO_ERROR, err);
+    EXPECT_EQ(3U, planes.planeCount);
+
+    const uint32_t yPlaneWidth = desc.width;
+    const uint32_t cPlaneWidth = desc.width / 2;
+    const uint32_t bytesPerPixel = 2;
+
+    EXPECT_THAT(planes.planes[0].data, NotNull());
+    EXPECT_THAT(planes.planes[0].pixelStride, Eq(bytesPerPixel));
+    EXPECT_THAT(planes.planes[0].rowStride, Ge(yPlaneWidth * bytesPerPixel));
+
+    EXPECT_THAT(planes.planes[1].data, NotNull());
+    EXPECT_THAT(planes.planes[1].pixelStride, Eq(bytesPerPixel * /*interleaved=*/2));
+    EXPECT_THAT(planes.planes[1].rowStride, Ge(cPlaneWidth * bytesPerPixel));
+
+    EXPECT_THAT(planes.planes[2].data, NotNull());
+    EXPECT_THAT(planes.planes[2].pixelStride, Eq(bytesPerPixel * /*interleaved=*/2));
+    EXPECT_THAT(planes.planes[2].rowStride, Ge(cPlaneWidth * bytesPerPixel));
+
+    // Unlock
+    err = AHardwareBuffer_unlock(buffer, nullptr);
+    EXPECT_EQ(NO_ERROR, err);
+
+    AHardwareBuffer_release(buffer);
+}
+
 TEST(AHardwareBufferTest, PlanarLockAndUnlockRgbaSucceed) {
     AHardwareBuffer* buffer = NULL;
     AHardwareBuffer_Desc desc = {};
diff --git a/tests/tests/os/src/android/os/cts/HexEncoding.java b/tests/tests/os/src/android/os/cts/HexEncoding.java
new file mode 100644
index 0000000..ff49899
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/HexEncoding.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts;
+
+/**
+ * Hexadecimal encoding where each byte is represented by two hexadecimal digits.
+ * Note that this is copied from android.keystore.cts.HexEncoding but only keep the
+ * needed part.
+ *
+ * @hide
+ */
+public class HexEncoding {
+
+  /** Hidden constructor to prevent instantiation. */
+  private HexEncoding() {}
+
+  /**
+   * Decodes the provided hexadecimal string into an array of bytes.
+   */
+  public static byte[] decode(String encoded) {
+    // IMPLEMENTATION NOTE: Special care is taken to permit odd number of hexadecimal digits.
+    int resultLengthBytes = (encoded.length() + 1) / 2;
+    byte[] result = new byte[resultLengthBytes];
+    int resultOffset = 0;
+    int encodedCharOffset = 0;
+    if ((encoded.length() % 2) != 0) {
+      // Odd number of digits -- the first digit is the lower 4 bits of the first result byte.
+      result[resultOffset++] = (byte) getHexadecimalDigitValue(encoded.charAt(encodedCharOffset));
+      encodedCharOffset++;
+    }
+    for (int len = encoded.length(); encodedCharOffset < len; encodedCharOffset += 2) {
+      result[resultOffset++] = (byte)
+          ((getHexadecimalDigitValue(encoded.charAt(encodedCharOffset)) << 4)
+          | getHexadecimalDigitValue(encoded.charAt(encodedCharOffset + 1)));
+    }
+    return result;
+  }
+
+  private static int getHexadecimalDigitValue(char c) {
+    if ((c >= 'a') && (c <= 'f')) {
+      return (c - 'a') + 0x0a;
+    } else if ((c >= 'A') && (c <= 'F')) {
+      return (c - 'A') + 0x0a;
+    } else if ((c >= '0') && (c <= '9')) {
+      return c - '0';
+    } else {
+      throw new IllegalArgumentException(
+          "Invalid hexadecimal digit at position : '" + c + "' (0x" + Integer.toHexString(c) + ")");
+    }
+  }
+}
diff --git a/tests/tests/os/src/android/os/cts/SntpTestServer.java b/tests/tests/os/src/android/os/cts/SntpTestServer.java
new file mode 100644
index 0000000..bca6dd1
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/SntpTestServer.java
@@ -0,0 +1,131 @@
+/*
+ * 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.os.cts;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.util.Arrays;
+
+/**
+ * Simple Sntp Server implementation for testing purpose.
+ * This is copied from {@code SntpClientTest}.
+ */
+public class SntpTestServer {
+    private final static String TAG = SntpTestServer.class.getSimpleName();
+    private static final int ORIGINATE_TIME_OFFSET = 24;
+    private static final int TRANSMIT_TIME_OFFSET = 40;
+
+    private final Object mLock = new Object();
+    private final DatagramSocket mSocket;
+    private final InetAddress mAddress;
+    private final int mPort;
+    private byte[] mReply;
+    private boolean mGenerateValidOriginateTimestamp = true;
+    private int mRcvd;
+    private int mSent;
+    private Thread mListeningThread;
+
+    public SntpTestServer() {
+        mSocket = makeSocket();
+        mAddress = mSocket.getLocalAddress();
+        mPort = mSocket.getLocalPort();
+        Log.d(TAG, "testing server listening on (" + mAddress + ", " + mPort + ")");
+
+        mListeningThread = new Thread() {
+            public void run() {
+                while (true) {
+                    byte[] buffer = new byte[512];
+                    DatagramPacket ntpMsg = new DatagramPacket(buffer, buffer.length);
+                    try {
+                        mSocket.receive(ntpMsg);
+                    } catch (IOException e) {
+                        Log.e(TAG, "datagram receive error: " + e);
+                        break;
+                    }
+                    synchronized (mLock) {
+                        mRcvd++;
+                        if (mReply == null) { continue; }
+                        if (mGenerateValidOriginateTimestamp) {
+                            // Copy the transmit timestamp into originate timestamp: This is
+                            // validated by well-behaved clients.
+                            System.arraycopy(ntpMsg.getData(), TRANSMIT_TIME_OFFSET,
+                                    mReply, ORIGINATE_TIME_OFFSET, 8);
+                        } else {
+                            // Fill it with junk instead.
+                            Arrays.fill(mReply, ORIGINATE_TIME_OFFSET,
+                                    ORIGINATE_TIME_OFFSET + 8, (byte) 0xFF);
+                        }
+                        ntpMsg.setData(mReply);
+                        ntpMsg.setLength(mReply.length);
+                        try {
+                            mSocket.send(ntpMsg);
+                        } catch (IOException e) {
+                            Log.e(TAG, "datagram send error: " + e);
+                            break;
+                        }
+                        mSent++;
+                    }
+                }
+                mSocket.close();
+            }
+        };
+        mListeningThread.start();
+    }
+
+    private DatagramSocket makeSocket() {
+        DatagramSocket socket;
+        try {
+            socket = new DatagramSocket(0, InetAddress.getLoopbackAddress());
+        } catch (SocketException e) {
+            Log.e(TAG, "Failed to create test server socket: " + e);
+            return null;
+        }
+        return socket;
+    }
+
+    public void clearServerReply() {
+        setServerReply(null);
+    }
+
+    public void setServerReply(byte[] reply) {
+        synchronized (mLock) {
+            mReply = reply;
+            mRcvd = 0;
+            mSent = 0;
+        }
+    }
+
+    /**
+     * Controls the test server's behavior of copying the client's transmit timestamp into the
+     * response's originate timestamp (which is required of a real server).
+     */
+    public void setGenerateValidOriginateTimestamp(boolean enabled) {
+        synchronized (mLock) {
+            mGenerateValidOriginateTimestamp = enabled;
+        }
+    }
+
+    public InetAddress getAddress() { return mAddress; }
+    public int getPort() { return mPort; }
+    public int numRequestsReceived() { synchronized (mLock) { return mRcvd; } }
+    public int numRepliesSent() { synchronized (mLock) { return mSent; } }
+}
diff --git a/tests/tests/os/src/android/os/cts/SystemClockSntpTest.java b/tests/tests/os/src/android/os/cts/SystemClockSntpTest.java
new file mode 100644
index 0000000..56b658d
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/SystemClockSntpTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.os.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.os.SystemClock;
+import android.util.Range;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.ThrowingRunnable;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.DateTimeException;
+
+@RunWith(AndroidJUnit4.class)
+public class SystemClockSntpTest {
+    // Mocked server response. Refer to SntpClientTest.
+    private static final String MOCKED_NTP_RESPONSE =
+            "240206ec"
+                    + "00000165"
+                    + "000000b2"
+                    + "ddfd4729"
+                    + "d9ca9446820a5000"
+                    + "d9ca9451938a3771"
+                    + "d9ca945194bd3fff"
+                    + "d9ca945194bd4001";
+    // The midpoint between d9ca945194bd3fff and d9ca945194bd4001, d9ca9451.94bd4000 represents
+    // (decimal) 1444943313.581012726 seconds in the Unix epoch, which is
+    // ~2015-10-15 21:08:33.581 UTC.
+    private static long MOCKED_NTP_TIMESTAMP = 1444943313581L;
+    private static long TEST_NTP_TIMEOUT_MILLIS = 300L;
+
+    private SntpTestServer mServer;
+
+    @After
+    public void tearDown() {
+        // Restore NTP server configurations.
+        executeShellCommand("cmd network_time_update_service set_server_config");
+    }
+
+    @Test
+    public void testCurrentNetworkTimeClock() throws Exception {
+        // Start a local SNTP test server. But does not setup a fake response.
+        // So the server will not reply to any request.
+        runWithShellPermissionIdentity(() -> mServer = new SntpTestServer());
+
+        // Write test server address into settings.
+        executeShellCommand(
+                "cmd network_time_update_service set_server_config --hostname "
+                        + mServer.getAddress().getHostAddress()
+                        + " --port " + mServer.getPort()
+                        + " --timeout_millis " + TEST_NTP_TIMEOUT_MILLIS);
+
+        // Clear current NTP value and verify it throws exception.
+        executeShellCommand("cmd network_time_update_service clear_time");
+
+        // Verify the case where the device hasn't made an NTP request yet.
+        assertThrows(DateTimeException.class, () -> SystemClock.currentNetworkTimeClock().millis());
+
+        // Trigger NtpTrustedTime refresh with the new command.
+        executeShellCommandAndAssertOutput(
+                "cmd network_time_update_service force_refresh", "false");
+
+        // Verify the returned clock throws since there is still no previous NTP fix.
+        assertThrows(DateTimeException.class, () -> SystemClock.currentNetworkTimeClock().millis());
+
+        // Setup fake responses (Refer to SntpClientTest). And trigger NTP refresh.
+        mServer.setServerReply(HexEncoding.decode(MOCKED_NTP_RESPONSE));
+
+        // After force_refresh, network_time_update_service should have associated
+        // MOCKED_NTP_TIMESTAMP with an elapsedRealtime() value between
+        // beforeRefreshElapsedMillis and afterRefreshElapsedMillis.
+        final long beforeRefreshElapsedMillis = SystemClock.elapsedRealtime();
+        executeShellCommandAndAssertOutput("cmd network_time_update_service force_refresh", "true");
+        final long afterRefreshElapsedMillis = SystemClock.elapsedRealtime();
+
+        // Request the current Unix epoch time. Assert value of SystemClock#currentNetworkTimeClock.
+        assertCurrentNetworkTimeClockInBounds(MOCKED_NTP_TIMESTAMP, beforeRefreshElapsedMillis,
+                afterRefreshElapsedMillis);
+
+        // Simulate some time passing and verify that SystemClock returns an updated time
+        // using the same NTP signal.
+        final long PASSED_DURATION_MS = 100L;
+        Thread.sleep(PASSED_DURATION_MS);
+
+        // Request the current Unix epoch time again. Verify that SystemClock returns an
+        // updated time using the same NTP signal.
+        assertCurrentNetworkTimeClockInBounds(MOCKED_NTP_TIMESTAMP, beforeRefreshElapsedMillis,
+                afterRefreshElapsedMillis);
+
+        // Remove fake server response and trigger NTP refresh to simulate a failed refresh.
+        mServer.setServerReply(null);
+        executeShellCommandAndAssertOutput(
+                "cmd network_time_update_service force_refresh", "false");
+
+        // Verify that SystemClock still returns an updated time using the same NTP signal.
+        assertCurrentNetworkTimeClockInBounds(MOCKED_NTP_TIMESTAMP, beforeRefreshElapsedMillis,
+                afterRefreshElapsedMillis);
+    }
+
+    private static void executeShellCommand(String command) {
+        executeShellCommandAndAssertOutput(command, null);
+    }
+
+    private static void executeShellCommandAndAssertOutput(
+            String command, String expectedOutput) {
+        final String trimmedResult = runShellCommand(command).trim();
+        if (expectedOutput != null) {
+            assertEquals(expectedOutput, trimmedResult);
+        }
+    }
+
+    private static void runWithShellPermissionIdentity(ThrowingRunnable command)
+            throws Exception {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity();
+        try {
+            command.run();
+        } finally {
+            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                    .dropShellPermissionIdentity();
+        }
+    }
+
+    /** Verify the given value is in range [lower, upper] */
+    private static void assertInRange(String tag, long value, long lower, long upper) {
+        final Range range = new Range(lower, upper);
+        assertTrue(tag + ": " + value + " is not within range [" + lower + ", " + upper + "]",
+                range.contains(value));
+    }
+
+    private static void assertCurrentNetworkTimeClockInBounds(long expectedTimestamp,
+            long beforeRefreshElapsedMillis, long afterRefreshElapsedMillis) {
+        final long beforeQueryElapsedMillis = SystemClock.elapsedRealtime();
+        final long networkEpochMillis = SystemClock.currentNetworkTimeClock().millis();
+        final long afterQueryElapsedMillis = SystemClock.elapsedRealtime();
+
+        // Calculate the lower/upper bound base on the elapsed time of refreshing.
+        final long lowerBoundNetworkEpochMillis =
+                expectedTimestamp + (beforeQueryElapsedMillis - afterRefreshElapsedMillis);
+        final long upperBoundNetworkEpochMillis =
+                expectedTimestamp + (afterQueryElapsedMillis - beforeRefreshElapsedMillis);
+        assertInRange("Network time", networkEpochMillis, lowerBoundNetworkEpochMillis,
+                upperBoundNetworkEpochMillis);
+    }
+}
diff --git a/tests/tests/permission/permissionTestUtilLib/Android.bp b/tests/tests/permission/permissionTestUtilLib/Android.bp
index dd50015..36f89d7 100644
--- a/tests/tests/permission/permissionTestUtilLib/Android.bp
+++ b/tests/tests/permission/permissionTestUtilLib/Android.bp
@@ -19,13 +19,16 @@
 java_library {
     name: "permission-test-util-lib",
 
-    srcs: ["src/**/*.java"],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
 
     static_libs: [
         "ub-uiautomator",
         "compatibility-device-util-axt",
-        "androidx.test.ext.junit-nodeps"
-   ],
+        "androidx.test.ext.junit-nodeps",
+    ],
 
     sdk_version: "test_current",
 }
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
index f245001..3b91f98 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -51,7 +51,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -292,11 +291,11 @@
 
     private void enableTestMode() {
         runShellCommandOrThrow("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled");
+                + " com.android.bluetooth.btservice.AdapterService set-test-mode enabled");
     }
 
     private void disableTestMode() {
         runShellCommandOrThrow("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled");
+                + " com.android.bluetooth.btservice.AdapterService set-test-mode disabled");
     }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
index 030acf9..a4e480a 100644
--- a/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NotificationListenerCheckTest.java
@@ -16,6 +16,7 @@
 
 package android.permission.cts;
 
+import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
 import static android.content.Intent.ACTION_BOOT_COMPLETED;
 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
 import static android.os.Process.myUserHandle;
@@ -59,7 +60,7 @@
 import androidx.test.filters.SdkSuppress;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.compatibility.common.util.DeviceConfigStateHelper;
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
 import com.android.compatibility.common.util.ProtoUtils;
 import com.android.compatibility.common.util.mainline.MainlineModule;
 import com.android.compatibility.common.util.mainline.ModuleDetector;
@@ -71,6 +72,7 @@
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -105,6 +107,9 @@
     private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED =
             "notification_listener_check_enabled";
 
+    /** Name of the flag that determines whether SafetyCenter is enabled. */
+    private static final String PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled";
+
     /**
      * Device config property for time period in milliseconds after which current enabled
      * notification
@@ -116,17 +121,15 @@
     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";
+    private static final String PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW =
+            "qc_max_job_count_per_rate_limiting_window";
+
+    private static final String PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS =
+            "qc_rate_limiting_window_ms";
 
     /**
      * ID for notification shown by
-     * {@link com.android.permissioncontroller.permission.service.NotificationListenerCheck}.
+     * {@link com.android.permissioncontroller.permission.service.v33.NotificationListenerCheck}.
      */
     public static final int NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID = 3;
 
@@ -141,39 +144,77 @@
     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));
+    // Override SafetyCenter enabled flag
+    @Rule
+    public DeviceConfigStateChangerRule sPrivacyDeviceConfigSafetyCenterEnabled =
+            new DeviceConfigStateChangerRule(sContext,
+                    DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_SAFETY_CENTER_ENABLED,
+                    Boolean.toString(true));
+
+    // Override NlsCheck enabled flag
+    @Rule
+    public DeviceConfigStateChangerRule sPrivacyDeviceConfigNlsCheckEnabled =
+            new DeviceConfigStateChangerRule(sContext,
+                    DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+                    Boolean.toString(true));
+
+    // Override general notification interval from once every day to once ever 1 second
+    @Rule
+    public DeviceConfigStateChangerRule sPrivacyDeviceConfigNlsCheckIntervalMillis =
+            new DeviceConfigStateChangerRule(sContext,
+                    DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS,
+                    Long.toString(OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS));
+
+    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
+    @Rule
+    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig1 =
+            new DeviceConfigStateChangerRule(sContext,
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    PROPERTY_JOB_SCHEDULER_MAX_JOB_PER_RATE_LIMIT_WINDOW,
+                    Integer.toString(3000000));
+
+    // Disable job scheduler throttling by allowing 300000 jobs per 30 sec
+    @Rule
+    public DeviceConfigStateChangerRule sJobSchedulerDeviceConfig2 =
+            new DeviceConfigStateChangerRule(sContext,
+                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+                    PROPERTY_JOB_SCHEDULER_RATE_LIMIT_WINDOW_MILLIS,
+                    Integer.toString(30000));
+
+    private static void setDeviceConfigPrivacyProperty(String propertyName, String value) {
+        runWithShellPermissionIdentity(() -> {
+            boolean valueWasSet =  DeviceConfig.setProperty(
+                    DeviceConfig.NAMESPACE_PRIVACY,
+                    /* name = */ propertyName,
+                    /* value = */ value,
+                    /* makeDefault = */ false);
+            if (!valueWasSet) {
+                throw new  IllegalStateException("Could not set " + propertyName + " to " + value);
+            }
+        }, WRITE_DEVICE_CONFIG);
     }
 
     /**
-     * Disable notification listener check
+     * Enabled or disable Safety Center
      */
-    private static void disableNotificationListenerCheckFeature() {
-        sPrivacyDeviceConfig.set(PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
-                String.valueOf(false));
+    private static void setSafetyCenterEnabled(boolean enabled) {
+        setDeviceConfigPrivacyProperty(
+                PROPERTY_SAFETY_CENTER_ENABLED,
+                /* value = */ String.valueOf(enabled));
     }
 
-    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));
+    /**
+     * Enable or disable notification listener check
+     */
+    private static void setNotificationListenerCheckEnabled(boolean enabled) {
+        setDeviceConfigPrivacyProperty(
+                PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+                /* value = */ String.valueOf(enabled));
     }
 
     /**
@@ -188,6 +229,32 @@
         runShellCommand(command);
     }
 
+    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);
+        }
+    }
+
     private void allowTestAppNotificationListenerService() {
         setNotificationListenerServiceAllowed(
                 new ComponentName(TEST_APP_PKG, TEST_APP_NOTIFICATION_SERVICE), true);
@@ -334,22 +401,17 @@
     }
 
     @BeforeClass
-    public static void beforeClassSetup() {
+    public static void beforeClassSetup() throws Exception {
         // 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);
@@ -358,66 +420,6 @@
         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();
@@ -464,9 +466,6 @@
      * 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
@@ -552,7 +551,17 @@
 
     @Test
     public void noNotificationIfFeatureDisabled() throws Throwable {
-        disableNotificationListenerCheckFeature();
+        setNotificationListenerCheckEnabled(false);
+
+        runNotificationListenerCheck();
+
+        ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+                EXPECTED_TIMEOUT_MILLIS);
+    }
+
+    @Test
+    public void noNotificationIfSafetyCenterDisabled() throws Throwable {
+        setSafetyCenterEnabled(false);
 
         runNotificationListenerCheck();
 
diff --git a/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java b/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
index c6583fc..036f47f 100755
--- a/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
+++ b/tests/tests/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
@@ -107,6 +107,8 @@
                 case WRITE_EXTERNAL_STORAGE:
                     if (newPermissions.contains(READ_EXTERNAL_STORAGE)) {
                         assertSplit(split, NO_TARGET, READ_EXTERNAL_STORAGE);
+                    } else if (newPermissions.contains(ACCESS_MEDIA_LOCATION)) {
+                        assertSplit(split, Build.VERSION_CODES.Q, ACCESS_MEDIA_LOCATION);
                     } else if (newPermissions.contains(READ_MEDIA_AUDIO)) {
                         assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_AUDIO);
                     } else if (newPermissions.contains(READ_MEDIA_VIDEO)) {
@@ -152,7 +154,7 @@
             }
         }
 
-        assertEquals(20, seenSplits.size());
+        assertEquals(21, seenSplits.size());
     }
 
     private void assertSplit(SplitPermissionInfo split, int targetSdk, String... permission) {
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 7d3bb7b..bd516b3 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1966,15 +1966,6 @@
         android:label="@string/permlab_changeWifiState"
         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.
-     @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,
@@ -2475,14 +2466,6 @@
     <!-- ======================================== -->
     <eat-comment />
 
-    <!-- @SystemApi Allows an application to send location to the device admin when an
-         organization-owned device is in lost mode.
-         <p>Not for use by third-party applications.
-         @hide
-    -->
-    <permission android:name="android.permission.SEND_LOST_MODE_LOCATION_UPDATES"
-        android:protectionLevel="signature|privileged"/>
-
     <!-- @SystemApi Allows an application to trigger lost mode on an organization-owned device.
          <p>Not for use by third-party applications.
          @hide
@@ -3738,6 +3721,12 @@
     <permission android:name="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- Allows the caller to generate keymint keys with the INCLUDE_UNIQUE_ID tag, which
+         uniquely identifies the device via the attestation certificate.
+         @hide @TestApi -->
+    <permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION"
+         android:protectionLevel="signature" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
@@ -6019,12 +6008,12 @@
       generation service.
     @hide  <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION"
-        android:protectionLevel="signature|role" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to manage the cloudsearch service.
      @hide  <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_CLOUDSEARCH"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged|role" />
 
     <!-- Allows an app to set the theme overlay in /vendor/overlay
          being used.
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 1a3fef3..edfcf3a 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -71,9 +71,6 @@
     private static final String MANAGE_COMPANION_DEVICES_PERMISSION
             = "android.permission.MANAGE_COMPANION_DEVICES";
 
-    private static final String ALLOW_SLIPPERY_TOUCHES_PERMISSION
-            = "android.permission.ALLOW_SLIPPERY_TOUCHES";
-
     private static final String LOG_TAG = "PermissionProtectionTest";
 
     private static final String PLATFORM_PACKAGE_NAME = "android";
@@ -478,9 +475,6 @@
                 return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE);
             case MANAGE_COMPANION_DEVICES_PERMISSION:
                 return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
-            case ALLOW_SLIPPERY_TOUCHES_PERMISSION:
-                // In R and S branches, skip this permission
-                return true;
             default:
                 return false;
         }
diff --git a/tests/tests/permission3/Android.bp b/tests/tests/permission3/Android.bp
index 36d24af..4928598 100644
--- a/tests/tests/permission3/Android.bp
+++ b/tests/tests/permission3/Android.bp
@@ -55,6 +55,7 @@
         ":CtsAccessMicrophoneApp",
         ":CtsAccessMicrophoneApp2",
         ":CtsAccessMicrophoneAppLocationProvider",
+        ":CtsAppLocationProviderWithSummary",
         ":CtsHelperAppOverlay",
         ":CtsCreateNotificationChannelsApp31",
         ":CtsCreateNotificationChannelsApp33",
diff --git a/tests/tests/permission3/AndroidTest.xml b/tests/tests/permission3/AndroidTest.xml
index 9e54fc6..384ea0b 100644
--- a/tests/tests/permission3/AndroidTest.xml
+++ b/tests/tests/permission3/AndroidTest.xml
@@ -43,6 +43,7 @@
         <option name="push" value="CtsAccessMicrophoneApp.apk->/data/local/tmp/cts/permission3/CtsAccessMicrophoneApp.apk" />
         <option name="push" value="CtsAccessMicrophoneApp2.apk->/data/local/tmp/cts/permission3/CtsAccessMicrophoneApp2.apk" />
         <option name="push" value="CtsAccessMicrophoneAppLocationProvider.apk->/data/local/tmp/cts/permission3/CtsAccessMicrophoneAppLocationProvider.apk" />
+        <option name="push" value="CtsAppLocationProviderWithSummary.apk->/data/local/tmp/cts/permission3/CtsAppLocationProviderWithSummary.apk" />
         <option name="push" value="CtsPermissionPolicyApp25.apk->/data/local/tmp/cts/permission3/CtsPermissionPolicyApp25.apk" />
         <option name="push" value="CtsUsePermissionApp22.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp22.apk" />
         <option name="push" value="CtsUsePermissionApp22CalendarOnly.apk->/data/local/tmp/cts/permission3/CtsUsePermissionApp22CalendarOnly.apk" />
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 9264c6c..104655f 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
@@ -25,7 +25,6 @@
 import android.os.Handler
 import android.os.Looper
 
-const val EXTRA_DELETE_CHANNELS_ON_CLOSE = "extra_delete_channels_on_close"
 const val EXTRA_CREATE_CHANNELS = "extra_create"
 const val EXTRA_CREATE_CHANNELS_DELAYED = "extra_create_delayed"
 const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
@@ -38,12 +37,16 @@
 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
+const val LONG_DELAY_MS = 2000L
 
 class CreateNotificationChannelsActivity : Activity() {
     lateinit var notificationManager: NotificationManager
+    var launchActivityOnSecondResume = false
+    var isFirstResume = true
+    val handler = Handler(Looper.getMainLooper())
+
     override fun onStart() {
-        val handler = Handler(Looper.getMainLooper())
+        val launchSecondActivity = intent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)
         notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
         if (intent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
             handler.postDelayed({
@@ -57,12 +60,20 @@
             }, LONG_DELAY_MS)
         } else if (intent.getBooleanExtra(EXTRA_CREATE_CHANNELS, false)) {
             createChannel()
+            if (launchSecondActivity) {
+                launchActivityOnSecondResume = true
+            }
         } else if (intent.getBooleanExtra(EXTRA_CREATE_CHANNELS_DELAYED, false)) {
             handler.postDelayed({
                 createChannel()
             }, DELAY_MS)
+        } else {
+            if (launchSecondActivity) {
+                launchSecondActivity()
+            }
         }
 
+
         if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
             requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
         } else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
@@ -74,19 +85,20 @@
         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 launchSecondActivity() {
+        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)
+    }
+
     private fun createChannel() {
         if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
             notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
@@ -94,11 +106,12 @@
         }
     }
 
-    override fun onPause() {
-        if (intent.getBooleanExtra(EXTRA_DELETE_CHANNELS_ON_CLOSE, false)) {
-            notificationManager.deleteNotificationChannel(CHANNEL_ID_31)
+    override fun onResume() {
+        super.onResume()
+        if (!isFirstResume && launchActivityOnSecondResume) {
+            launchSecondActivity()
         }
-        super.onPause()
+        isFirstResume = false
     }
 
     override fun onRequestPermissionsResult(
diff --git a/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/Android.bp b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/Android.bp
new file mode 100644
index 0000000..91143ae
--- /dev/null
+++ b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsAppLocationProviderWithSummary",
+    defaults: ["mts-target-sdk-version-current"],
+    min_sdk_version: "31",
+    srcs: [
+        "src/**/*.kt",
+    ],
+    static_libs: [
+        "kotlin-stdlib",
+    ],
+}
diff --git a/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/AndroidManifest.xml b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/AndroidManifest.xml
new file mode 100644
index 0000000..020f613
--- /dev/null
+++ b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?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.applocationproviderwithsummary">
+
+  <application
+      android:label="LocationProviderWithSummaryApp">
+    <activity android:name=".AddLocationProviderActivity" android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+    <activity android:name=".AllServicesActivity" android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.VIEW_APP_FEATURES" />
+      </intent-filter>
+      <meta-data
+          android:name="app_features_preference_summary"
+          android:resource="@string/summary_label"/>
+    </activity>
+  </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_delegatetargetactivity.xml b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/res/values/strings.xml
similarity index 80%
rename from tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_delegatetargetactivity.xml
rename to tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/res/values/strings.xml
index a8d062e..d6f150a 100644
--- a/tests/quickaccesswallet/res/xml/quickaccesswallet_configuration_delegatetargetactivity.xml
+++ b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/res/values/strings.xml
@@ -13,7 +13,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<quickaccesswallet-service
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:useTargetActivityForQuickAccess="true"/>
\ No newline at end of file
+<resources>
+  <string name="attribution_label">Attribution label.</string>
+  <string name="summary_label">Services summary.</string>
+</resources>
diff --git a/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AddLocationProviderActivity.kt b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AddLocationProviderActivity.kt
new file mode 100644
index 0000000..632bbb6
--- /dev/null
+++ b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AddLocationProviderActivity.kt
@@ -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 android.permission3.cts.applocationproviderwithsummary
+
+import android.app.Activity
+import android.location.Criteria
+import android.location.LocationManager
+import android.os.Bundle
+
+/**
+ * An activity that adds this package as a test location provider.
+ */
+class AddLocationProviderActivity : Activity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val attrContext = createAttributionContext("test.tag")
+        val locationManager = attrContext.getSystemService(LocationManager::class.java)
+        locationManager.addTestProvider(
+            packageName, false, false, false, false, false, false, false, Criteria.POWER_LOW,
+            Criteria.ACCURACY_COARSE
+        )
+
+        setResult(RESULT_OK)
+        finish()
+    }
+}
\ No newline at end of file
diff --git a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AllServicesActivity.kt
similarity index 71%
rename from tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
rename to tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AllServicesActivity.kt
index 533524b..94939de 100644
--- a/tests/quickaccesswallet/src/android/quickaccesswallet/UseTargetActivityForQuickAccessWalletService.java
+++ b/tests/tests/permission3/UsePermissionAppLocationProviderWithSummary/src/AllServicesActivity.kt
@@ -13,10 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import android.app.Activity
+import android.os.Bundle
 
-package android.quickaccesswallet;
+class AllServicesActivity : Activity() {
 
-/**
- * Extends {@link TestQuickAccessWalletService} to allow for a different manifest configuration.
- */
-public class UseTargetActivityForQuickAccessWalletService extends TestQuickAccessWalletService {}
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index dc9d177..5310f49 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -58,8 +58,7 @@
 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
+const val EXPECTED_TIMEOUT_MS = 2000L
 
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
 class NotificationPermissionTest : BaseUsePermissionTest() {
@@ -211,8 +210,6 @@
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(startSecondActivity = true)
         pressBack()
-        assertDialogNotShowing(DELAY_MS_SHORT)
-        Thread.sleep(DELAY_MS)
         clickPermissionRequestAllowButton()
     }
 
@@ -220,7 +217,6 @@
     fun notificationPromptNotShownForSubsequentStartsIfTaskStartWasNotLauncher() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(mainIntent = false, startSecondActivity = true)
-        Thread.sleep(DELAY_MS)
         assertDialogNotShowing()
     }
 
@@ -228,7 +224,6 @@
     fun notificationPromptShownForChannelCreateInSecondActivityIfTaskStartWasLauncher() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(startSecondActivity = true, createChannels = false)
-        Thread.sleep(DELAY_MS)
         clickPermissionRequestAllowButton()
     }
 
@@ -236,7 +231,6 @@
     fun notificationPromptNotShownForChannelCreateInSecondActivityIfTaskStartWasntLauncher() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(mainIntent = false, startSecondActivity = true, createChannels = false)
-        Thread.sleep(DELAY_MS)
         assertDialogNotShowing()
     }
 
@@ -246,7 +240,6 @@
         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()
@@ -312,7 +305,7 @@
             context.startActivity(grantPermission)
         }
         try {
-            clickPermissionRequestAllowButton()
+            clickPermissionRequestAllowButton(timeoutMillis = EXPECTED_TIMEOUT_MS)
             Assert.fail("Expected not to find permission request dialog")
         } catch (expected: RuntimeException) {
             // Do nothing
@@ -323,7 +316,6 @@
     fun mergeAppPermissionRequestIntoNotificationAndVerifyResult() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(requestPermissionsDelayed = true)
-        Thread.sleep(DELAY_MS)
         clickPermissionRequestAllowButton()
         assertAppPermissionGrantedState(POST_NOTIFICATIONS, granted = true)
         clickPermissionRequestAllowForegroundButton()
@@ -337,7 +329,6 @@
     fun mergeNotificationRequestIntoAppPermissionRequestAndVerifyResult() {
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(createChannels = false, createChannelsDelayed = true, requestPermissions = true)
-        Thread.sleep(DELAY_MS)
         clickPermissionRequestAllowForegroundButton()
         assertAppPermissionGrantedState(RECORD_AUDIO, granted = true)
         clickPermissionRequestAllowButton()
@@ -390,7 +381,7 @@
         installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
         launchApp(createChannels = false, requestNotificationPermission = true)
         try {
-            clickPermissionRequestAllowButton()
+            clickPermissionRequestAllowButton(timeoutMillis = EXPECTED_TIMEOUT_MS)
             Assert.fail("Expected not to find permission request dialog")
         } catch (expected: RuntimeException) {
             // Do nothing
@@ -430,7 +421,6 @@
     private fun launchApp(
         createChannels: Boolean = true,
         createChannelsDelayed: Boolean = false,
-        deleteChannels: Boolean = false,
         requestNotificationPermission: Boolean = false,
         requestPermissions: Boolean = false,
         requestPermissionsDelayed: Boolean = false,
@@ -453,7 +443,6 @@
         if (!createChannels) {
             intent.putExtra(EXTRA_CREATE_CHANNELS_DELAYED, createChannelsDelayed)
         }
-        intent.putExtra(EXTRA_DELETE_CHANNELS_ON_CLOSE, deleteChannels)
         intent.putExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, requestPermissions)
         if (!requestPermissions) {
             intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, requestPermissionsDelayed)
@@ -481,7 +470,7 @@
         waitForIdle()
     }
 
-    private fun assertDialogNotShowing(timeoutMillis: Long = DELAY_MS) {
+    private fun assertDialogNotShowing(timeoutMillis: Long = EXPECTED_TIMEOUT_MS) {
         try {
             clickPermissionRequestAllowButton(timeoutMillis)
             Assert.fail("Expected not to find permission request dialog")
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionAllServicesTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionAllServicesTest.kt
new file mode 100644
index 0000000..727a22f
--- /dev/null
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionAllServicesTest.kt
@@ -0,0 +1,162 @@
+/*
+ * 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
+
+import android.app.Activity
+import android.app.AppOpsManager
+import com.android.compatibility.common.util.AppOpsUtils.setOpMode
+import android.content.ComponentName
+import android.content.Intent
+import android.location.LocationManager
+import android.net.Uri
+import android.provider.Settings
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import org.junit.Test
+import java.util.concurrent.TimeUnit
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Assert.assertNull
+import android.support.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.eventually
+
+class PermissionAllServicesTest : BasePermissionTest() {
+    val locationManager = context.getSystemService(LocationManager::class.java)!!
+
+    @Test
+    fun testAllServicesPreferenceShownWhenAppIsLocationProviderAndCanHandleClick() {
+        installPackage(LOCATION_PROVIDER_APP_APK_PATH_2, grantRuntimePermissions = true)
+        allowPackagesToMockLocation(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+        enableAppAsLocationProvider(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+
+        eventually({
+            try {
+                launchAppInfoActivity(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+                waitFindObject(By.textContains(ALL_SERVICES_LABEL))
+            } catch (e: Exception) {
+                pressBack()
+                throw e
+            } }, 1000L)
+
+        uninstallPackage(LOCATION_PROVIDER_APP_PACKAGE_NAME_2, requireSuccess = false)
+        locationManager.removeTestProvider(LOCATION_PROVIDER_APP_APK_PATH_2)
+    }
+
+    @Test
+    fun testAllServicesSummaryShowsWhenAppIsLocationProviderAndCanHandleClick() {
+        installPackage(LOCATION_PROVIDER_APP_APK_PATH_2, grantRuntimePermissions = true)
+        allowPackagesToMockLocation(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+        enableAppAsLocationProvider(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+
+        eventually({
+            try {
+                launchAppInfoActivity(LOCATION_PROVIDER_APP_PACKAGE_NAME_2)
+                waitFindObject(By.textContains(SUMMARY))
+            } catch (e: Exception) {
+                pressBack()
+                throw e
+            } }, 1000L)
+
+        uninstallPackage(LOCATION_PROVIDER_APP_PACKAGE_NAME_2, requireSuccess = false)
+        locationManager.removeTestProvider(LOCATION_PROVIDER_APP_APK_PATH_2)
+    }
+
+    @Test
+    fun testAllServicesPreferenceNotShownWhenAppCannotHandleClick() {
+        installPackage(LOCATION_PROVIDER_APP_APK_PATH_1, grantRuntimePermissions = true)
+        allowPackagesToMockLocation(LOCATION_PROVIDER_APP_PACKAGE_NAME_1)
+        enableAppAsLocationProvider(LOCATION_PROVIDER_APP_PACKAGE_NAME_1)
+
+        eventually({
+            try {
+                launchAppInfoActivity(LOCATION_PROVIDER_APP_PACKAGE_NAME_1)
+                assertNull(waitFindObjectOrNull(By.textContains(ALL_SERVICES_LABEL)))
+            } catch (e: Exception) {
+                pressBack()
+                throw e
+            } }, 1000L)
+
+        uninstallPackage(LOCATION_PROVIDER_APP_PACKAGE_NAME_1, requireSuccess = false)
+        locationManager.removeTestProvider(LOCATION_PROVIDER_APP_APK_PATH_1)
+    }
+
+    @Test
+    fun testAllServicesPreferenceNotShownWhenAppIsNotLocationProvider() {
+        installPackage(NON_LOCATION_APP_APK_PATH, grantRuntimePermissions = true)
+
+        eventually({
+            try {
+                launchAppInfoActivity(NON_LOCATION_APP_PACKAGE_NAME)
+                assertNull(waitFindObjectOrNull(By.textContains(ALL_SERVICES_LABEL)))
+            } catch (e: Exception) {
+                pressBack()
+                throw e
+            } }, 1000L)
+
+        uninstallPackage(NON_LOCATION_APP_APK_PATH, requireSuccess = false)
+    }
+
+    private fun allowPackagesToMockLocation(packageName: String) {
+        setOpMode(packageName, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpsManager.MODE_ALLOWED)
+        setOpMode(
+            context.packageName, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpsManager.MODE_ALLOWED
+        )
+    }
+
+    private fun launchAppInfoActivity(packageName: String) {
+        context.startActivity(
+            Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
+                data = Uri.parse("package:$packageName")
+                addCategory(Intent.CATEGORY_DEFAULT)
+                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+            })
+    }
+
+    private fun enableAppAsLocationProvider(appPackageName: String) {
+        // Add the test app as location provider.
+        val future = startActivityForFuture(
+            Intent().apply {
+                component = ComponentName(
+                    appPackageName, "$appPackageName.AddLocationProviderActivity"
+                )
+            })
+
+        val result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+        assertEquals(Activity.RESULT_OK, result.resultCode)
+        assertTrue(
+            callWithShellPermissionIdentity {
+                locationManager.isProviderPackage(appPackageName)
+            }
+        )
+    }
+
+    companion object {
+        const val LOCATION_PROVIDER_APP_APK_PATH_1 =
+            "$APK_DIRECTORY/CtsAccessMicrophoneAppLocationProvider.apk"
+        const val NON_LOCATION_APP_APK_PATH = "$APK_DIRECTORY/CtsUsePermissionApp22.apk"
+        const val LOCATION_PROVIDER_APP_APK_PATH_2 =
+            "$APK_DIRECTORY/CtsAppLocationProviderWithSummary.apk"
+        const val NON_LOCATION_APP_PACKAGE_NAME = "android.permission3.cts.usepermission"
+        const val LOCATION_PROVIDER_APP_PACKAGE_NAME_1 =
+            "android.permission3.cts.accessmicrophoneapplocationprovider"
+        const val LOCATION_PROVIDER_APP_PACKAGE_NAME_2 =
+            "android.permission3.cts.applocationproviderwithsummary"
+        const val APP_LABEL = "LocationProviderWithSummaryApp"
+        const val ALL_SERVICES_LABEL = "All Services"
+        const val SUMMARY = "Services summary."
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
index 699d111..448405d 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
@@ -187,8 +187,8 @@
         context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
 
     private fun enableTestMode() = runShellCommandOrThrow("dumpsys activity service" +
-        " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled")
+        " com.android.bluetooth.btservice.AdapterService set-test-mode enabled")
 
     private fun disableTestMode() = runShellCommandOrThrow("dumpsys activity service" +
-        " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled")
+        " com.android.bluetooth.btservice.AdapterService set-test-mode disabled")
 }
diff --git a/tests/tests/persistentdataservice/Android.bp b/tests/tests/persistentdataservice/Android.bp
new file mode 100644
index 0000000..ce31120
--- /dev/null
+++ b/tests/tests/persistentdataservice/Android.bp
@@ -0,0 +1,36 @@
+// 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 {
+    name: "CtsPersistentDataBlockManagerTestCases",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "ctstestrunner-axt",
+         "Harrier",
+         "truth-prebuilt"
+    ],
+    libs: ["android.test.base"],
+    srcs: ["src/**/*.java"],
+    sdk_version: "test_current",
+    min_sdk_version: "27",
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+}
diff --git a/tests/tests/persistentdataservice/AndroidManifest.xml b/tests/tests/persistentdataservice/AndroidManifest.xml
new file mode 100644
index 0000000..e5db957
--- /dev/null
+++ b/tests/tests/persistentdataservice/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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.persistentdata.cts">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!-- This is a self-instrumenting test package. -->
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.persistentdata.cts"
+                     android:label="CTS tests of PersistentDataBlockManager">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="17"></uses-sdk>
+
+</manifest>
+
diff --git a/tests/tests/persistentdataservice/AndroidTest.xml b/tests/tests/persistentdataservice/AndroidTest.xml
new file mode 100644
index 0000000..e47032f
--- /dev/null
+++ b/tests/tests/persistentdataservice/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS PersistentDataBlockManager test cases">
+    <option name="test-suite-tag" value="cts" />
+
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+
+    <option name="not-shardable" value="true" />
+    <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="CtsPersistentDataBlockManagerTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.persistentdata.cts" />
+        <option name="runtime-hint" value="8m30s" />
+    </test>
+</configuration>
diff --git a/tests/tests/persistentdataservice/OWNERS b/tests/tests/persistentdataservice/OWNERS
new file mode 100644
index 0000000..f4d73eb
--- /dev/null
+++ b/tests/tests/persistentdataservice/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 24950
+omakoto@google.com
+yamasani@google.com
diff --git a/tests/tests/persistentdataservice/TEST_MAPPING b/tests/tests/persistentdataservice/TEST_MAPPING
new file mode 100644
index 0000000..4772e4f
--- /dev/null
+++ b/tests/tests/persistentdataservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsPersistentDataBlockManagerTestCases"
+    }
+  ]
+}
diff --git a/tests/tests/persistentdataservice/src/android/service/persistentdata/PersistentDataBlockManagerTest.java b/tests/tests/persistentdataservice/src/android/service/persistentdata/PersistentDataBlockManagerTest.java
new file mode 100644
index 0000000..70e97ea
--- /dev/null
+++ b/tests/tests/persistentdataservice/src/android/service/persistentdata/PersistentDataBlockManagerTest.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.service.persistentdata;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureDoesNotHavePermission;
+import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.nene.TestApis;
+
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(BedsteadJUnit4.class)
+public class PersistentDataBlockManagerTest {
+    @ClassRule
+    @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final Context sContext = TestApis.context().instrumentedContext();
+    private static final PersistentDataBlockManager sPersistentDataBlockManager =
+            sContext.getSystemService(PersistentDataBlockManager.class);
+
+    @EnsureHasPermission(android.Manifest.permission.ACCESS_PDB_STATE)
+    @Test
+    public void getPersistentDataPackageName_returnsNonNullResult() {
+        if (sPersistentDataBlockManager == null) {
+            return;
+        }
+        assertThat(sPersistentDataBlockManager.getPersistentDataPackageName()).isNotNull();
+    }
+
+    @EnsureDoesNotHavePermission(android.Manifest.permission.ACCESS_PDB_STATE)
+    @Test
+    public void getPersistentDataPackageName_withoutPermission_throwsException() {
+        if (sPersistentDataBlockManager == null) {
+            return;
+        }
+        assertThrows(SecurityException.class,
+                sPersistentDataBlockManager::getPersistentDataPackageName);
+    }
+}
diff --git a/tests/tests/provider/Android.bp b/tests/tests/provider/Android.bp
index e293332..5a1b7a0 100644
--- a/tests/tests/provider/Android.bp
+++ b/tests/tests/provider/Android.bp
@@ -47,7 +47,8 @@
     // uncomment when b/140885436 is fixed
     // sdk_version: "test_current",
     min_sdk_version: "21",
-    target_sdk_version: "Tiramisu",
+    //TODO(b/227617884): Change target_sdk_version to 33 after T SDK finalization is complete
+    target_sdk_version: "10000",
 
     platform_apis: true,
 
diff --git a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
index 1deafdd..ca85b65 100644
--- a/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
+++ b/tests/tests/security/src/android/security/cts/AndroidFutureTest.java
@@ -37,7 +37,7 @@
 @RunWith(AndroidJUnit4.class)
 public class AndroidFutureTest extends StsExtraBusinessLogicTestCase {
 
-    @AsbSecurityTest(cveBugId = 186530450)
+    @AsbSecurityTest(cveBugId =  197228210)
     @Test
     public void testAndroidFutureReadThrowable() throws Exception {
         String filePath = "/data/system/" + System.currentTimeMillis();
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index 65eb132..ecf8acc 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -22,31 +22,24 @@
 import android.content.res.Resources;
 import android.media.MediaMetadataRetriever;
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import android.test.AndroidTestCase;
 
 import java.io.IOException;
 
-import org.junit.Before;
-import org.junit.After;
-import static org.junit.Assert.*;
-
-import androidx.test.runner.AndroidJUnit4;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-@RunWith(AndroidJUnit4.class)
-public class MediaMetadataRetrieverTest extends StsExtraBusinessLogicTestCase {
+public class MediaMetadataRetrieverTest extends AndroidTestCase {
     protected Resources mResources;
     protected MediaMetadataRetriever mRetriever;
 
-    @Before
-    public void setUp() throws Exception {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
         mResources = getContext().getResources();
         mRetriever = new MediaMetadataRetriever();
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
         mRetriever.release();
     }
 
@@ -60,7 +53,6 @@
         }
     }
 
-    @Test
     @AsbSecurityTest(cveBugId = 24623447)
     public void testID3v2EmbeddedPicture() {
         setDataSourceFd(R.raw.id3v2_3_extended_header_overflow_padding);
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 83ce8ff..2d2e084 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -24,7 +24,7 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.AsbSecurityTest;
-import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+import android.test.AndroidTestCase;
 import android.util.Log;
 
 import com.android.compatibility.common.util.MediaUtils;
@@ -38,16 +38,7 @@
 
 import android.security.cts.R;
 
-import org.junit.Before;
-import org.junit.After;
-import static org.junit.Assert.*;
-
-import androidx.test.runner.AndroidJUnit4;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-@RunWith(AndroidJUnit4.class)
-public class MediaServerCrashTest extends StsExtraBusinessLogicTestCase {
+public class MediaServerCrashTest extends AndroidTestCase {
     private static final String TAG = "MediaServerCrashTest";
 
     private static final String MIMETYPE_DRM_MESSAGE = "application/vnd.oma.drm.message";
@@ -58,8 +49,9 @@
     private final ConditionVariable mOnPrepareCalled = new ConditionVariable();
     private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
 
-    @Before
-    public void setUp() throws Exception {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
         mFlFilePath = new File(getContext().getFilesDir(), "temp.fl").getAbsolutePath();
 
         mOnPrepareCalled.close();
@@ -91,12 +83,12 @@
         });
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
         new File(mFlFilePath).delete();
     }
 
-    @Test
     @AsbSecurityTest(cveBugId = 25070434)
     public void testInvalidMidiNullPointerAccess() throws Exception {
         testIfMediaServerDied(R.raw.midi_crash);
@@ -123,17 +115,16 @@
         }
     }
 
-    @Test
     @AsbSecurityTest(cveBugId = 25070434)
     public void testDrmManagerClientReset() throws Exception {
         checkIfMediaServerDiedForDrm(R.raw.drm_uaf);
     }
 
     private void checkIfMediaServerDiedForDrm(int res) throws Exception {
-        AssetFileDescriptor afd = getInstrumentation().getContext().getResources().openRawResourceFd(res);
+        AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(res);
         FileInputStream dmStream = afd.createInputStream();
         RandomAccessFile flFile = new RandomAccessFile(mFlFilePath, "rw");
-        if (!MediaUtils.convertDmToFl(getInstrumentation().getContext(), dmStream, flFile)) {
+        if (!MediaUtils.convertDmToFl(mContext, dmStream, flFile)) {
             Log.w(TAG, "Can not convert dm to fl, skip checkIfMediaServerDiedForDrm");
             mMediaPlayer.release();
             return;
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
index 8467f9a..0de6253 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
@@ -29,6 +29,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.ShortcutListAsserter;
 
 import java.util.ArrayList;
@@ -36,20 +37,20 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Predicate;
 
-import com.android.compatibility.common.util.CddTest;
-
 @CddTest(requirement="3.8.1/C-2-3")
 @SmallTest
 public class ShortcutManagerLauncherCallbackTest extends ShortcutManagerCtsTestsBase {
 
     private static class MyCallback extends LauncherApps.Callback {
         private final HashSet<String> mInterestedPackages = new HashSet<String>();
-        private boolean called;
+        private final AtomicInteger mCallcount = new AtomicInteger(0);
         private String lastPackage;
         private final List<ShortcutInfo> lastShortcuts = new ArrayList<>();
 
+
         public MyCallback(String... interestedPackages) {
             mInterestedPackages.addAll(Arrays.asList(interestedPackages));
         }
@@ -98,17 +99,17 @@
             lastPackage = packageName;
             lastShortcuts.clear();
             lastShortcuts.addAll(shortcuts);
-            called = true;
+            mCallcount.incrementAndGet();
         }
 
         public synchronized void reset() {
             lastPackage = null;
             lastShortcuts.clear();
-            called = false;
+            mCallcount.set(0);
         }
 
         public synchronized boolean isCalled() {
-            return called;
+            return mCallcount.get() > 0;
         }
 
         public synchronized ShortcutListAsserter assertCalled(Context clientContext) {
@@ -343,6 +344,16 @@
                     .areAllDisabled();
             reset.run();
 
+            //-----------------------
+            Log.i(TAG, "testCallbacks: pushDynamicShortcut");
+            runWithCaller(mPackageContext1, () -> {
+                for (int i = 0; i < 100; i++) {
+                    getManager().pushDynamicShortcut(makeShortcut("s" + i));
+                }
+            });
+            retryUntil(c::isCalled, "callback not called.");
+            assertEquals(1, c.mCallcount.get());
+            reset.run();
         } finally {
             runWithCaller(mLauncherContext1, () -> {
                 if (registered.get()) {
diff --git a/tests/tests/telephony/OWNERS b/tests/tests/telephony/OWNERS
index d28e9ff..02848c8 100644
--- a/tests/tests/telephony/OWNERS
+++ b/tests/tests/telephony/OWNERS
@@ -1,16 +1,2 @@
-# Bug component: 20868
-amitmahajan@google.com
-breadley@google.com
-fionaxu@google.com
-jackyu@google.com
-rgreenwalt@google.com
-tgunn@google.com
-jminjie@google.com
-shuoq@google.com
-sarahchin@google.com
-xiaotonj@google.com
-huiwang@google.com
-jayachandranc@google.com
-chinmayd@google.com
-amruthr@google.com
-sasindran@google.com
+file:platform/frameworks/opt/telephony:/OWNERS
+
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioConfigImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioConfigImpl.java
index 86a2c8f7..b18a355 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioConfigImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioConfigImpl.java
@@ -265,4 +265,14 @@
             Log.e(TAG, "null mRadioConfigIndication");
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioConfig.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioConfig.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioDataImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioDataImpl.java
index e9fff8e..92a22c3 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioDataImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioDataImpl.java
@@ -222,4 +222,14 @@
             Log.e(TAG, "Failed to stopKeepalive from AIDL. Exception" + ex);
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioData.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioData.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioModemImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioModemImpl.java
index 4cca64b..8f6a9a9 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioModemImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioModemImpl.java
@@ -472,4 +472,14 @@
                 break;
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioModem.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioModem.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioNetworkImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioNetworkImpl.java
index c914f79..fb3dbca 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioNetworkImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioNetworkImpl.java
@@ -505,4 +505,14 @@
             Log.e(TAG, "Failed to getUsageSetting from AIDL. Exception" + ex);
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioNetwork.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioNetwork.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
index 08980a3..b6e9d00 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
@@ -838,4 +838,14 @@
             Log.e(TAG, "null mRadioSimIndication");
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioSim.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioSim.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioVoiceImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioVoiceImpl.java
index 4a415cd..c6fdfdf 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioVoiceImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioVoiceImpl.java
@@ -749,4 +749,14 @@
             Log.e(TAG, "null mRadioVoiceIndication");
         }
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IRadioVoice.HASH;
+    }
+
+    @Override
+    public int getInterfaceVersion() {
+        return IRadioVoice.VERSION;
+    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index 8d88810..137a43b 100755
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -64,6 +64,7 @@
 import androidx.test.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.CarrierPrivilegeUtils;
+import com.android.compatibility.common.util.PropertyUtil;
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.compatibility.common.util.TestThread;
@@ -81,7 +82,9 @@
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -1217,45 +1220,78 @@
         }
     }
 
-    @Test
-    public void testCellularUsageSetting() throws Exception {
-        if (!isSupported()) return;
-
-        boolean isUsageSettingSupported = true;
-        int defaultUsageSetting = SubscriptionManager.USAGE_SETTING_DEFAULT;
-        int[] supportedUsageSettings;
+    private Set<Integer> getSupportedUsageSettings() throws Exception {
+        final Set<Integer> supportedUsageSettings = new HashSet();
         final Context context = InstrumentationRegistry.getContext();
 
-        //  Load the resources to provide the device capability
+        // Vendors can add supported usage settings by adding resources.
         try {
-            defaultUsageSetting = context.getResources().getInteger(
-                com.android.internal.R.integer.config_default_cellular_usage_setting);
-            supportedUsageSettings = context.getResources().getIntArray(
+            int[] usageSettingsFromResource = context.getResources().getIntArray(
                 com.android.internal.R.array.config_supported_cellular_usage_settings);
-            // If usage settings are not supported, return the default setting, which is UNKNOWN.
-            if (supportedUsageSettings.length < 1) {
-                isUsageSettingSupported = false;
-                fail("Usage Setting resources empty");
+
+            for (int setting : usageSettingsFromResource) {
+                supportedUsageSettings.add(setting);
             }
-        } catch (Resources.NotFoundException nfe) {
-            fail("Usage Setting resources not found");
-            isUsageSettingSupported = false;
+
+        } catch (Resources.NotFoundException ignore) {
         }
 
-        int[] settingsToTest = new int[] {
-                SubscriptionManager.USAGE_SETTING_DEFAULT,
-                defaultUsageSetting};
+        // For devices shipping with Radio HAL 2.0 and/or non-HAL devices launching with T,
+        // the usage settings are required to be supported if the rest of the telephony stack
+        // has support for that mode of operation.
+        if (PropertyUtil.isVendorApiLevelAtLeast(android.os.Build.VERSION_CODES.TIRAMISU)) {
+            final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
 
-        for (int setting : settingsToTest) {
-            PersistableBundle bundle = new PersistableBundle();
-            bundle.putInt(CarrierConfigManager.KEY_CELLULAR_USAGE_SETTING_INT, setting);
-            overrideCarrierConfig(bundle, mSubId);
-            SubscriptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
-                    (sm) -> sm.getActiveSubscriptionInfo(mSubId));
-            assertEquals(
-                    isUsageSettingSupported ? setting :
-                            SubscriptionManager.USAGE_SETTING_UNKNOWN,
-                    info.getUsageSetting());
+            if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_DATA)) {
+                supportedUsageSettings.add(SubscriptionManager.USAGE_SETTING_DATA_CENTRIC);
+            }
+            if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) {
+                supportedUsageSettings.add(SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC);
+            }
+        }
+
+        return supportedUsageSettings;
+    }
+
+    private int getUsageSetting() throws Exception {
+        SubscriptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
+                (sm) -> sm.getActiveSubscriptionInfo(mSubId));
+        return info.getUsageSetting();
+    }
+
+    private void checkUsageSetting(int inputSetting, boolean isSupported) throws Exception {
+        final int initialSetting = getUsageSetting();
+
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(CarrierConfigManager.KEY_CELLULAR_USAGE_SETTING_INT, inputSetting);
+        overrideCarrierConfig(bundle, mSubId);
+
+        final int newSetting = getUsageSetting();
+        assertEquals(isSupported ? inputSetting : initialSetting, newSetting);
+    }
+
+    @Test
+    public void testCellularUsageSetting() throws Exception {
+        Set<Integer> supportedUsageSettings = getSupportedUsageSettings();
+
+        // If any setting works, default must be allowed.
+        if (supportedUsageSettings.size() > 0) {
+            supportedUsageSettings.add(SubscriptionManager.USAGE_SETTING_DEFAULT);
+        }
+
+        final int[] allUsageSettings = new int[]{
+                SubscriptionManager.USAGE_SETTING_UNKNOWN,
+                SubscriptionManager.USAGE_SETTING_DEFAULT,
+                SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC,
+                SubscriptionManager.USAGE_SETTING_DATA_CENTRIC,
+                3 /* undefined value */};
+
+        try {
+            for (int setting : allUsageSettings) {
+                checkUsageSetting(setting, supportedUsageSettings.contains(setting));
+            }
+        } finally {
+            overrideCarrierConfig(null, mSubId);
         }
     }
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
index 482cd92..89f34c4 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
@@ -185,7 +185,13 @@
 
     private void registerTelephonyCallback(@NonNull TelephonyCallback callback,
             boolean renounceFine, boolean renounceCoarse) {
-        mTelephonyManager.registerTelephonyCallback(renounceFine, renounceCoarse, mSimpleExecutor,
+        int includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_FINE;
+        if (renounceFine && renounceCoarse) {
+            includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_NONE;
+        } else if (renounceFine) {
+            includeLocationData = TelephonyManager.INCLUDE_LOCATION_DATA_COARSE;
+        }
+        mTelephonyManager.registerTelephonyCallback(includeLocationData, mSimpleExecutor,
                 callback);
     }
 
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 f6148af..1436e51 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1380,11 +1380,12 @@
         }
 
         assertEquals(mServiceState, mTelephonyManager.getServiceState());
-        assertServiceStateSanitization(mServiceState, mTelephonyManager.getServiceState(true,
-                true));
+        assertServiceStateSanitization(mServiceState, mTelephonyManager.getServiceState(
+                TelephonyManager.INCLUDE_LOCATION_DATA_NONE));
         assertServiceStateFineLocationSanitization(mServiceState,
-                mTelephonyManager.getServiceState(true, false));
-        assertEquals(mServiceState, mTelephonyManager.getServiceState(false, true));
+                mTelephonyManager.getServiceState(TelephonyManager.INCLUDE_LOCATION_DATA_COARSE));
+        assertEquals(mServiceState, mTelephonyManager.getServiceState(
+                TelephonyManager.INCLUDE_LOCATION_DATA_FINE));
     }
 
     private void assertServiceStateSanitization(ServiceState expectedServiceState,
@@ -3549,8 +3550,6 @@
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity("android.permission.READ_PRIVILEGED_PHONE_STATE");
         List<UiccCardInfo> cardsInfo = mTelephonyManager.getUiccCardsInfo();
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .dropShellPermissionIdentity();
         for (UiccCardInfo cardInfo : cardsInfo) {
             for (UiccPortInfo portInfo : cardInfo.getPorts()) {
                 int simCardState = mTelephonyManager.getSimCardState(cardInfo
@@ -3562,6 +3561,8 @@
                         TelephonyManager.SIM_STATE_PRESENT).contains(simCardState));
             }
         }
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
     }
 
     private boolean isDataEnabled() {
@@ -4372,6 +4373,7 @@
             return;
         }
 
+        boolean connectedToNrCell = false;
         for (CellInfo cellInfo : mTelephonyManager.getAllCellInfo()) {
             CellIdentity cellIdentity = cellInfo.getCellIdentity();
             int[] bands;
@@ -4389,11 +4391,21 @@
                             || (band >= AccessNetworkConstants.NgranBands.BAND_257
                             && band <= AccessNetworkConstants.NgranBands.BAND_261));
                 }
+                if (cellInfo.isRegistered()) {
+                    connectedToNrCell = true;
+                }
             } else {
                 continue;
             }
             assertTrue(bands.length > 0);
         }
+
+        if (connectedToNrCell) {
+            assertEquals(TelephonyManager.NETWORK_TYPE_NR, mTelephonyManager.getDataNetworkType());
+        } else {
+            assertNotEquals(TelephonyManager.NETWORK_TYPE_NR,
+                    mTelephonyManager.getDataNetworkType());
+        }
     }
 
     /**
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
index 9810d1b..0bd0236 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
@@ -158,7 +158,7 @@
         }
 
         // Wait the radio state update in Framework
-        TimeUnit.SECONDS.sleep(1);
+        TimeUnit.SECONDS.sleep(2);
         int toggleRadioState =
                 radioState == TelephonyManager.RADIO_POWER_ON
                         ? TelephonyManager.RADIO_POWER_OFF
@@ -177,7 +177,7 @@
         }
 
         // Wait the radio state update in Framework
-        TimeUnit.SECONDS.sleep(1);
+        TimeUnit.SECONDS.sleep(2);
         assertEquals(sTelephonyManager.getRadioPowerState(), radioState);
 
         Log.d(TAG, "Test Done ");
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
index b563d16..62f0f01 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
@@ -381,7 +381,6 @@
 
         if (sServiceConnector != null && sIsBound) {
             sServiceConnector.disconnectCarrierImsService();
-            sServiceConnector.disconnectServices();
             sIsBound = false;
         }
     }
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 3495b66..692b32f 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
@@ -2165,6 +2165,37 @@
             automation.dropShellPermissionIdentity();
         }
 
+        // Reply the SIP code 504 SERVER TIMEOUT
+        capExchangeImpl.setPublishOperator((listener, pidfXml, cb) -> {
+            int networkResp = 504;
+            String reason = "SERVER TIMEOUT";
+            cb.onNetworkResponse(networkResp, reason);
+            listener.onPublish();
+        });
+
+        // Notify framework to send the PUBLISH request to the ImsService.
+        eventListener.onRequestPublishCapabilities(
+                RcsUceAdapter.CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN);
+
+        // Verify ImsService receive the publish request from framework.
+        assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
+                TestImsService.LATCH_UCE_REQUEST_PUBLISH));
+
+        try {
+            // Verify the publish state callback is received.
+            assertEquals(RcsUceAdapter.PUBLISH_STATE_PUBLISHING,
+                    waitForIntResult(publishStateQueue));
+            assertEquals(RcsUceAdapter.PUBLISH_STATE_RCS_PROVISION_ERROR,
+                    waitForIntResult(publishStateQueue));
+            // Verify the value of getting from the API is PUBLISH_STATE_RCS_PROVISION_ERROR
+            automation.adoptShellPermissionIdentity();
+            int publishState = uceAdapter.getUcePublishState();
+            assertEquals(RcsUceAdapter.PUBLISH_STATE_RCS_PROVISION_ERROR, publishState);
+        } finally {
+            publishStateQueue.clear();
+            automation.dropShellPermissionIdentity();
+        }
+
         LinkedBlockingQueue<Integer> errorQueue = new LinkedBlockingQueue<>();
         LinkedBlockingQueue<Long> errorRetryQueue = new LinkedBlockingQueue<>();
         LinkedBlockingQueue<Boolean> completeQueue = new LinkedBlockingQueue<>();
diff --git a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java b/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
index 92904b2..4dd61b4 100644
--- a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
@@ -19,8 +19,10 @@
 import static androidx.test.InstrumentationRegistry.getContext;
 
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.AsyncTask;
 import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
@@ -37,6 +39,9 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue(getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY));
+
         mTelephonyManager =
                 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
     }
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 0848ec4..250575a 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
@@ -181,7 +181,10 @@
         List<TvInteractiveAppServiceInfo> list = mManager.getTvInteractiveAppServiceList();
 
         for (TvInteractiveAppServiceInfo info : list) {
-            if (info.getServiceInfo().name.equals(StubTvInteractiveAppService.class.getName())) {
+            if (info.getServiceInfo().name.equals(StubTvInteractiveAppService.class.getName())
+                    && info.getSupportedTypes()
+                    == (TvInteractiveAppServiceInfo.INTERACTIVE_APP_TYPE_HBBTV
+                            | TvInteractiveAppServiceInfo.INTERACTIVE_APP_TYPE_GINGA)) {
                 return;
             }
         }
diff --git a/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppViewTest.java b/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppViewTest.java
index 308bafe..103eec9 100644
--- a/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/interactive/cts/TvInteractiveAppViewTest.java
@@ -27,6 +27,7 @@
 import android.media.tv.interactive.TvInteractiveAppView;
 import android.os.ConditionVariable;
 import android.tv.cts.R;
+import android.view.InputEvent;
 
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -56,6 +57,7 @@
     private TvInteractiveAppView mTvInteractiveAppView;
     private TvInteractiveAppManager mManager;
     private TvInteractiveAppServiceInfo mStubInfo;
+    private TvInteractiveAppView.OnUnhandledInputEventListener mOnUnhandledInputEventListener;
 
     @Rule
     public RequiredFeatureRule featureRule = new RequiredFeatureRule(
@@ -181,4 +183,23 @@
             }
         }.run();
     }
+
+    @Test
+    public void testGetOnUnhandledInputEventListener() {
+        mOnUnhandledInputEventListener = new TvInteractiveAppView.OnUnhandledInputEventListener() {
+            @Override
+            public boolean onUnhandledInputEvent(InputEvent event) {
+                return true;
+            }
+        };
+        mTvInteractiveAppView.setOnUnhandledInputEventListener(getExecutor(),
+                mOnUnhandledInputEventListener);
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mTvInteractiveAppView.getOnUnhandledInputEventListener()
+                        == mOnUnhandledInputEventListener;
+            }
+        }.run();
+    }
 }
diff --git a/tests/tests/uidmigration/OWNERS b/tests/tests/uidmigration/OWNERS
index e69fd97..966a94a 100644
--- a/tests/tests/uidmigration/OWNERS
+++ b/tests/tests/uidmigration/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 315013
 topjohnwu@google.com
 ashfall@google.com
+mpgroover@google.com
diff --git a/tests/tests/uidmigration/lib/src/android/uidmigration/cts/Const.kt b/tests/tests/uidmigration/lib/src/android/uidmigration/cts/Const.kt
index e08d627..9064aa5 100644
--- a/tests/tests/uidmigration/lib/src/android/uidmigration/cts/Const.kt
+++ b/tests/tests/uidmigration/lib/src/android/uidmigration/cts/Const.kt
@@ -19,6 +19,7 @@
 object Const {
     const val CTS_TEST_PKG = "android.uidmigration.cts"
     const val INSTALL_TEST_PKG = "android.uidmigration.cts.InstallTestApp"
+    const val INSTALL_TEST_PKG2 = "${INSTALL_TEST_PKG}2"
     const val PERM_TEST_PKG = "android.uidmigration.cts.PermissionTestApp"
     const val DATA_TEST_PKG = "android.uidmigration.cts.DataTestApp"
     const val ACTION_UPDATE_ACK = "android.uidmigration.cts.ACTION_UPDATE_ACK"
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
index cb84f3f..1cc9980 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
@@ -70,7 +70,7 @@
         // 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)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG, Const.INSTALL_TEST_PKG + "2"))
 
         // Should not allow upgrading to an APK that directly removes sharedUserId.
         assertFalse(installPackage(InstallTest.APK3))
@@ -78,7 +78,7 @@
         // Leave shared UID.
         assertTrue(installPackage(InstallTest.APK4))
         pkgs = mPm.getPackagesForUid(uid).assertNotNull()
-        assertEquals(1, pkgs.size)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG + "2"))
 
         uninstallPackage(Const.INSTALL_TEST_PKG)
         uninstallPackage(Const.INSTALL_TEST_PKG + "2")
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
index a525ff8..4a0a8863 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
@@ -49,6 +49,10 @@
 @Suppress("NOTHING_TO_INLINE")
 inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
 
+// Identical regardless of order
+fun <T> Array<T>.sameAs(vararg items: T) =
+        size == items.size && all { items.contains(it) } && items.all { contains(it) }
+
 fun installPackage(apkPath: String): Boolean {
     return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
 }
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
index 3958a12..1f7af46 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
@@ -48,7 +48,7 @@
     @After
     fun tearDown() {
         uninstallPackage(Const.INSTALL_TEST_PKG)
-        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        uninstallPackage(Const.INSTALL_TEST_PKG2)
     }
 
     // Restore and ensure both test apps are sharing UID.
@@ -56,7 +56,7 @@
         uninstallPackage(Const.INSTALL_TEST_PKG)
         assertTrue(installPackage(InstallTest.APK))
         val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
-        assertEquals(2, pkgs.size)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG, Const.INSTALL_TEST_PKG2))
     }
 
     private fun testNewInstallOnly(uid: Int) {
@@ -72,7 +72,7 @@
         assertTrue(installPackage(InstallTest.APK4))
         var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         // With NEW_INSTALL_ONLY, upgrades should not change appId.
-        assertEquals(2, pkgs.size)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG, Const.INSTALL_TEST_PKG2))
         pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
         assertNotNull(pkgInfo.sharedUserId)
 
@@ -84,7 +84,7 @@
         assertTrue(installPackage(InstallTest.APK4))
         pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         // Newly installed apps with sharedUserMaxSdkVersion set should not join shared UID.
-        assertEquals(1, pkgs.size)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG2))
         pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
         assertNull(pkgInfo.sharedUserId)
     }
@@ -95,17 +95,17 @@
         assertTrue(installPackage(InstallTest.APK4))
         var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         // With BEST_EFFORT, upgrades should also not change appId.
-        assertEquals(2, pkgs.size)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG, Const.INSTALL_TEST_PKG2))
         var pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
         assertNotNull(pkgInfo.sharedUserId)
 
         val oldUidName = mPm.getNameForUid(uid)
-        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        uninstallPackage(Const.INSTALL_TEST_PKG2)
 
         // 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)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG))
 
         // Confirm that the internal PackageSetting is actually migrated.
         val newUidName = mPm.getNameForUid(uid)
@@ -116,7 +116,7 @@
         // 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)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG))
     }
 
     @Test
@@ -127,7 +127,7 @@
         // 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)
+        assertTrue(pkgs.sameAs(Const.INSTALL_TEST_PKG, Const.INSTALL_TEST_PKG2))
 
         if (Build.IS_USERDEBUG) {
             testNewInstallOnly(uid)
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index ddf9c54..7d73da9 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -69,6 +69,7 @@
                     p.setAntiAlias(false);
                     p.setStrokeWidth(1f);
                     p.setColor(Color.BLACK);
+                    canvas.translate(0.5f, 0.5f);
                     for (int i = 0; i < 10; i++) {
                         canvas.drawPoint(i * 10, i * 10, p);
                     }
@@ -129,7 +130,7 @@
                     };
                     canvas.drawLines(pts, p);
                 })
-                .runWithComparer(mExactComparer);
+                .runWithComparer(new MSSIMComparer(0.99));
     }
 
     @Test
@@ -150,7 +151,7 @@
                     p.setStrokeWidth(5);
                     canvas.drawText(testString, 30, 50, p);
                 })
-                .runWithComparer(mExactComparer);
+                .runWithComparer(new MSSIMComparer(0.99));
     }
 
     private void drawTestTextOnPath(Canvas canvas) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java
index acfc9cc..3bbac74 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java
@@ -36,7 +36,7 @@
 public abstract class DisplayModifier {
     private static final RectF RECT = new RectF(0, 0, 100, 100);
     private static final float[] POINTS = new float[]{
-            0, 40, 40, 0, 40, 80, 80, 40
+            0.5f, 40.5f, 40.5f, 0.5f, 40.5f, 80.5f, 80.5f, 40.5f
     };
     private static final float[] TRIANGLE_POINTS = new float[]{
             40, 0, 80, 80, 80, 80, 0, 80, 0, 80, 40, 0
diff --git a/tests/tests/usb/AndroidTest.xml b/tests/tests/usb/AndroidTest.xml
index fb75184..ef71236 100644
--- a/tests/tests/usb/AndroidTest.xml
+++ b/tests/tests/usb/AndroidTest.xml
@@ -19,6 +19,7 @@
     <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" />
+    <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUsbManagerTestCases.apk" />
diff --git a/tests/tests/usb/src/android/usb/cts/UsbPortApiTest.java b/tests/tests/usb/src/android/usb/cts/UsbPortApiTest.java
index e953417..cf269b9 100644
--- a/tests/tests/usb/src/android/usb/cts/UsbPortApiTest.java
+++ b/tests/tests/usb/src/android/usb/cts/UsbPortApiTest.java
@@ -34,6 +34,9 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import java.util.function.Consumer;
+import java.util.concurrent.Executor;
+
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
@@ -64,9 +67,13 @@
     private UiAutomation mUiAutomation =
         InstrumentationRegistry.getInstrumentation().getUiAutomation();
 
+    private Executor mExecutor;
+    private Consumer<Integer> mConsumer;
+
     @Before
     public void setUp() {
         mContext = InstrumentationRegistry.getContext();
+        mExecutor = mContext.getMainExecutor();
         PackageManager pm = mContext.getPackageManager();
         MockitoAnnotations.initMocks(this);
 
@@ -85,26 +92,26 @@
         mUiAutomation.adoptShellPermissionIdentity(MANAGE_USB);
 
         mMockUsbPort = new UsbPort(mUsbManagerMock, "1", 0, 0, true, true);
-        int result = 0;
+        boolean result = true;
 
+        mConsumer = new Consumer<Integer>(){
+            public void accept(Integer status){
+                Log.d(TAG, "Consumer status:" + status);
+            };
+        };
         // Should pass with permission.
-        when(mMockUsbService.resetUsbPort(anyString(),anyInt(),
-                  any(IUsbOperationInternal.class))).thenReturn(true);
-        result = mMockUsbPort.resetUsbPort();
-        if (result == 0) {
-            Log.d(TAG, "resetUsbPort success");
-        } else {
-            Log.d(TAG, "resetUsbPort fail ,result = " + result);
-        }
+        mMockUsbService.resetUsbPort(anyString(), anyInt(),
+                  any(IUsbOperationInternal.class));
+        mMockUsbPort.resetUsbPort(mExecutor, mConsumer);
 
         // Drop MANAGE_USB permission.
         mUiAutomation.dropShellPermissionIdentity();
 
         try {
-            mUsbPort.resetUsbPort();
-            Assert.fail("Expected SecurityException on resetUsbPort.");
+            mUsbPort.resetUsbPort(mExecutor, mConsumer);
+            Assert.fail("SecurityException not thrown for resetUsbPort when MANAGE_USB is not acquired.");
         } catch (SecurityException secEx) {
-            Log.d(TAG, "Expected SecurityException on resetUsbPort.");
+            Log.d(TAG, "SecurityException expected on resetUsbPort  when MANAGE_USB is not acquired.");
         }
     }
 
diff --git a/tests/tests/view/src/android/view/cts/AttachedSurfaceControlTest.java b/tests/tests/view/src/android/view/cts/AttachedSurfaceControlTest.java
index 8ba340a..962d75a 100644
--- a/tests/tests/view/src/android/view/cts/AttachedSurfaceControlTest.java
+++ b/tests/tests/view/src/android/view/cts/AttachedSurfaceControlTest.java
@@ -17,12 +17,14 @@
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.util.Log;
+import android.server.wm.ActivityManagerTestBase;
 import android.view.AttachedSurfaceControl;
 
 import androidx.lifecycle.Lifecycle;
@@ -34,6 +36,7 @@
 
 import org.junit.Assert;
 import org.junit.Assume;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -48,6 +51,7 @@
 @RequiresDevice
 public class AttachedSurfaceControlTest {
     private static final String TAG = "AttachedSurfaceControlTest";
+    private ActivityManagerTestBase.IgnoreOrientationRequestSession mOrientationSession;
 
     private static class TransformHintListener implements
             AttachedSurfaceControl.OnBufferTransformHintChangedListener {
@@ -77,7 +81,6 @@
         }
     }
 
-
     @Before
     public void setup() {
         PackageManager pm =
@@ -85,6 +88,12 @@
         boolean supportsRotation = pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
                 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
         Assume.assumeTrue(supportsRotation);
+        mOrientationSession = new ActivityManagerTestBase.IgnoreOrientationRequestSession(DEFAULT_DISPLAY, false);
+    }
+
+    @After
+    public void teardown() {
+        mOrientationSession.close();
     }
 
     @Test
@@ -175,10 +184,9 @@
             // If the device is already in landscape, do nothing.
             if (firstCallback[0] != null) {
                 Assert.assertTrue(firstCallback[0].await(3, TimeUnit.SECONDS));
-            }
-            // Check the callback value matches the call to get the transform hint.
-            scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[0],
+                scenario.onActivity(activity -> Assert.assertEquals(transformHintResult[0],
                     activity.getWindow().getRootSurfaceControl().getBufferTransformHint()));
+            }
 
             scenario.onActivity(activity -> {
                 TransformHintListener listener = new TransformHintListener(activity,
diff --git a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
index 90d23a3..4d0d24b 100644
--- a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
+++ b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
@@ -16,12 +16,18 @@
 
 package android.view.cts;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import android.app.Dialog;
+import android.view.View;
+import android.widget.FrameLayout;
 import android.window.OnBackInvokedCallback;
 import android.window.OnBackInvokedDispatcher;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.Lifecycle;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.filters.MediumTest;
@@ -30,6 +36,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import java.util.HashMap;
+
 /**
  * Test {@link OnBackInvokedDispatcher}.
  */
@@ -58,6 +66,77 @@
     }
 
     @Test
+    public void findDispatcherOnView() {
+        final OnBackInvokedDispatcher[] windowOnBackInvokedDispatcher = {null};
+        mActivityRule.getScenario().onActivity(activity -> {
+            mActivity = activity;
+            mDialog = mActivity.getDialog();
+            View view = new View(activity) {
+                @Override
+                protected void onAttachedToWindow() {
+                    super.onAttachedToWindow();
+                    windowOnBackInvokedDispatcher[0] = findOnBackInvokedDispatcher();
+                }
+            };
+            assertNull("View is not attached, it should not have an OnBackInvokedDispatcher",
+                    view.findOnBackInvokedDispatcher());
+            activity.setContentView(view);
+        });
+        assertNotNull("View is attached, it should have an OnBackInvokedDispatcher",
+                windowOnBackInvokedDispatcher[0]);
+    }
+
+    @Test
+    public void findDispatcherOnViewGroup() {
+        final HashMap<String, View> viewMap = new HashMap<>();
+        mActivityRule.getScenario().onActivity(activity -> {
+            mActivity = activity;
+            mDialog = mActivity.getDialog();
+            FrameLayout root = new FrameLayout(activity) {
+                @Nullable
+                @Override
+                public OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(
+                        @NonNull View child, @NonNull View requester) {
+                    viewMap.put("root_child", child);
+                    viewMap.put("root_requester", requester);
+                    return super.findOnBackInvokedDispatcherForChild(child, requester);
+                }
+            };
+            FrameLayout parent = new FrameLayout(activity) {
+                @Nullable
+                @Override
+                public OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(
+                        @NonNull View child, @NonNull View requester) {
+                    viewMap.put("parent_child", child);
+                    viewMap.put("parent_requester", requester);
+                    return super.findOnBackInvokedDispatcherForChild(child, requester);
+                }
+            };
+            View view = new View(activity);
+            viewMap.put("root", root);
+            viewMap.put("parent", parent);
+            viewMap.put("view", view);
+
+            root.addView(parent);
+            parent.addView(view);
+            activity.setContentView(root);
+        });
+
+        View view = viewMap.get("view");
+        View parent = viewMap.get("parent");
+        assertNotNull("View is attached, it should have an OnBackInvokedDispatcher",
+                view.findOnBackInvokedDispatcher());
+        assertEquals("Requester from root should be the leaf view",
+                view, viewMap.get("root_requester"));
+        assertEquals("Child from root should be the direct child",
+                parent, viewMap.get("root_child"));
+        assertEquals("Requester from direct parent should be the direct child",
+                view, viewMap.get("parent_requester"));
+        assertEquals("Child from parent should be the direct child",
+                view, viewMap.get("parent_child"));
+    }
+
+    @Test
     public void testRegisterAndUnregisterCallbacks() {
         OnBackInvokedDispatcher dispatcher = mActivity.getOnBackInvokedDispatcher();
         OnBackInvokedCallback callback1 = createBackCallback();
@@ -72,9 +151,6 @@
     }
 
     private OnBackInvokedCallback createBackCallback() {
-        return new OnBackInvokedCallback() {
-            @Override
-            public void onBackInvoked() {}
-        };
+        return () -> {};
     }
 }
diff --git a/tests/tests/virtualdevice/app/src/android/virtualdevice/streamedtestapp/MainActivity.java b/tests/tests/virtualdevice/app/src/android/virtualdevice/streamedtestapp/MainActivity.java
index 90fe811..7eba35c 100644
--- a/tests/tests/virtualdevice/app/src/android/virtualdevice/streamedtestapp/MainActivity.java
+++ b/tests/tests/virtualdevice/app/src/android/virtualdevice/streamedtestapp/MainActivity.java
@@ -18,16 +18,30 @@
 
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.media.AudioFormat.CHANNEL_OUT_MONO;
+import static android.media.AudioFormat.ENCODING_PCM_16BIT;
+import static android.media.AudioFormat.ENCODING_PCM_FLOAT;
+import static android.media.AudioRecord.READ_BLOCKING;
 import static android.virtualdevice.cts.common.ActivityResultReceiver.ACTION_SEND_ACTIVITY_RESULT;
+import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_LAST_RECORDED_NONZERO_VALUE;
 import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_POWER_SPECTRUM_AT_FREQUENCY;
 import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_POWER_SPECTRUM_NOT_FREQUENCY;
 import static android.virtualdevice.cts.common.AudioHelper.ACTION_PLAY_AUDIO;
 import static android.virtualdevice.cts.common.AudioHelper.ACTION_RECORD_AUDIO;
 import static android.virtualdevice.cts.common.AudioHelper.AMPLITUDE;
 import static android.virtualdevice.cts.common.AudioHelper.BUFFER_SIZE_IN_BYTES;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_BUFFER;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_VALUE;
 import static android.virtualdevice.cts.common.AudioHelper.CHANNEL_COUNT;
+import static android.virtualdevice.cts.common.AudioHelper.EXTRA_AUDIO_DATA_TYPE;
+import static android.virtualdevice.cts.common.AudioHelper.FLOAT_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.FLOAT_VALUE;
 import static android.virtualdevice.cts.common.AudioHelper.FREQUENCY;
+import static android.virtualdevice.cts.common.AudioHelper.NUMBER_OF_SAMPLES;
 import static android.virtualdevice.cts.common.AudioHelper.SAMPLE_RATE;
+import static android.virtualdevice.cts.common.AudioHelper.SHORT_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.SHORT_VALUE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -51,6 +65,7 @@
 
 import java.nio.ByteBuffer;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
 
 /**
  * Test activity to be streamed in the virtual device.
@@ -143,10 +158,53 @@
                     finish();
                     break;
                 case ACTION_PLAY_AUDIO:
-                    playAudio();
+                    @AudioHelper.DataType int playDataType = getIntent().getIntExtra(
+                            EXTRA_AUDIO_DATA_TYPE, -1);
+                    int playEncoding =
+                            playDataType == FLOAT_ARRAY ? ENCODING_PCM_FLOAT : ENCODING_PCM_16BIT;
+                    int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, CHANNEL_OUT_MONO,
+                            playEncoding);
+                    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE,
+                            CHANNEL_OUT_MONO, playEncoding, bufferSize, AudioTrack.MODE_STREAM);
+                    audioTrack.play();
+                    switch (playDataType) {
+                        case BYTE_BUFFER:
+                            playAudioFromByteBuffer(audioTrack);
+                            break;
+                        case BYTE_ARRAY:
+                            playAudioFromByteArray(audioTrack);
+                            break;
+                        case SHORT_ARRAY:
+                            playAudioFromShortArray(audioTrack);
+                            break;
+                        case FLOAT_ARRAY:
+                            playAudioFromFloatArray(audioTrack);
+                            break;
+                    }
                     break;
                 case ACTION_RECORD_AUDIO:
-                    recordAudio();
+                    @AudioHelper.DataType int recordDataType = getIntent().getIntExtra(
+                            EXTRA_AUDIO_DATA_TYPE, -1);
+                    int recordEncoding =
+                            recordDataType == FLOAT_ARRAY ? ENCODING_PCM_FLOAT : ENCODING_PCM_16BIT;
+                    AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
+                            SAMPLE_RATE,
+                            AudioFormat.CHANNEL_IN_MONO, recordEncoding, BUFFER_SIZE_IN_BYTES);
+                    audioRecord.startRecording();
+                    switch (recordDataType) {
+                        case BYTE_BUFFER:
+                            recordAudioToByteBuffer(audioRecord);
+                            break;
+                        case BYTE_ARRAY:
+                            recordAudioToByteArray(audioRecord);
+                            break;
+                        case SHORT_ARRAY:
+                            recordAudioToShortArray(audioRecord);
+                            break;
+                        case FLOAT_ARRAY:
+                            recordAudioToFloatArray(audioRecord);
+                            break;
+                    }
                     break;
                 default:
                     Log.w(TAG, "Unknown action: " + action);
@@ -219,50 +277,179 @@
         }
     }
 
-    private void playAudio() {
-        int numSamples = AudioHelper.computeNumSamples(/* timeMs= */ 1000, SAMPLE_RATE,
-                CHANNEL_COUNT);
-        ByteBuffer audioData = AudioHelper.createAudioData(
-                SAMPLE_RATE, numSamples, CHANNEL_COUNT, FREQUENCY, AMPLITUDE);
-
-        int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
-                AudioFormat.ENCODING_PCM_16BIT);
-        AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE,
-                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize,
-                AudioTrack.MODE_STREAM);
-        audioTrack.play();
-
+    private void playAudioFromByteBuffer(AudioTrack audioTrack) {
         // Write to the audio track asynchronously to avoid ANRs.
-        CompletableFuture.runAsync(() -> {
-            int remainingSamples = numSamples;
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            ByteBuffer audioData = AudioHelper.createAudioData(
+                    SAMPLE_RATE, NUMBER_OF_SAMPLES, CHANNEL_COUNT, FREQUENCY, AMPLITUDE);
+
+            int remainingSamples = NUMBER_OF_SAMPLES;
             while (remainingSamples > 0) {
-                remainingSamples -= audioTrack.write(
-                        audioData,
-                        audioData.remaining(),
+                remainingSamples -= audioTrack.write(audioData, audioData.remaining(),
                         AudioTrack.WRITE_BLOCKING);
             }
             audioTrack.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            sendBroadcast(intent);
             finish();
         });
     }
 
-    private void recordAudio() {
-        AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE,
-                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE_IN_BYTES);
-        audioRecord.startRecording();
+    private void playAudioFromByteArray(AudioTrack audioTrack) {
+        // Write to the audio track asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            byte[] audioData = new byte[NUMBER_OF_SAMPLES];
+            for (int i = 0; i < audioData.length; i++) {
+                audioData[i] = BYTE_VALUE;
+            }
 
+            int remainingSamples = audioData.length;
+            while (remainingSamples > 0) {
+                remainingSamples -= audioTrack.write(audioData, 0, audioData.length);
+            }
+            audioTrack.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            sendBroadcast(intent);
+            finish();
+        });
+    }
+
+    private void playAudioFromShortArray(AudioTrack audioTrack) {
+        // Write to the audio track asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            short[] audioData = new short[NUMBER_OF_SAMPLES];
+            for (int i = 0; i < audioData.length; i++) {
+                audioData[i] = SHORT_VALUE;
+            }
+
+            int remainingSamples = audioData.length;
+            while (remainingSamples > 0) {
+                remainingSamples -= audioTrack.write(audioData, 0, audioData.length);
+            }
+            audioTrack.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            sendBroadcast(intent);
+            finish();
+        });
+    }
+
+    private void playAudioFromFloatArray(AudioTrack audioTrack) {
+        // Write to the audio track asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            float[] audioData = new float[NUMBER_OF_SAMPLES];
+            for (int i = 0; i < audioData.length; i++) {
+                audioData[i] = FLOAT_VALUE;
+            }
+
+            int remainingSamples = audioData.length;
+            while (remainingSamples > 0) {
+                remainingSamples -= audioTrack.write(audioData, 0, audioData.length,
+                        AudioTrack.WRITE_BLOCKING);
+            }
+            audioTrack.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            sendBroadcast(intent);
+            finish();
+        });
+    }
+
+    private void recordAudioToByteBuffer(AudioRecord audioRecord) {
         // Read from the audio record asynchronously to avoid ANRs.
-        CompletableFuture.runAsync(() -> {
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
             AudioHelper.CapturedAudio capturedAudio = new AudioHelper.CapturedAudio(audioRecord);
             double powerSpectrumNotFrequency = capturedAudio.getPowerSpectrum(FREQUENCY + 100);
             double powerSpectrumAtFrequency = capturedAudio.getPowerSpectrum(FREQUENCY);
+            audioRecord.release();
 
             Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
             intent.putExtra(EXTRA_POWER_SPECTRUM_NOT_FREQUENCY, powerSpectrumNotFrequency);
             intent.putExtra(EXTRA_POWER_SPECTRUM_AT_FREQUENCY, powerSpectrumAtFrequency);
             sendBroadcast(intent);
+            finish();
+        });
+    }
 
+    private void recordAudioToByteArray(AudioRecord audioRecord) {
+        // Read from the audio record asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            byte[] audioData = new byte[BUFFER_SIZE_IN_BYTES];
+            while (true) {
+                int bytesRead = audioRecord.read(audioData, 0, audioData.length);
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            byte value = 0;
+            for (int i = 0; i < audioData.length; i++) {
+                if (audioData[i] != 0) {
+                    value = audioData[i];
+                    break;
+                }
+            }
             audioRecord.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            intent.putExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE, value);
+            sendBroadcast(intent);
+            finish();
+        });
+    }
+
+    private void recordAudioToShortArray(AudioRecord audioRecord) {
+        // Read from the audio record asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            short[] audioData = new short[BUFFER_SIZE_IN_BYTES / 2];
+            while (true) {
+                int bytesRead = audioRecord.read(audioData, 0, audioData.length);
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            short value = 0;
+            for (int i = 0; i < audioData.length; i++) {
+                if (audioData[i] != 0) {
+                    value = audioData[i];
+                    break;
+                }
+            }
+            audioRecord.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            intent.putExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE, value);
+            sendBroadcast(intent);
+            finish();
+        });
+    }
+
+    private void recordAudioToFloatArray(AudioRecord audioRecord) {
+        // Read from the audio record asynchronously to avoid ANRs.
+        Future<?> unusedFuture = CompletableFuture.runAsync(() -> {
+            float[] audioData = new float[BUFFER_SIZE_IN_BYTES / 4];
+            while (true) {
+                int bytesRead = audioRecord.read(audioData, 0, audioData.length, READ_BLOCKING);
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            float value = 0f;
+            for (int i = 0; i < audioData.length; i++) {
+                if (Float.compare(audioData[i], 0.0f) != 0) {
+                    value = audioData[i];
+                    break;
+                }
+            }
+            audioRecord.release();
+
+            Intent intent = new Intent(ACTION_SEND_ACTIVITY_RESULT);
+            intent.putExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE, value);
+            sendBroadcast(intent);
             finish();
         });
     }
diff --git a/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/ActivityResultReceiver.java b/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/ActivityResultReceiver.java
index be3ca7c..7073aeb 100644
--- a/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/ActivityResultReceiver.java
+++ b/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/ActivityResultReceiver.java
@@ -37,6 +37,9 @@
     /** Extra for sending the computed power spectrum off expected audio frequency. */
     public static final String EXTRA_POWER_SPECTRUM_NOT_FREQUENCY = "powerSpectrumNotFrequency";
 
+    /** Extra for sending the value of recorded audio data. */
+    public static final String EXTRA_LAST_RECORDED_NONZERO_VALUE = "lastRecordedNonZeroValue";
+
     public interface Callback {
         void onActivityResult(Intent data);
     }
diff --git a/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/AudioHelper.java b/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/AudioHelper.java
index 15b4e5a..16f67cc2 100644
--- a/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/AudioHelper.java
+++ b/tests/tests/virtualdevice/common/src/android/virtualdevice/cts/common/AudioHelper.java
@@ -16,10 +16,15 @@
 
 package android.virtualdevice.cts.common;
 
+import static android.media.AudioRecord.READ_BLOCKING;
+import static android.media.AudioRecord.READ_NON_BLOCKING;
+
+import android.annotation.IntDef;
 import android.companion.virtual.audio.AudioCapture;
-import android.media.AudioFormat;
 import android.media.AudioRecord;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
@@ -33,17 +38,44 @@
     /** Tells the activity to record audio for testing. */
     public static final String ACTION_RECORD_AUDIO = "android.virtualdevice.cts.RECORD_AUDIO";
 
+    /** Tells the activity to play or record for which audio data type. */
+    public static final String EXTRA_AUDIO_DATA_TYPE = "audio_data_type";
+
+    @IntDef({
+            BYTE_BUFFER,
+            BYTE_ARRAY,
+            SHORT_ARRAY,
+            FLOAT_ARRAY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DataType {}
+
+    public static final int BYTE_BUFFER = 1;
+    public static final int BYTE_ARRAY = 2;
+    public static final int SHORT_ARRAY = 3;
+    public static final int FLOAT_ARRAY = 4;
+
+    /** Values for read and write verification. */
+    public static final byte BYTE_VALUE = 8;
+    public static final short SHORT_VALUE = 16;
+    public static final float FLOAT_VALUE = 0.8f;
+
     /** Constants of audio config for testing. */
     public static final int FREQUENCY = 264;
     public static final int SAMPLE_RATE = 44100;
     public static final int CHANNEL_COUNT = 1;
     public static final int AMPLITUDE = 32767;
     public static final int BUFFER_SIZE_IN_BYTES = 65536;
+    public static final int NUMBER_OF_SAMPLES = computeNumSamples(/* timeMs= */ 1000, SAMPLE_RATE,
+            CHANNEL_COUNT);
 
     public static class CapturedAudio {
-        private final int mSamplingRate;
-        private final int mChannelCount;
-        private final ByteBuffer mCapturedData;
+        private int mSamplingRate;
+        private int mChannelCount;
+        private ByteBuffer mCapturedData;
+        private byte mByteValue;
+        private short mShortValue;
+        private float mFloatValue;
 
         public CapturedAudio(AudioRecord audioRecord) {
             mSamplingRate = audioRecord.getSampleRate();
@@ -62,15 +94,18 @@
             }
         }
 
-        public CapturedAudio(AudioCapture audioCapture, AudioFormat audioFormat) {
-            mSamplingRate = audioFormat.getSampleRate();
-            mChannelCount = audioFormat.getChannelCount();
-            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE_IN_BYTES).order(
-                    ByteOrder.nativeOrder());
+        public CapturedAudio(AudioCapture audioCapture, ByteBuffer byteBuffer, int readMode) {
+            mSamplingRate = audioCapture.getFormat().getSampleRate();
+            mChannelCount = audioCapture.getFormat().getChannelCount();
             while (true) {
                 // Read the first buffer with non-zero data
                 byteBuffer.clear();
-                int bytesRead = audioCapture.read(byteBuffer, BUFFER_SIZE_IN_BYTES);
+                int bytesRead;
+                if (readMode == READ_BLOCKING || readMode == READ_NON_BLOCKING) {
+                    bytesRead = audioCapture.read(byteBuffer, BUFFER_SIZE_IN_BYTES, readMode);
+                } else {
+                    bytesRead = audioCapture.read(byteBuffer, BUFFER_SIZE_IN_BYTES);
+                }
                 if (bytesRead == 0 || isAllZero(byteBuffer)) {
                     continue;
                 }
@@ -79,9 +114,79 @@
             }
         }
 
+        public CapturedAudio(AudioCapture audioCapture, byte[] audioData, int readMode) {
+            while (true) {
+                int bytesRead;
+                if (readMode == READ_BLOCKING || readMode == READ_NON_BLOCKING) {
+                    bytesRead = audioCapture.read(audioData, 0, audioData.length, readMode);
+                } else {
+                    bytesRead = audioCapture.read(audioData, 0, audioData.length);
+                }
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            for (int i = 0; i < audioData.length; i++) {
+                if (audioData[i] != 0) {
+                    mByteValue = audioData[i];
+                    break;
+                }
+            }
+        }
+
+        public CapturedAudio(AudioCapture audioCapture, short[] audioData, int readMode) {
+            while (true) {
+                int bytesRead;
+                if (readMode == READ_BLOCKING || readMode == READ_NON_BLOCKING) {
+                    bytesRead = audioCapture.read(audioData, 0, audioData.length, readMode);
+                } else {
+                    bytesRead = audioCapture.read(audioData, 0, audioData.length);
+                }
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            for (int i = 0; i < audioData.length; i++) {
+                if (audioData[i] != 0) {
+                    mShortValue = audioData[i];
+                    break;
+                }
+            }
+        }
+
+        public CapturedAudio(AudioCapture audioCapture, float[] audioData, int readMode) {
+            while (true) {
+                int bytesRead = audioCapture.read(audioData, 0, audioData.length, readMode);
+                if (bytesRead == 0) {
+                    continue;
+                }
+                break;
+            }
+            for (int i = 0; i < audioData.length; i++) {
+                if (audioData[i] != 0) {
+                    mFloatValue = audioData[i];
+                    break;
+                }
+            }
+        }
+
         public double getPowerSpectrum(int frequency) {
             return getCapturedPowerSpectrum(mSamplingRate, mChannelCount, mCapturedData, frequency);
         }
+
+        public byte getByteValue() {
+            return mByteValue;
+        }
+
+        public short getShortValue() {
+            return mShortValue;
+        }
+
+        public float getFloatValue() {
+            return mFloatValue;
+        }
     }
 
     public static int computeNumSamples(int timeMs, int samplingRate, int channelCount) {
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
index 789e63b..344cccc 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
@@ -71,6 +71,7 @@
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
+import java.util.function.IntConsumer;
 
 /**
  * Tests for activity management, like launching and listening to activity change events, in the
@@ -100,7 +101,7 @@
     @Mock
     private VirtualDisplay.Callback mVirtualDisplayCallback;
     @Mock
-    private VirtualDeviceManager.LaunchCallback mLaunchCallback;
+    private IntConsumer mLaunchCompleteListener;
     @Nullable private ServiceConnectionFuture<IStreamedTestApp> mServiceConnection;
     @Mock
     private OnReceiveResultListener mOnReceiveResultListener;
@@ -254,10 +255,11 @@
                 mVirtualDisplayCallback);
 
         mVirtualDevice.launchPendingIntent(virtualDisplay.getDisplay().getDisplayId(),
-                pendingIntent, Runnable::run, mLaunchCallback);
+                pendingIntent, Runnable::run, mLaunchCompleteListener);
 
         verify(mOnReceiveResultListener, timeout(5000)).onReceiveResult(
                 eq(Activity.RESULT_OK), nullable(Bundle.class));
+        verify(mLaunchCompleteListener).accept(eq(VirtualDeviceManager.LAUNCH_SUCCESS));
     }
 
     @Test
@@ -281,10 +283,11 @@
         mVirtualDevice.launchPendingIntent(
                 virtualDisplay.getDisplay().getDisplayId(),
                 pendingIntent, Runnable::run,
-                mLaunchCallback);
+                mLaunchCompleteListener);
 
         verify(mOnReceiveResultListener, timeout(5000)).onReceiveResult(
                 eq(Activity.RESULT_OK), nullable(Bundle.class));
+        verify(mLaunchCompleteListener).accept(eq(VirtualDeviceManager.LAUNCH_SUCCESS));
     }
 
     @Test
@@ -309,10 +312,11 @@
                 virtualDisplay.getDisplay().getDisplayId(),
                 pendingIntent,
                 Runnable::run,
-                mLaunchCallback);
+                mLaunchCompleteListener);
 
         verify(mOnReceiveResultListener, after(5000).never()).onReceiveResult(
                 eq(Activity.RESULT_OK), nullable(Bundle.class));
+        verify(mLaunchCompleteListener).accept(eq(VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY));
     }
 
     private IStreamedTestApp getTestAppService() throws Exception {
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
index 9cb839d..d39ee52 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/VirtualAudioTest.java
@@ -25,16 +25,34 @@
 import static android.Manifest.permission.WAKE_LOCK;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
 import static android.media.AudioFormat.CHANNEL_IN_MONO;
-import static android.media.AudioFormat.CHANNEL_OUT_MONO;
 import static android.media.AudioFormat.ENCODING_PCM_16BIT;
+import static android.media.AudioFormat.ENCODING_PCM_FLOAT;
+import static android.media.AudioRecord.READ_BLOCKING;
+import static android.media.AudioRecord.RECORDSTATE_RECORDING;
+import static android.media.AudioRecord.RECORDSTATE_STOPPED;
+import static android.media.AudioTrack.PLAYSTATE_PLAYING;
+import static android.media.AudioTrack.PLAYSTATE_STOPPED;
+import static android.media.AudioTrack.WRITE_BLOCKING;
+import static android.media.AudioTrack.WRITE_NON_BLOCKING;
+import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_LAST_RECORDED_NONZERO_VALUE;
 import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_POWER_SPECTRUM_AT_FREQUENCY;
 import static android.virtualdevice.cts.common.ActivityResultReceiver.EXTRA_POWER_SPECTRUM_NOT_FREQUENCY;
 import static android.virtualdevice.cts.common.AudioHelper.ACTION_PLAY_AUDIO;
 import static android.virtualdevice.cts.common.AudioHelper.ACTION_RECORD_AUDIO;
 import static android.virtualdevice.cts.common.AudioHelper.AMPLITUDE;
+import static android.virtualdevice.cts.common.AudioHelper.BUFFER_SIZE_IN_BYTES;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_BUFFER;
+import static android.virtualdevice.cts.common.AudioHelper.BYTE_VALUE;
 import static android.virtualdevice.cts.common.AudioHelper.CHANNEL_COUNT;
+import static android.virtualdevice.cts.common.AudioHelper.EXTRA_AUDIO_DATA_TYPE;
+import static android.virtualdevice.cts.common.AudioHelper.FLOAT_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.FLOAT_VALUE;
 import static android.virtualdevice.cts.common.AudioHelper.FREQUENCY;
+import static android.virtualdevice.cts.common.AudioHelper.NUMBER_OF_SAMPLES;
 import static android.virtualdevice.cts.common.AudioHelper.SAMPLE_RATE;
+import static android.virtualdevice.cts.common.AudioHelper.SHORT_ARRAY;
+import static android.virtualdevice.cts.common.AudioHelper.SHORT_VALUE;
 import static android.virtualdevice.cts.util.TestAppHelper.MAIN_ACTIVITY_COMPONENT;
 import static android.virtualdevice.cts.util.VirtualDeviceTestUtils.createActivityOptions;
 
@@ -59,7 +77,6 @@
 import android.content.pm.PackageManager;
 import android.hardware.display.VirtualDisplay;
 import android.media.AudioFormat;
-import android.media.AudioTrack;
 import android.platform.test.annotations.AppModeFull;
 import android.virtualdevice.cts.common.ActivityResultReceiver;
 import android.virtualdevice.cts.common.AudioHelper;
@@ -81,6 +98,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 /**
  * Tests for injection and capturing of audio from streamed apps
@@ -101,18 +119,7 @@
 
     private static final VirtualDeviceParams DEFAULT_VIRTUAL_DEVICE_PARAMS =
             new VirtualDeviceParams.Builder().build();
-    private static final AudioFormat AUDIO_CAPTURE_FORMAT =
-            new AudioFormat.Builder()
-                    .setSampleRate(SAMPLE_RATE)
-                    .setEncoding(ENCODING_PCM_16BIT)
-                    .setChannelMask(CHANNEL_IN_MONO)
-                    .build();
-    private static final AudioFormat AUDIO_INJECTION_FORMAT =
-            new AudioFormat.Builder()
-                    .setSampleRate(SAMPLE_RATE)
-                    .setEncoding(ENCODING_PCM_16BIT)
-                    .setChannelMask(CHANNEL_OUT_MONO)
-                    .build();
+
     @Rule
     public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
             InstrumentationRegistry.getInstrumentation().getUiAutomation(),
@@ -160,8 +167,6 @@
                 /* flags= */ VIRTUAL_DISPLAY_FLAG_TRUSTED,
                 Runnable::run,
                 mVirtualDisplayCallback);
-        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
-                mVirtualDisplay, /* executor= */ null, mAudioConfigurationChangeCallback);
     }
 
     @After
@@ -178,69 +183,334 @@
     }
 
     @Test
-    public void audioCapture_shouldCaptureAppPlaybackFrequency() {
-        AudioCapture audioCapture = mVirtualAudioDevice.startAudioCapture(AUDIO_CAPTURE_FORMAT);
+    public void audioCapture_createCorrectly() {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, /* callback= */ null);
+        AudioFormat audioFormat = createCaptureFormat(ENCODING_PCM_16BIT);
+        AudioCapture audioCapture = mVirtualAudioDevice.startAudioCapture(audioFormat);
         assertThat(audioCapture).isNotNull();
+        assertThat(audioCapture.getFormat()).isEqualTo(audioFormat);
+        assertThat(mVirtualAudioDevice.getAudioCapture()).isEqualTo(audioCapture);
 
-        InstrumentationRegistry.getInstrumentation().getTargetContext().startActivity(
-                createPlayAudioIntent(), createActivityOptions(mVirtualDisplay));
-        verify(mAudioConfigurationChangeCallback, timeout(5000).atLeastOnce())
-                .onPlaybackConfigChanged(any());
-
-        AudioHelper.CapturedAudio capturedAudio = new AudioHelper.CapturedAudio(audioCapture,
-                AUDIO_CAPTURE_FORMAT);
-        assertThat(capturedAudio.getPowerSpectrum(FREQUENCY + 100))
-                .isLessThan(POWER_THRESHOLD_FOR_ABSENT);
-        assertThat(capturedAudio.getPowerSpectrum(FREQUENCY))
-                .isGreaterThan(POWER_THRESHOLD_FOR_PRESENT);
+        audioCapture.startRecording();
+        assertThat(audioCapture.getRecordingState()).isEqualTo(RECORDSTATE_RECORDING);
+        audioCapture.stop();
+        assertThat(audioCapture.getRecordingState()).isEqualTo(RECORDSTATE_STOPPED);
     }
 
     @Test
-    public void audioInjection_appShouldRecordInjectedFrequency() {
-        AudioInjection audioInjection = mVirtualAudioDevice.startAudioInjection(
-                AUDIO_INJECTION_FORMAT);
+    public void audioInjection_createCorrectly() {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, /* callback= */ null);
+        AudioFormat audioFormat = createInjectionFormat(ENCODING_PCM_16BIT);
+        AudioInjection audioInjection = mVirtualAudioDevice.startAudioInjection(audioFormat);
         assertThat(audioInjection).isNotNull();
+        assertThat(audioInjection.getFormat()).isEqualTo(audioFormat);
+        assertThat(mVirtualAudioDevice.getAudioInjection()).isEqualTo(audioInjection);
+
+        audioInjection.play();
+        assertThat(audioInjection.getPlayState()).isEqualTo(PLAYSTATE_PLAYING);
+        audioInjection.stop();
+        assertThat(audioInjection.getPlayState()).isEqualTo(PLAYSTATE_STOPPED);
+    }
+
+    @Test
+    public void audioCapture_receivesAudioConfigurationChangeCallback() {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, mAudioConfigurationChangeCallback);
+        AudioFormat audioFormat = createCaptureFormat(ENCODING_PCM_16BIT);
+        mVirtualAudioDevice.startAudioCapture(audioFormat);
 
         ActivityResultReceiver activityResultReceiver = new ActivityResultReceiver(
                 getApplicationContext());
         activityResultReceiver.register(mActivityResultCallback);
         InstrumentationRegistry.getInstrumentation().getTargetContext().startActivity(
-                createAudioRecordIntent(), createActivityOptions(mVirtualDisplay));
-
-        int numSamples = AudioHelper.computeNumSamples(/* timeMs= */ 1000, SAMPLE_RATE,
-                CHANNEL_COUNT);
-        ByteBuffer audioData = AudioHelper.createAudioData(
-                SAMPLE_RATE, numSamples, CHANNEL_COUNT, FREQUENCY, AMPLITUDE);
-        int remaining = audioData.remaining();
-        while (remaining > 0) {
-            remaining -= audioInjection.write(
-                    audioData, audioData.remaining(), AudioTrack.WRITE_BLOCKING);
-        }
+                createPlayAudioIntent(BYTE_BUFFER),
+                createActivityOptions(mVirtualDisplay));
+        verify(mAudioConfigurationChangeCallback, timeout(5000).atLeastOnce())
+                .onPlaybackConfigChanged(any());
         verify(mActivityResultCallback, timeout(5000)).onActivityResult(
                 mIntentCaptor.capture());
-        verify(mAudioConfigurationChangeCallback, timeout(5000).atLeastOnce())
-                .onRecordingConfigChanged(any());
-
-        Intent intent = mIntentCaptor.getValue();
-        assertThat(intent).isNotNull();
-        double powerSpectrumAtFrequency = intent.getDoubleExtra(EXTRA_POWER_SPECTRUM_AT_FREQUENCY,
-                0);
-        double powerSpectrumNotFrequency = intent.getDoubleExtra(EXTRA_POWER_SPECTRUM_NOT_FREQUENCY,
-                0);
-        assertThat(powerSpectrumNotFrequency).isLessThan(POWER_THRESHOLD_FOR_ABSENT);
-        assertThat(powerSpectrumAtFrequency).isGreaterThan(POWER_THRESHOLD_FOR_PRESENT);
-
         activityResultReceiver.unregister();
     }
 
-    private static Intent createPlayAudioIntent() {
+    @Test
+    public void audioInjection_receivesAudioConfigurationChangeCallback() {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, mAudioConfigurationChangeCallback);
+        AudioFormat audioFormat = createInjectionFormat(ENCODING_PCM_16BIT);
+        mVirtualAudioDevice.startAudioInjection(audioFormat);
+
+        ActivityResultReceiver activityResultReceiver = new ActivityResultReceiver(
+                getApplicationContext());
+        activityResultReceiver.register(mActivityResultCallback);
+        InstrumentationRegistry.getInstrumentation().getTargetContext().startActivity(
+                createAudioRecordIntent(BYTE_BUFFER),
+                createActivityOptions(mVirtualDisplay));
+        verify(mAudioConfigurationChangeCallback, timeout(5000).atLeastOnce())
+                .onRecordingConfigChanged(any());
+        verify(mActivityResultCallback, timeout(5000)).onActivityResult(
+                mIntentCaptor.capture());
+        activityResultReceiver.unregister();
+    }
+
+    @Test
+    public void audioCapture_readByteBuffer_shouldCaptureAppPlaybackFrequency() {
+        runAudioCaptureTest(BYTE_BUFFER, /* readMode= */ -1);
+    }
+
+    @Test
+    public void audioCapture_readByteBufferBlocking_shouldCaptureAppPlaybackFrequency() {
+        runAudioCaptureTest(BYTE_BUFFER, /* readMode= */ READ_BLOCKING);
+    }
+
+    @Test
+    public void audioCapture_readByteArray_shouldCaptureAppPlaybackData() {
+        runAudioCaptureTest(BYTE_ARRAY, /* readMode= */ -1);
+    }
+
+    @Test
+    public void audioCapture_readByteArrayBlocking_shouldCaptureAppPlaybackData() {
+        runAudioCaptureTest(BYTE_ARRAY, /* readMode= */ READ_BLOCKING);
+    }
+
+    @Test
+    public void audioCapture_readShortArray_shouldCaptureAppPlaybackData() {
+        runAudioCaptureTest(SHORT_ARRAY, /* readMode= */ -1);
+    }
+
+    @Test
+    public void audioCapture_readShortArrayBlocking_shouldCaptureAppPlaybackData() {
+        runAudioCaptureTest(SHORT_ARRAY, /* readMode= */ READ_BLOCKING);
+    }
+
+    @Test
+    public void audioCapture_readFloatArray_shouldCaptureAppPlaybackData() {
+        runAudioCaptureTest(FLOAT_ARRAY, /* readMode= */ READ_BLOCKING);
+    }
+
+    @Test
+    public void audioInjection_writeByteBuffer_appShouldRecordInjectedFrequency() {
+        runAudioInjectionTest(BYTE_BUFFER, /* writeMode= */
+                WRITE_BLOCKING, /* timestamp= */ 0);
+    }
+
+    @Test
+    public void audioInjection_writeByteBufferWithTimestamp_appShouldRecordInjectedFrequency() {
+        runAudioInjectionTest(BYTE_BUFFER, /* writeMode= */
+                WRITE_BLOCKING, /* timestamp= */ 50);
+    }
+
+    @Test
+    public void audioInjection_writeByteArray_appShouldRecordInjectedData() {
+        runAudioInjectionTest(BYTE_ARRAY, /* writeMode= */ -1, /* timestamp= */ 0);
+    }
+
+    @Test
+    public void audioInjection_writeByteArrayBlocking_appShouldRecordInjectedData() {
+        runAudioInjectionTest(BYTE_ARRAY, /* writeMode= */ WRITE_BLOCKING, /* timestamp= */
+                0);
+    }
+
+    @Test
+    public void audioInjection_writeShortArray_appShouldRecordInjectedData() {
+        runAudioInjectionTest(SHORT_ARRAY, /* writeMode= */ -1, /* timestamp= */ 0);
+    }
+
+    @Test
+    public void audioInjection_writeShortArrayBlocking_appShouldRecordInjectedData() {
+        runAudioInjectionTest(SHORT_ARRAY, /* writeMode= */
+                WRITE_BLOCKING, /* timestamp= */ 0);
+    }
+
+    @Test
+    public void audioInjection_writeFloatArray_appShouldRecordInjectedData() {
+        runAudioInjectionTest(FLOAT_ARRAY, /* writeMode= */
+                WRITE_BLOCKING, /* timestamp= */ 0);
+    }
+
+    private void runAudioCaptureTest(@AudioHelper.DataType int dataType, int readMode) {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, /* callback= */ null);
+        int encoding = dataType == FLOAT_ARRAY ? ENCODING_PCM_FLOAT : ENCODING_PCM_16BIT;
+        AudioCapture audioCapture = mVirtualAudioDevice.startAudioCapture(
+                createCaptureFormat(encoding));
+
+        ActivityResultReceiver activityResultReceiver = new ActivityResultReceiver(
+                getApplicationContext());
+        activityResultReceiver.register(mActivityResultCallback);
+        InstrumentationRegistry.getInstrumentation().getTargetContext().startActivity(
+                createPlayAudioIntent(dataType),
+                createActivityOptions(mVirtualDisplay));
+
+        AudioHelper.CapturedAudio capturedAudio = null;
+        switch (dataType) {
+            case BYTE_BUFFER:
+                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE_IN_BYTES).order(
+                        ByteOrder.nativeOrder());
+                capturedAudio = new AudioHelper.CapturedAudio(audioCapture, byteBuffer, readMode);
+                assertThat(capturedAudio.getPowerSpectrum(FREQUENCY + 100))
+                        .isLessThan(POWER_THRESHOLD_FOR_ABSENT);
+                assertThat(capturedAudio.getPowerSpectrum(FREQUENCY))
+                        .isGreaterThan(POWER_THRESHOLD_FOR_PRESENT);
+                break;
+            case BYTE_ARRAY:
+                byte[] byteArray = new byte[BUFFER_SIZE_IN_BYTES];
+                capturedAudio = new AudioHelper.CapturedAudio(audioCapture, byteArray, readMode);
+                assertThat(capturedAudio.getByteValue()).isEqualTo(BYTE_VALUE);
+                break;
+            case SHORT_ARRAY:
+                short[] shortArray = new short[BUFFER_SIZE_IN_BYTES / 2];
+                capturedAudio = new AudioHelper.CapturedAudio(audioCapture, shortArray, readMode);
+                assertThat(capturedAudio.getShortValue()).isEqualTo(SHORT_VALUE);
+                break;
+            case FLOAT_ARRAY:
+                float[] floatArray = new float[BUFFER_SIZE_IN_BYTES / 4];
+                capturedAudio = new AudioHelper.CapturedAudio(audioCapture, floatArray, readMode);
+                float roundOffError = Math.abs(capturedAudio.getFloatValue() - FLOAT_VALUE);
+                assertThat(roundOffError).isLessThan(0.001f);
+                break;
+        }
+
+        verify(mActivityResultCallback, timeout(5000)).onActivityResult(
+                mIntentCaptor.capture());
+        activityResultReceiver.unregister();
+    }
+
+    private void runAudioInjectionTest(@AudioHelper.DataType int dataType, int writeMode,
+            long timestamp) {
+        mVirtualAudioDevice = mVirtualDevice.createVirtualAudioDevice(
+                mVirtualDisplay, /* executor= */ null, /* callback= */ null);
+        int encoding = dataType == FLOAT_ARRAY ? ENCODING_PCM_FLOAT : ENCODING_PCM_16BIT;
+        AudioInjection audioInjection = mVirtualAudioDevice.startAudioInjection(
+                createInjectionFormat(encoding));
+
+        ActivityResultReceiver activityResultReceiver = new ActivityResultReceiver(
+                getApplicationContext());
+        activityResultReceiver.register(mActivityResultCallback);
+        InstrumentationRegistry.getInstrumentation().getTargetContext().startActivity(
+                createAudioRecordIntent(dataType),
+                createActivityOptions(mVirtualDisplay));
+
+        int remaining;
+        switch (dataType) {
+            case BYTE_BUFFER:
+                ByteBuffer byteBuffer = AudioHelper.createAudioData(
+                        SAMPLE_RATE, NUMBER_OF_SAMPLES, CHANNEL_COUNT, FREQUENCY, AMPLITUDE);
+                remaining = byteBuffer.remaining();
+                while (remaining > 0) {
+                    if (timestamp != 0) {
+                        remaining -= audioInjection.write(byteBuffer, byteBuffer.remaining(),
+                                writeMode, timestamp);
+                    } else {
+                        remaining -= audioInjection.write(byteBuffer, byteBuffer.remaining(),
+                                writeMode);
+                    }
+                }
+                break;
+            case BYTE_ARRAY:
+                byte[] byteArray = new byte[NUMBER_OF_SAMPLES];
+                for (int i = 0; i < byteArray.length; i++) {
+                    byteArray[i] = BYTE_VALUE;
+                }
+                remaining = byteArray.length;
+                while (remaining > 0) {
+                    if (writeMode == WRITE_BLOCKING || writeMode == WRITE_NON_BLOCKING) {
+                        remaining -= audioInjection.write(byteArray, 0, byteArray.length,
+                                writeMode);
+                    } else {
+                        remaining -= audioInjection.write(byteArray, 0, byteArray.length);
+                    }
+                }
+                break;
+            case SHORT_ARRAY:
+                short[] shortArray = new short[NUMBER_OF_SAMPLES];
+                for (int i = 0; i < shortArray.length; i++) {
+                    shortArray[i] = SHORT_VALUE;
+                }
+                remaining = shortArray.length;
+                while (remaining > 0) {
+                    if (writeMode == WRITE_BLOCKING || writeMode == WRITE_NON_BLOCKING) {
+                        remaining -= audioInjection.write(shortArray, 0, shortArray.length,
+                                writeMode);
+                    } else {
+                        remaining -= audioInjection.write(shortArray, 0, shortArray.length);
+                    }
+                }
+                break;
+            case FLOAT_ARRAY:
+                float[] floatArray = new float[NUMBER_OF_SAMPLES];
+                for (int i = 0; i < floatArray.length; i++) {
+                    floatArray[i] = FLOAT_VALUE;
+                }
+                remaining = floatArray.length;
+                while (remaining > 0) {
+                    remaining -= audioInjection.write(floatArray, 0, floatArray.length, writeMode);
+                }
+                break;
+        }
+
+        verify(mActivityResultCallback, timeout(5000)).onActivityResult(
+                mIntentCaptor.capture());
+        Intent intent = mIntentCaptor.getValue();
+        assertThat(intent).isNotNull();
+        activityResultReceiver.unregister();
+
+        switch (dataType) {
+            case BYTE_BUFFER:
+                double powerSpectrumAtFrequency = intent.getDoubleExtra(
+                        EXTRA_POWER_SPECTRUM_AT_FREQUENCY,
+                        0);
+                double powerSpectrumNotFrequency = intent.getDoubleExtra(
+                        EXTRA_POWER_SPECTRUM_NOT_FREQUENCY,
+                        0);
+                assertThat(powerSpectrumNotFrequency).isLessThan(POWER_THRESHOLD_FOR_ABSENT);
+                assertThat(powerSpectrumAtFrequency).isGreaterThan(POWER_THRESHOLD_FOR_PRESENT);
+                break;
+            case BYTE_ARRAY:
+                byte byteValue = intent.getByteExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE,
+                        Byte.MIN_VALUE);
+                assertThat(byteValue).isEqualTo(BYTE_VALUE);
+                break;
+            case SHORT_ARRAY:
+                short shortValue = intent.getShortExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE,
+                        Short.MIN_VALUE);
+                assertThat(shortValue).isEqualTo(SHORT_VALUE);
+                break;
+            case FLOAT_ARRAY:
+                float floatValue = intent.getFloatExtra(EXTRA_LAST_RECORDED_NONZERO_VALUE, 0);
+                float roundOffError = Math.abs(floatValue - FLOAT_VALUE);
+                assertThat(roundOffError).isLessThan(0.001f);
+                break;
+        }
+    }
+
+    private static AudioFormat createCaptureFormat(int encoding) {
+        return new AudioFormat.Builder()
+                .setSampleRate(SAMPLE_RATE)
+                .setEncoding(encoding)
+                .setChannelMask(CHANNEL_IN_MONO)
+                .build();
+    }
+
+    private static AudioFormat createInjectionFormat(int encoding) {
+        return new AudioFormat.Builder()
+                .setSampleRate(SAMPLE_RATE)
+                .setEncoding(encoding)
+                .setChannelMask(CHANNEL_IN_MONO)
+                .build();
+    }
+
+    private static Intent createPlayAudioIntent(@AudioHelper.DataType int dataType) {
         return new Intent(ACTION_PLAY_AUDIO)
+                .putExtra(EXTRA_AUDIO_DATA_TYPE, dataType)
                 .setComponent(MAIN_ACTIVITY_COMPONENT)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
     }
 
-    private static Intent createAudioRecordIntent() {
+    private static Intent createAudioRecordIntent(@AudioHelper.DataType int dataType) {
         return new Intent(ACTION_RECORD_AUDIO)
+                .putExtra(EXTRA_AUDIO_DATA_TYPE, dataType)
                 .setComponent(MAIN_ACTIVITY_COMPONENT)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
     }
diff --git a/tests/tests/voiceinteraction/TEST_MAPPING b/tests/tests/voiceinteraction/TEST_MAPPING
index b22a259..7c84b9c 100644
--- a/tests/tests/voiceinteraction/TEST_MAPPING
+++ b/tests/tests/voiceinteraction/TEST_MAPPING
@@ -5,6 +5,19 @@
       "options": [
         {
           "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        // TODO(b/225076204): Remove the following four test cases after fixing the test fail.
+        {
+          "exclude-filter": "android.voiceinteraction.cts.HotwordDetectionServiceBasicTest#testHotwordDetectionService_createDetectorTwiceQuickly_triggerSuccess"
+        },
+        {
+          "exclude-filter": "android.voiceinteraction.cts.HotwordDetectionServiceBasicTest#testHotwordDetectionService_onDetectFromDsp_success"
+        },
+        {
+          "exclude-filter": "android.voiceinteraction.cts.HotwordDetectionServiceBasicTest#testHotwordDetectionService_onDetectFromExternalSource_success"
+        },
+        {
+          "exclude-filter": "android.voiceinteraction.cts.HotwordDetectionServiceBasicTest#testHotwordDetectionService_onDetectFromMic_success"
         }
       ]
     }
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index 4a152bc..be61d93 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -163,6 +163,7 @@
     public static final String DIRECT_ACTIONS_ACTIVITY_CMD_DESTROYED_INTERACTOR =
             "destroyedInteractor";
     public static final String DIRECT_ACTIONS_ACTIVITY_CMD_INVALIDATE_ACTIONS = "invalidateActions";
+    public static final String DIRECT_ACTIONS_ACTIVITY_CMD_GET_PACKAGE_NAME = "getpackagename";
 
     public static final String DIRECT_ACTIONS_RESULT_PERFORMED = "performed";
     public static final String DIRECT_ACTIONS_RESULT_CANCELLED = "cancelled";
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
index 4ece6b9..3c74da6 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
@@ -79,6 +79,23 @@
 
     @AppModeFull(reason = "testPerformDirectAction() is enough")
     @Test
+    public void testGetPackageName() throws Exception {
+        mActivityControl.startActivity();
+        mSessionControl.startVoiceInteractionSession();
+        try {
+            // Get the actions to set up the VoiceInteractor
+            mSessionControl.getDirectActions();
+
+            String packageName = mActivityControl.getPackageName();
+            assertThat(packageName).isEqualTo("android.voiceinteraction.service");
+        } finally {
+            mSessionControl.stopVoiceInteractionSession();
+            mActivityControl.finishActivity();
+        }
+    }
+
+    @AppModeFull(reason = "testPerformDirectAction() is enough")
+    @Test
     public void testCancelPerformedDirectAction() throws Exception {
         mActivityControl.startActivity();
         mSessionControl.startVoiceInteractionSession();
@@ -232,6 +249,13 @@
             return result.getBoolean(Utils.DIRECT_ACTIONS_KEY_RESULT);
         }
 
+        private String getPackageName()
+                throws Exception {
+            final Bundle result = executeRemoteCommand(
+                    Utils.DIRECT_ACTIONS_ACTIVITY_CMD_GET_PACKAGE_NAME);
+            return result.getString(Utils.DIRECT_ACTIONS_KEY_RESULT);
+        }
+
         void finishActivity() throws Exception {
             executeRemoteCommand(Utils.VOICE_INTERACTION_ACTIVITY_CMD_FINISH);
         }
@@ -316,3 +340,4 @@
                 .that(Utils.DIRECT_ACTIONS_RESULT_CANCELLED).isEqualTo(status);
     }
 }
+
diff --git a/tests/tests/voiceinteraction/testapp/src/android/voiceinteraction/testapp/DirectActionsActivity.java b/tests/tests/voiceinteraction/testapp/src/android/voiceinteraction/testapp/DirectActionsActivity.java
index 4b6d2e3..7a7c07c 100644
--- a/tests/tests/voiceinteraction/testapp/src/android/voiceinteraction/testapp/DirectActionsActivity.java
+++ b/tests/tests/voiceinteraction/testapp/src/android/voiceinteraction/testapp/DirectActionsActivity.java
@@ -73,6 +73,11 @@
                             Utils.VOICE_INTERACTION_KEY_CALLBACK);
                     invalidateDirectActions(commandCallback);
                 } break;
+                case Utils.DIRECT_ACTIONS_ACTIVITY_CMD_GET_PACKAGE_NAME: {
+                    final RemoteCallback commandCallback = cmdArgs.getParcelable(
+                            Utils.VOICE_INTERACTION_KEY_CALLBACK);
+                    getPackageName(commandCallback);
+                } break;
             }
         });
 
@@ -157,6 +162,14 @@
         callback.sendResult(result);
     }
 
+    private void getPackageName(@NonNull RemoteCallback callback) {
+        String packageName = getVoiceInteractor().getPackageName();
+        final Bundle result = new Bundle();
+        result.putString(Utils.DIRECT_ACTIONS_KEY_RESULT, packageName);
+        Log.v(TAG, "getPackageName(): " + Utils.toBundleString(result));
+        callback.sendResult(result);
+    }
+
     private void doFinish(@NonNull RemoteCallback callback) {
         finish();
         final Bundle result = new Bundle();
diff --git a/tests/tests/widget/Android.bp b/tests/tests/widget/Android.bp
index 414dd0f..98290f0 100644
--- a/tests/tests/widget/Android.bp
+++ b/tests/tests/widget/Android.bp
@@ -24,13 +24,14 @@
         "androidx.annotation_annotation",
         "androidx.test.ext.junit",
         "androidx.test.rules",
-	"ctsdeviceutillegacy-axt",
+        "ctsdeviceutillegacy-axt",
         "mockito-target-minus-junit4",
         "android-common",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
         "platform-test-annotations",
         "truth-prebuilt",
+        "CtsMockInputMethodLib",
     ],
 
     libs: ["android.test.runner"],
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
index 27476fb..f2eb9ef 100644
--- a/tests/tests/widget/AndroidTest.xml
+++ b/tests/tests/widget/AndroidTest.xml
@@ -33,6 +33,16 @@
         <option name="test-file-name" value="CtsWidgetTestCases.apk" />
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <!--
+            MockIME always needs to be installed as a full package, even when CTS is running
+            for instant apps.
+        -->
+        <option name="force-install-mode" value="FULL"/>
+        <option name="test-file-name" value="CtsMockInputMethod.apk" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <!--
             To fail-fast in case test-ime setup somehow failed.  Consider increasing the
diff --git a/tests/tests/widget/src/android/widget/cts/EditTextTest.java b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
index b5f7263..2370562 100755
--- a/tests/tests/widget/src/android/widget/cts/EditTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
@@ -16,6 +16,8 @@
 
 package android.widget.cts;
 
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -27,6 +29,10 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Point;
+import android.os.SystemClock;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.InputType;
@@ -41,6 +47,7 @@
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.KeyEvent;
+import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
@@ -55,6 +62,9 @@
 
 import com.android.compatibility.common.util.CtsKeyEventUtil;
 import com.android.compatibility.common.util.CtsTouchUtils;
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.ImeSettings;
+import com.android.cts.mockime.MockImeSession;
 
 import org.junit.After;
 import org.junit.Before;
@@ -64,6 +74,7 @@
 import org.xmlpull.v1.XmlPullParser;
 
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
 @SmallTest
@@ -722,4 +733,31 @@
         assertEquals(InputType.TYPE_CLASS_TEXT
                 | InputType.TYPE_TEXT_FLAG_ENABLE_TEXT_CONVERSION_SUGGESTIONS, tv.getInputType());
     }
+
+    @Test
+    public void testClickTwice_showIme() throws Throwable {
+        try (MockImeSession imeSession = MockImeSession.create(
+                mInstrumentation.getContext(),
+                mInstrumentation.getUiAutomation(),
+                new ImeSettings.Builder())) {
+
+            clickOnEditText1();
+            mInstrumentation.waitForIdleSync();
+
+            clickOnEditText1();
+            mInstrumentation.waitForIdleSync();
+
+            final ImeEventStream stream = imeSession.openEventStream();
+            expectEvent(stream,
+                    event -> "showSoftInput".equals(event.getEventName()),
+                    TimeUnit.SECONDS.toMillis(2));
+        }
+    }
+
+    private void clickOnEditText1() throws Exception {
+        final UiObject2 object = UiDevice.getInstance(mInstrumentation)
+                .findObject(By.res("android.widget.cts", "edittext_simple1"));
+        object.click();
+        SystemClock.sleep(ViewConfiguration.getDoubleTapTimeout() + 50);
+    }
 }
diff --git a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 711e098..0f0c739 100644
--- a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -670,7 +670,7 @@
         intentFilter.addAction(WifiAwareManager.ACTION_WIFI_AWARE_RESOURCE_CHANGED);
         WifiAwareResourcesBroadcastReceiver receiver = new WifiAwareResourcesBroadcastReceiver();
         mContext.registerReceiver(receiver, intentFilter);
-        final String serviceName = "ValidName";
+        final String serviceName = "PublishName";
 
         WifiAwareSession session = attachAndGetSession();
 
@@ -735,7 +735,7 @@
             return;
         }
 
-        final String serviceName = "ValidName";
+        final String serviceName = "PublishName";
         final int ttlSec = 5;
 
         WifiAwareSession session = attachAndGetSession();
@@ -774,7 +774,7 @@
             return;
         }
 
-        final String serviceName = "ValidName";
+        final String serviceName = "PublishName";
         final String passphrase = "SomePassword";
         final byte[] pmk = "01234567890123456789012345678901".getBytes();
         final byte[] pmkId = "0123456789012345".getBytes();
@@ -845,7 +845,7 @@
         if (!characteristics.isInstantCommunicationModeSupported()) {
             return;
         }
-        final String serviceName = "ValidName";
+        final String serviceName = "PublishName";
         WifiAwareSession session = attachAndGetSession();
 
         PublishConfig publishConfig = new PublishConfig.Builder()
@@ -887,7 +887,7 @@
         intentFilter.addAction(WifiAwareManager.ACTION_WIFI_AWARE_RESOURCE_CHANGED);
         WifiAwareResourcesBroadcastReceiver receiver = new WifiAwareResourcesBroadcastReceiver();
         mContext.registerReceiver(receiver, intentFilter);
-        final String serviceName = "ValidName";
+        final String serviceName = "SubscribeName";
 
         WifiAwareSession session = attachAndGetSession();
 
@@ -963,7 +963,7 @@
         if (!characteristics.isInstantCommunicationModeSupported()) {
             return;
         }
-        final String serviceName = "ValidName";
+        final String serviceName = "SubscribeName";
         WifiAwareSession session = attachAndGetSession();
 
         SubscribeConfig subscribeConfig = new SubscribeConfig.Builder()
@@ -1003,7 +1003,7 @@
             return;
         }
 
-        final String serviceName = "ValidName";
+        final String serviceName = "SubscribeName";
         final int ttlSec = 5;
 
         WifiAwareSession session = attachAndGetSession();
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 2c7605b..479c0eb3 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -177,7 +177,7 @@
     private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000;
     private static final int TEST_WAIT_DURATION_MS = 10_000;
     private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000;
-    private static final int WIFI_PNO_CONNECT_TIMEOUT_MILLIS = 60_000;
+    private static final int WIFI_PNO_CONNECT_TIMEOUT_MILLIS = 90_000;
     private static final int WAIT_MSEC = 60;
     private static final int DURATION_SCREEN_TOGGLE = 2000;
     private static final int DURATION_SETTINGS_TOGGLE = 1_000;
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
index 87cd929..bdec62b 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/TestBase.java
@@ -309,10 +309,10 @@
         }
 
         if (!ap5Ghz.isEmpty()) {
-            s11McScanResult = getHighestRssiScanResult(ap5Ghz.values());
+            s11McScanResult = getRandomScanResult(ap5Ghz.values());
             return;
         }
-        s11McScanResult = getHighestRssiScanResult(ap24Ghz.values());
+        s11McScanResult = getRandomScanResult(ap24Ghz.values());
     }
 
     static Context getContext() {
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index b40c379..2a3f67a 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -83,7 +83,7 @@
     private static final MacAddress MAC = MacAddress.fromString("00:01:02:03:04:05");
 
     // Interval between two ranging request.
-    private static final int intervalMs = 200;
+    private static final int INTERVAL_MS = 1000;
 
     /**
      * Test Wi-Fi RTT ranging operation using ScanResults in request:
@@ -304,7 +304,7 @@
                 numFailures++;
             }
             // Sleep a while to avoid stress AP.
-            Thread.sleep(intervalMs);
+            Thread.sleep(INTERVAL_MS);
         }
 
         // Save results to log
@@ -651,6 +651,7 @@
      */
     private void rangeNon11mcApRequest(RangingRequest request, ScanResult testAp,
             int variationLimit) throws InterruptedException {
+        Thread.sleep(5000);
         List<RangingResult> allResults = new ArrayList<>();
         int numFailures = 0;
         int distanceSum = 0;
@@ -724,7 +725,7 @@
                 numFailures++;
             }
             // Sleep a while to avoid stress AP.
-            Thread.sleep(intervalMs);
+            Thread.sleep(INTERVAL_MS);
         }
         // Save results to log
         int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures;
diff --git a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
index a4c71f8..7a0d6f1 100644
--- a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
@@ -620,12 +620,194 @@
         // Make sure onFinished will not be called twice.
         mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
         mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
         Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
 
         // TODO(b/191417938): add a test to verify startUiTranslation + Activity destroyed.
     }
 
     @Test
+    public void testCallbackRegisteredAfterTranslationStarted() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        // Callback should receive onStarted.
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onStarted(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        pauseUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1)).onPaused(any(String.class));
+
+        resumeUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onResumed(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        finishUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+
+        // Make sure onFinished will not be called twice.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+    }
+
+    @Test
+    public void testCallbackRegisteredAfterTranslationStartedAndPaused() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+        pauseUiTranslation(contentCaptureContext);
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        // Callback should receive onStarted and onPaused events.
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onStarted(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.times(1)).onPaused(any(String.class));
+
+        resumeUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onResumed(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        finishUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+
+        // Make sure onFinished will not be called twice.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+    }
+
+    @Test
+    public void testCallbackRegisteredAfterTranslationStartedPausedAndResumed() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+        pauseUiTranslation(contentCaptureContext);
+
+        resumeUiTranslation(contentCaptureContext);
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        // Callback should receive onStarted event but NOT an onPaused event, because translation
+        // was already resumed prior to registration.
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onStarted(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.never()).onPaused(any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.never())
+                .onResumed(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        finishUiTranslation(contentCaptureContext);
+
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+
+        // Make sure onFinished will not be called twice.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+        Mockito.verify(mockCallback, Mockito.times(1)).onFinished(any(String.class));
+    }
+
+    @Test
+    public void testCallbackRegisteredAfterTranslationFinished() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        UiTranslationManager manager =
+                sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+
+        startUiTranslation(/* shouldPadContent */ false, views, contentCaptureContext);
+
+        pauseUiTranslation(contentCaptureContext);
+
+        resumeUiTranslation(contentCaptureContext);
+
+        finishUiTranslation(contentCaptureContext);
+
+        // Register callback
+        final Executor executor = Executors.newSingleThreadExecutor();
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+
+        // Callback should receive no events.
+        Mockito.verify(mockCallback, Mockito.never())
+                .onStarted(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.never()).onPaused(any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.never())
+                .onResumed(any(ULocale.class), any(ULocale.class), any(String.class));
+
+        Mockito.verify(mockCallback, Mockito.never()).onFinished(any(String.class));
+
+        // Make sure onFinished will not be called at all.
+        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        mActivityScenario = null;
+        SystemClock.sleep(UI_WAIT_TIMEOUT);
+        Mockito.verify(mockCallback, Mockito.never()).onFinished(any(String.class));
+    }
+
+    @Test
     public void testVirtualViewUiTranslation() throws Throwable {
         // Enable CTS ContentCaptureService
         CtsContentCaptureService contentcaptureService = enableContentCaptureService();
diff --git a/tests/video/Android.bp b/tests/video/Android.bp
index 55eaa74..b41a32c 100644
--- a/tests/video/Android.bp
+++ b/tests/video/Android.bp
@@ -24,6 +24,7 @@
         "ctsmediautil",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
+        "cts-media-common",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index 4755b9a..401468f 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -27,6 +27,7 @@
 import android.media.MediaFormat;
 import android.media.cts.CodecImage;
 import android.media.cts.CodecUtils;
+import android.media.cts.TestUtils;
 import android.media.cts.YUVImage;
 import android.os.Build;
 import android.util.Log;
@@ -124,6 +125,8 @@
     private double mRmsErrorMargin;
     private Random mRandom;
 
+    private boolean mUpdatedSwCodec = false;
+
     private class TestConfig {
         public boolean mTestPixels = true;
         public boolean mReportFrameTime = false;
@@ -157,6 +160,8 @@
     protected void setUp() throws Exception {
         mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
         mRmsErrorMargin = PIXEL_RMS_ERROR_MARGIN;
+        mUpdatedSwCodec =
+                !TestUtils.isMainlineModuleFactoryVersion("com.google.android.media.swcodec");
         // Use time as a seed, hoping to prevent checking pixels in the same pattern
         long now = System.currentTimeMillis();
         mRandom = new Random(now);
@@ -819,8 +824,10 @@
         }
 
         if (isPerf) {
+            // allow improvements in mainline-updated google-supplied software codecs.
+            boolean fasterIsOk =  mUpdatedSwCodec & encoderName.startsWith("c2.android.");
             String error = MediaPerfUtils.verifyAchievableFrameRates(
-                    encoderName, mimeType, w, h, measuredFps);
+                    encoderName, mimeType, w, h, fasterIsOk, measuredFps);
             // Performance numbers only make sense on real devices, so skip on non-real devices
             //
             // Also ignore verification on non-preferred ABIs due to the possibility of
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index f4da75b..16287c5 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -70,6 +70,7 @@
 
     <!-- b/183234756, b/80388296, b/110260628, b/159295445, b/159294948 CtsDevicePolicyManagerTestCases -->
     <option name="compatibility:exclude-filter" value="CtsDevicePolicyManagerTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsDevicePolicyTestCases" />
 
     <!-- b/183985653 -->
     <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-EGL.*" />
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 ced6aaf..90ffb97 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
@@ -129,7 +129,7 @@
                     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));
+                                + "exists in testcases/", config.getName(), apkName));
                     }
                     AaptParser res = AaptParser.parse(apkFile);
                     assertNotNull(res);
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 7b6e0d1..8e21bf7 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
@@ -33,6 +33,7 @@
 import com.android.tradefed.invoker.shard.token.TokenProperty;
 import com.android.tradefed.targetprep.DeviceSetup;
 import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.PythonVirtualenvPreparer;
 import com.android.tradefed.testtype.AndroidJUnitTest;
 import com.android.tradefed.testtype.GTest;
 import com.android.tradefed.testtype.HostTest;
@@ -48,6 +49,7 @@
 import org.junit.runners.JUnit4;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -55,6 +57,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
 
 /**
  * Test that configuration in CTS can load and have expected properties.
@@ -62,6 +65,7 @@
 @RunWith(JUnit4.class)
 public class CtsConfigLoadingTest {
 
+    private static final Pattern TODO_BUG_PATTERN = Pattern.compile(".*TODO\\(b/[0-9]+\\).*", Pattern.DOTALL);
     private static final String METADATA_COMPONENT = "component";
     private static final Set<String> KNOWN_COMPONENTS =
             new HashSet<>(
@@ -211,6 +215,7 @@
             if (c.getDeviceConfig().size() > 2) {
                 throw new ConfigurationException(String.format("%s declares more than 2 devices.", config));
             }
+            int deviceCount = 0;
             for (IDeviceConfiguration dConfig : c.getDeviceConfig()) {
                 // Ensure the deprecated ApkInstaller is not used anymore.
                 for (ITargetPreparer prep : dConfig.getTargetPreparers()) {
@@ -238,7 +243,12 @@
                                                  config.getName(), prep.getClass()));
                        }
                     }
+                    if (prep.getClass().isAssignableFrom(PythonVirtualenvPreparer.class)) {
+                        // Ensure each modules has a tracking bug to be imported.
+                        checkPythonModules(config, deviceCount);
+                    }
                 }
+                deviceCount++;
             }
             // We can ensure that Host side tests are not empty.
             for (IRemoteTest test : c.getTests()) {
@@ -412,4 +422,22 @@
         }
         return families;
     }
+
+    /**
+     * For each usage of python virtualenv preparer, make sure we have tracking bugs to import as
+     * source the python libs.
+     */
+    private void checkPythonModules(File config, int deviceCount)
+            throws IOException, ConfigurationException {
+        if (deviceCount != 0) {
+            throw new ConfigurationException(
+                    String.format("%s: PythonVirtualenvPreparer should only be declared for "
+                            + "the first <device> tag in the config", config.getName()));
+        }
+        if (!TODO_BUG_PATTERN.matcher(FileUtil.readStringFromFile(config)).matches()) {
+            throw new ConfigurationException(
+                    String.format("%s: Contains some virtualenv python lib usage but no "
+                            + "tracking bug to import them as source.", config.getName()));
+        }
+    }
 }