Merge changes from topic "retailDemo" into tm-dev

* changes:
  Add cts tests to cover provisioning demo devices
  Add new permission PROVISION_DEMO_DEVICE
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 8516cbf..35cd382 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -253,14 +253,10 @@
 
       # If raw is available and main camera, use it as ground truth.
       ref_img_name_stem = f'{os.path.join(log_path, _NAME)}'
-      if raw_avlb and (fls_physical == fls_logical):
-        ref_fov, cc_ct_gt, aspect_ratio_gt = (
-            image_fov_utils.find_fov_reference(
-                cam, req, props, 'RAW', ref_img_name_stem))
-      else:
-        ref_fov, cc_ct_gt, aspect_ratio_gt = (
-            image_fov_utils.find_fov_reference(
-                cam, req, props, 'JPEG', ref_img_name_stem))
+      raw_bool = raw_avlb and (fls_physical == fls_logical)
+      ref_fov, cc_ct_gt, aspect_ratio_gt = (
+          image_fov_utils.find_fov_reference(
+              cam, req, props, raw_bool, ref_img_name_stem))
 
       run_crop_test = full_or_better and raw_avlb
       if run_crop_test:
diff --git a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
index 3afd554..93e4f11 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
@@ -37,11 +37,14 @@
 _ANGULAR_DIFF_THRESH_API30 = 10  # degrees
 _ANGULAR_DIFF_THRESH_CALIBRATED = 1.8  # degrees (180 deg / 1000 ms * 10 ms)
 _ANGULAR_MOVEMENT_THRESHOLD = 35  # degrees
+_ARDUINO_ANGLES = (0, 90)
+_ARDUINO_MOVE_TIME = 2  # seconds
+_ARDUINO_SERVO_SPEED = 20
 _FRAMES_WITH_SQUARES_MIN = 20  # min number of frames with angles extracted
 _NAME = os.path.basename(__file__).split('.')[0]
 _NUM_CAPTURES = 100
 _NUM_ROTATIONS = 10
-_ROT_INIT_WAIT_TIME = 2  # seconds
+_ROT_INIT_WAIT_TIME = 4  # seconds
 _CHART_DISTANCE_SF = 25  # cm
 _CM_TO_M = 1/100.0
 
@@ -175,7 +178,8 @@
     # Start camera rotation & sleep shortly to let rotations start
     p = multiprocessing.Process(
         target=sensor_fusion_utils.rotation_rig,
-        args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,))
+        args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,
+              _ARDUINO_ANGLES, _ARDUINO_SERVO_SPEED, _ARDUINO_MOVE_TIME,))
     p.start()
     time.sleep(_ROT_INIT_WAIT_TIME)
 
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 0b2bbcc16..df1813c 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -62,6 +62,9 @@
                                 10, 0.03))  # cv2.calcOpticalFlowPyrLK params.
 
 _NAME = os.path.splitext(os.path.basename(__file__))[0]
+_ARDUINO_ANGLES = (0, 90)
+_ARDUINO_MOVE_TIME = 2
+_ARDUINO_SERVO_SPEED = 20
 _NUM_ROTATIONS = 10
 _START_FRAME = 1
 _FRAME_DELTA_TOL = 1.5  # 50% margin over nominal FPS of captures
@@ -120,7 +123,8 @@
   # Start camera rotation.
   p = multiprocessing.Process(
       target=sensor_fusion_utils.rotation_rig,
-      args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,))
+      args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,
+            _ARDUINO_ANGLES, _ARDUINO_SERVO_SPEED, _ARDUINO_MOVE_TIME,))
   p.start()
 
   cam.start_sensor_events()
diff --git a/apps/CameraITS/utils/image_fov_utils.py b/apps/CameraITS/utils/image_fov_utils.py
index c3badf9..b9caf33 100644
--- a/apps/CameraITS/utils/image_fov_utils.py
+++ b/apps/CameraITS/utils/image_fov_utils.py
@@ -145,7 +145,7 @@
   return 100 * math.pi * math.pow(radius, 2) / (img_w * img_h)
 
 
-def find_fov_reference(cam, req, props, fmt_type, ref_img_name_stem):
+def find_fov_reference(cam, req, props, raw_bool, ref_img_name_stem):
   """Determine the circle coverage of the image in reference image.
 
   Captures a full-frame RAW or JPEG and uses its aspect ratio and circle center
@@ -166,7 +166,7 @@
     cam: camera object
     req: camera request
     props: camera properties
-    fmt_type: 'RAW' or 'JPEG'
+    raw_bool: True if RAW available
     ref_img_name_stem: test _NAME + location to save data
 
   Returns:
@@ -174,8 +174,10 @@
     cc_ct_gt: circle center position relative to the center of image.
     aspect_ratio_gt: aspect ratio of the detected circle in float.
   """
-  logging.debug('Creating references for fov_coverage from %s', fmt_type)
-  if fmt_type == 'RAW':
+  logging.debug('Creating references for fov_coverage')
+  if raw_bool:
+    logging.debug('Using RAW for reference')
+    fmt_type = 'RAW'
     out_surface = {'format': 'raw'}
     cap = cam.do_capture(req, out_surface)
     logging.debug('Captured RAW %dx%d', cap['width'], cap['height'])
@@ -201,7 +203,9 @@
         img = cv2.undistort(img, k, opencv_dist)
     size = img.shape
 
-  elif fmt_type == 'JPEG':
+  else:
+    logging.debug('Using JPEG for reference')
+    fmt_type = 'JPEG'
     ref_fov = {}
     fmt = capture_request_utils.get_largest_jpeg_format(props)
     cap = cam.do_capture(req, fmt)
@@ -267,7 +271,7 @@
     circle = {'w': 2, 'h': 1}
     e_msg_stem = 'check_ar_false'
     e_msg = check_ar(circle, ar_gt, w, h, e_msg_stem)
-    self.assertTrue('check_ar_false' in e_msg)
+    self.assertIn('check_ar_false', e_msg)
 
   def test_check_crop(self):
     """Unit test for crop check."""
@@ -284,7 +288,7 @@
     circle = {'w': 100, 'h': 100, 'x_offset': 2, 'y_offset': 1}
     e_msg_stem = 'check_crop_false'
     e_msg = check_crop(circle, cc_gt, w, h, e_msg_stem, crop_thresh_factor)
-    self.assertTrue('check_crop_false' in e_msg)
+    self.assertIn('check_crop_false', e_msg)
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 1087261..074399e 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -82,9 +82,12 @@
 
   # Seconds timeout on each socket operation.
   SOCK_TIMEOUT = 20.0
+  # Seconds timeout on performance measurement socket operation
+  SOCK_TIMEOUT_FOR_PERF_MEASURE = 40.0
+
   # Additional timeout in seconds when ITS service is doing more complicated
   # operations, for example: issuing warmup requests before actual capture.
-  EXTRA_SOCK_TIMEOUT = 10.0
+  EXTRA_SOCK_TIMEOUT = 5.0
 
   PACKAGE = 'com.android.cts.verifier.camera.its'
   INTENT_START = 'com.android.cts.verifier.camera.its.START'
@@ -1144,7 +1147,7 @@
     cmd['cameraId'] = self._camera_id
     self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
 
-    timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+    timeout = self.SOCK_TIMEOUT_FOR_PERF_MEASURE
     self.sock.settimeout(timeout)
     data, _ = self.__read_response_from_socket()
     self.sock.settimeout(self.SOCK_TIMEOUT)
@@ -1164,7 +1167,7 @@
     cmd['cameraId'] = self._camera_id
     self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
 
-    timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+    timeout = self.SOCK_TIMEOUT_FOR_PERF_MEASURE
     self.sock.settimeout(timeout)
     data, _ = self.__read_response_from_socket()
     self.sock.settimeout(self.SOCK_TIMEOUT)
diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py
index 263f108..e7893fe 100644
--- a/apps/CameraITS/utils/sensor_fusion_utils.py
+++ b/apps/CameraITS/utils/sensor_fusion_utils.py
@@ -28,11 +28,9 @@
 
 # Constants for Rotation Rig
 ARDUINO_ANGLE_MAX = 180.0  # degrees
-ARDUINO_ANGLES = [0]*5 +list(range(0, 90, 3)) + [90]*5 +list(range(90, -1, -3))
 ARDUINO_BAUDRATE = 9600
 ARDUINO_CMD_LENGTH = 3
 ARDUINO_CMD_TIME = 2.0 * ARDUINO_CMD_LENGTH / ARDUINO_BAUDRATE  # round trip
-ARDUINO_MOVE_TIME = 0.06 - ARDUINO_CMD_TIME  # seconds
 ARDUINO_PID = 0x0043
 ARDUINO_SERVO_SPEED_MAX = 255
 ARDUINO_SERVO_SPEED_MIN = 1
@@ -175,14 +173,14 @@
           for x in cmd]
 
 
-def arduino_rotate_servo_to_angle(ch, angle, serial_port, delay=0):
+def arduino_rotate_servo_to_angle(ch, angle, serial_port, move_time):
   """Rotate servo to the specified angle.
 
   Args:
     ch: str; servo to rotate in ARDUINO_VALID_CH
     angle: int; servo angle to move to
     serial_port: object; serial port
-    delay: int; time in seconds
+    move_time: int; time in seconds
   """
   if angle < 0 or angle > ARDUINO_ANGLE_MAX:
     logging.debug('Angle must be between 0 and %d.', ARDUINO_ANGLE_MAX)
@@ -192,23 +190,31 @@
 
   cmd = [struct.pack('B', i) for i in [ARDUINO_START_BYTE, int(ch), angle]]
   arduino_send_cmd(serial_port, cmd)
-  time.sleep(delay)
+  time.sleep(move_time)
 
 
-def arduino_rotate_servo(ch, serial_port):
-  """Rotate servo between 0 --> 90 --> 0.
+def arduino_rotate_servo(ch, angles, servo_speed, move_time, serial_port):
+  """Rotate servo through 'angles'.
 
   Args:
     ch: str; servo to rotate
+    angles: list of ints; servo angles to move to
+    servo_speed: int; move speed between [1, 255]
+    move_time: int; time required to allow for arduino movement
     serial_port: object; serial port
   """
-  for angle in ARDUINO_ANGLES:
+
+  # set servo speed
+  logging.debug('Servo speed: %d', servo_speed)
+  set_servo_speed(ch, servo_speed, serial_port, delay=0)
+
+  for angle in angles:
     angle_norm = int(round(angle*ARDUINO_ANGLE_MAX/HS755HB_ANGLE_MAX, 0))
-    arduino_rotate_servo_to_angle(
-        ch, angle_norm, serial_port, ARDUINO_MOVE_TIME)
+    arduino_rotate_servo_to_angle(ch, angle_norm, serial_port, move_time)
 
 
-def rotation_rig(rotate_cntl, rotate_ch, num_rotations):
+def rotation_rig(rotate_cntl, rotate_ch, num_rotations, angles, servo_speed,
+                 move_time):
   """Rotate the phone n times using rotate_cntl and rotate_ch defined.
 
   rotate_ch is hard wired and must be determined from physical setup.
@@ -220,6 +226,9 @@
     rotate_cntl: str to identify as 'arduino' or 'canakit' controller.
     rotate_ch: str to identify rotation channel number.
     num_rotations: int number of rotations.
+    angles: list of ints; servo angle to move to.
+    servo_speed: int number of move speed between [1, 255].
+    move_time: int time required to allow for arduino movement.
   """
 
   logging.debug('Controller: %s, ch: %s', rotate_cntl, rotate_ch)
@@ -244,11 +253,15 @@
   logging.debug('Rotating phone %dx', num_rotations)
   for _ in range(num_rotations):
     if rotate_cntl == 'arduino':
-      arduino_rotate_servo(rotate_ch, arduino_serial_port)
+      arduino_rotate_servo(rotate_ch, angles, servo_speed, move_time,
+                           arduino_serial_port)
     elif rotate_cntl == 'canakit':
       canakit_set_relay_channel_state(canakit_serial_port, rotate_ch, 'ON')
       canakit_set_relay_channel_state(canakit_serial_port, rotate_ch, 'OFF')
   logging.debug('Finished rotations')
+  if rotate_cntl == 'arduino':
+    logging.debug('Moving servo to origin')
+    arduino_rotate_servo_to_angle(rotate_ch, 0, arduino_serial_port, 1)
 
 
 def set_servo_speed(ch, servo_speed, serial_port, delay=0):
@@ -267,7 +280,8 @@
     logging.debug('Servo speed must be <= %d.', ARDUINO_SERVO_SPEED_MAX)
     servo_speed = ARDUINO_SERVO_SPEED_MAX
 
-  cmd = [struct.pack('B', i) for i in [ARDUINO_SPEED_START_BYTE, int(ch), servo_speed]]
+  cmd = [struct.pack('B', i) for i in [ARDUINO_SPEED_START_BYTE,
+                                       int(ch), servo_speed]]
   arduino_send_cmd(serial_port, cmd)
   time.sleep(delay)
 
diff --git a/apps/CtsVerifier/OWNERS b/apps/CtsVerifier/OWNERS
new file mode 100644
index 0000000..0964da0
--- /dev/null
+++ b/apps/CtsVerifier/OWNERS
@@ -0,0 +1 @@
+per-file AndroidManifest*.xml = ape-relpgm-cls@google.com
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
index d96c0b1..f1fbf40 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
@@ -120,7 +120,7 @@
     }
 
     private static void assertHasRequiredReceiver(Context context) {
-        if (!UserManager.isHeadlessSystemUserMode()) return;
+        if (!Utils.isHeadlessSystemUserMode()) return;
 
         String packageName = context.getPackageName();
         Boolean hasIt = sHasRequiredReceiver.get(packageName);
@@ -226,7 +226,7 @@
         assertHasRequiredReceiver(context);
 
         int userId = context.getUserId();
-        if (userId == UserHandle.USER_SYSTEM || !UserManager.isHeadlessSystemUserMode()) {
+        if (userId == UserHandle.USER_SYSTEM || !Utils.isHeadlessSystemUserMode()) {
             Log.i(TAG, "get(): returning 'pure' DevicePolicyManager for user " + userId);
             return manager;
         }
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
index 03b8963..57289de 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -61,12 +62,17 @@
     @GuardedBy("LOCK")
     private static Handler sHandler;
 
+    static boolean isHeadlessSystemUserMode() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+                && UserManager.isHeadlessSystemUserMode();
+    }
+
     static boolean isHeadlessSystemUser() {
-        return UserManager.isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
+        return isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
     }
 
     static boolean isCurrentUserOnHeadlessSystemUser(Context context) {
-        return UserManager.isHeadlessSystemUserMode()
+        return isHeadlessSystemUserMode()
                 && context.getSystemService(UserManager.class).isUserForeground();
     }
 
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
index 4b40606..24bbaee 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
@@ -26,6 +26,7 @@
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
 
@@ -121,6 +122,7 @@
         Intent intent = new Intent(ACTION_DISABLE_SELF);
         intent.setComponent(new ComponentName(pkg().packageName(),
                 "com.android.bedstead.testapp.TestAppBroadcastController"));
+        Context context = TestApis.context().androidContextAsUser(mUser);
 
         try (PermissionContext p =
                      TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
@@ -130,7 +132,7 @@
                 BlockingBroadcastReceiver b = new BlockingBroadcastReceiver(
                         TestApis.context().instrumentedContext());
 
-                TestApis.context().androidContextAsUser(mUser).sendOrderedBroadcast(
+                context.sendOrderedBroadcast(
                         intent, /* receiverPermission= */ null, b, /* scheduler= */
                         null, /* initialCode= */
                         Activity.RESULT_CANCELED, /* initialData= */ null, /* initialExtras= */
@@ -139,14 +141,15 @@
                 b.awaitForBroadcastOrFail(Duration.ofSeconds(30).toMillis());
                 assertThat(b.getResultCode()).isEqualTo(Activity.RESULT_OK);
             }).timeout(Duration.ofMinutes(5)).runAndWrapException();
+
+            DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+
+            Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
+                    .toNotBeEqualTo(true)
+                    .errorOnFail()
+                    .await();
         }
 
-//        TODO(b/219894175) Expose isRemovingAdmin as a TestAPI for U.
-//        DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-//
-//        Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
-//                .toNotBeEqualTo(true)
-//                .await();
     }
 
     @Override
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
index f693ca1..a259203 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
@@ -26,6 +26,7 @@
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
 
@@ -113,6 +114,7 @@
         Intent intent = new Intent(ACTION_DISABLE_SELF);
         intent.setComponent(new ComponentName(pkg().packageName(),
                 "com.android.bedstead.testapp.TestAppBroadcastController"));
+        Context context = TestApis.context().androidContextAsUser(mUser);
 
         try (PermissionContext p =
                      TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
@@ -122,7 +124,7 @@
                 BlockingBroadcastReceiver b = new BlockingBroadcastReceiver(
                         TestApis.context().instrumentedContext());
 
-                TestApis.context().androidContextAsUser(mUser).sendOrderedBroadcast(
+                context.sendOrderedBroadcast(
                         intent, /* receiverPermission= */ null, b, /* scheduler= */
                         null, /* initialCode= */
                         Activity.RESULT_CANCELED, /* initialData= */ null, /* initialExtras= */
@@ -131,14 +133,15 @@
                 b.awaitForBroadcastOrFail(Duration.ofSeconds(30).toMillis());
                 assertThat(b.getResultCode()).isEqualTo(Activity.RESULT_OK);
             }).timeout(Duration.ofMinutes(5)).runAndWrapException();
+
+            DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+
+            Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
+                    .toNotBeEqualTo(true)
+                    .errorOnFail()
+                    .await();
         }
 
-//        TODO(b/219894175) Expose isRemovingAdmin as a TestAPI for U.
-//        DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-//
-//        Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
-//                .toNotBeEqualTo(true)
-//                .await();
     }
 
     @Override
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
index 8dc2ce6..9d44cc5 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
@@ -484,8 +484,8 @@
             "public void dumpInternal(@NonNull String, @Nullable java.io.FileDescriptor, @NonNull "
                     + "java.io.PrintWriter, @Nullable String[])",
 
-            // Uses android.view.OnBackInvokedDispatcher
-            "public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher()",
+            // Uses android.window.OnBackInvokedDispatcher
+            "public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher()",
 
             // Uses android.app.Activity
             "@Deprecated public void finishActivityFromChild(@NonNull android.app.Activity, int)",
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
index 3a6fc59..a6f307a 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
@@ -4072,7 +4072,7 @@
     method @Deprecated public void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
   }
 
-  @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+  @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
     ctor public Activity();
     method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public void closeContextMenu();
@@ -4115,7 +4115,7 @@
     method public int getMaxNumPictureInPictureActions();
     method public final android.media.session.MediaController getMediaController();
     method @NonNull public android.view.MenuInflater getMenuInflater();
-    method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+    method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
     method public final android.app.Activity getParent();
     method @Nullable public android.content.Intent getParentActivityIntent();
     method public android.content.SharedPreferences getPreferences(int);
@@ -5001,7 +5001,7 @@
     method public void onDateSet(android.widget.DatePicker, int, int, int);
   }
 
-  public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+  public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
     ctor public Dialog(@NonNull @UiContext android.content.Context);
     ctor public Dialog(@NonNull @UiContext android.content.Context, @StyleRes int);
     ctor protected Dialog(@NonNull @UiContext android.content.Context, boolean, @Nullable android.content.DialogInterface.OnCancelListener);
@@ -5021,7 +5021,7 @@
     method @NonNull @UiContext public final android.content.Context getContext();
     method @Nullable public android.view.View getCurrentFocus();
     method @NonNull public android.view.LayoutInflater getLayoutInflater();
-    method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+    method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
     method @Nullable public final android.app.Activity getOwnerActivity();
     method @Nullable public final android.view.SearchEvent getSearchEvent();
     method public final int getVolumeControlStream();
@@ -49026,14 +49026,14 @@
   }
 
   public interface OnBackInvokedDispatcher {
-    method public void registerOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback, @IntRange(from=0) int);
-    method public void unregisterOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback);
+    method public void registerOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback, @IntRange(from=0) int);
+    method public void unregisterOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback);
     field public static final int PRIORITY_DEFAULT = 0; // 0x0
     field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240
   }
 
   public interface OnBackInvokedDispatcherOwner {
-    method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+    method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
   }
 
   public interface OnReceiveContentListener {
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
index 9757b2f..3fe2a3e 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
@@ -103,7 +103,7 @@
 
 package android.app {
 
-  @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+  @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
     method public final boolean addDumpable(@NonNull android.util.Dumpable);
     method public void dumpInternal(@NonNull String, @Nullable java.io.FileDescriptor, @NonNull java.io.PrintWriter, @Nullable String[]);
     method public void onMovedToDisplay(int, android.content.res.Configuration);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index 4125ede..3ca979d 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -268,4 +268,33 @@
             }
         }
     }
+
+    /** Retrieves a map of prop to value for all props with the given prefix */
+    public static Map<String, String> getPropertiesWithPrefix(String prefix) {
+        Map<String, String> result = new HashMap<>();
+        Pattern pattern = Pattern.compile("\\[(.*)\\]: \\[(.*)\\]");
+        Scanner scanner = null;
+        try {
+            Process process = new ProcessBuilder("getprop").start();
+            scanner = new Scanner(process.getInputStream());
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine().trim();
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.find()) {
+                    String prop = matcher.group(1);
+                    String value = matcher.group(2);
+                    if (prop.startsWith(prefix)) {
+                        result.put(prop, value);
+                    }
+                }
+            }
+            return result;
+        } catch (IOException e) {
+            return result;
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+        }
+    }
 }
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index b3e2cab..cff7c22 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -203,12 +203,8 @@
                     "Landroid/hardware/usb/gadget/V1_2/IUsbGadget;",
                     "Landroid/hardware/usb/gadget/V1_2/IUsbGadgetCallback;",
                     "Landroid/hardware/usb/gadget/V1_2/UsbSpeed;",
-                    "Landroid/os/BlockUntrustedTouchesMode;",
                     "Landroid/os/CreateAppDataArgs;",
                     "Landroid/os/CreateAppDataResult;",
-                    "Landroid/os/IInputConstants;",
-                    "Landroid/os/InputEventInjectionResult;",
-                    "Landroid/os/InputEventInjectionSync;",
                     "Lcom/android/internal/util/FrameworkStatsLog;"
             );
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
index f61bc16..b571bba 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -21,7 +21,9 @@
 
     <!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
          to pass the build error, since tests need to use minSdkVersion 4. -->
-    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+        androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+        androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
 
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
index aff6672..672b163 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
@@ -26,8 +26,9 @@
 
     <!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
          to pass the build error, since tests need to use minSdkVersion 4. -->
-    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary=
-        "androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+        androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+        androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
 
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
index 9cd26cf..7d275aa 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
@@ -23,7 +23,9 @@
     <!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
          to pass the build error, since tests need to use minSdkVersion 4. -->
     <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
-        androidx.test.rules, androidx.test.monitor, androidx.test.services.storage" android:targetSdkVersion="27"/>
+        androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+        androidx.test.annotation, androidx.annotation.experimental androidx.tracing"
+        android:targetSdkVersion="27"/>
 
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
index 28bef9d..e2e5415 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
@@ -21,8 +21,9 @@
 
     <!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
          to pass the build error, since tests need to use minSdkVersion 4. -->
-    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary=
-        "androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+    <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+        androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+        androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
 
     <!-- Remove the CAMERA permission
     <uses-permission android:name="android.permission.CAMERA"/> -->
diff --git a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
index f761e8f..0396c3b 100644
--- a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
+++ b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
@@ -183,11 +183,12 @@
         assertNotNull(result.getModel());
         ThreadModel thread = findThread(result.getModel(), result.getTid());
         assertNotNull(thread);
-        assertEquals(2, thread.getSlices().size());
-        Slice sdkSlice = thread.getSlices().get(0);
-        assertEquals("AtraceDeviceTest::beginEndSection", sdkSlice.getName());
-        Slice ndkSlice = thread.getSlices().get(1);
-        assertEquals("ndk::beginEndSection", ndkSlice.getName());
+        Slice sdkSlice = SliceQueriesKt.selectFirst(thread,
+                slice1 -> "AtraceDeviceTest::beginEndSection".equals(slice1.getName()));
+        assertNotNull(sdkSlice);
+        Slice ndkSlice = SliceQueriesKt.selectFirst(thread,
+                slice -> "ndk::beginEndSection".equals(slice.getName()));
+        assertNotNull(ndkSlice);
     }
 
     public void testAsyncBeginEndSection() {
@@ -283,4 +284,5 @@
         assertEquals("Didn't find all async sections",
                 0, requiredAsyncSections.size());
     }
+
 }
diff --git a/hostsidetests/car/Android.bp b/hostsidetests/car/Android.bp
index 337879e..caa8290 100644
--- a/hostsidetests/car/Android.bp
+++ b/hostsidetests/car/Android.bp
@@ -24,7 +24,11 @@
         "src/**/*.java",
         "app/src/android/car/cts/app/PowerPolicyTestCommandStatus.java",
         "app/src/android/car/cts/app/PowerPolicyTestCommandType.java",
+        ":cartelemetryservice-proto-srcs",
     ],
+    proto: {
+        type: "lite",
+    },
     libs: [
         "cts-tradefed",
         "tradefed",
diff --git a/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
new file mode 100644
index 0000000..779d405
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.car.telemetry.TelemetryProto;
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CarTelemetryHostTest extends CarHostJUnit4TestCase {
+
+    // Publisher/subscriber listening for gear change property
+    private static final int GEAR_SELECTION_PROPERTY_ID = 287310850;
+    private static final TelemetryProto.Publisher GEAR_CHANGE_PUBLISHER =
+            TelemetryProto.Publisher.newBuilder()
+                    .setVehicleProperty(
+                            TelemetryProto.VehiclePropertyPublisher.newBuilder()
+                                    .setVehiclePropertyId(GEAR_SELECTION_PROPERTY_ID)
+                                    .setReadRate(0f))
+                    .build();
+    private static final TelemetryProto.Subscriber GEAR_CHANGE_SUBSCRIBER =
+            TelemetryProto.Subscriber.newBuilder()
+                    .setHandler("onGearChange")
+                    .setPublisher(GEAR_CHANGE_PUBLISHER)
+                    .setPriority(0)
+                    .build();
+
+    // only produces interim result
+    private static final String LUA_SCRIPT_INTERIM = new StringBuilder()
+            .append("function onGearChange(published_data, saved_state)\n")
+            .append("    saved_state['interim_result_exists'] = true\n")
+            .append("    on_success(saved_state)\n")
+            .append("end\n")
+            .toString();
+    private static final TelemetryProto.MetricsConfig METRICS_CONFIG_1 =
+            TelemetryProto.MetricsConfig.newBuilder()
+                    .setName("test_config_1")
+                    .setVersion(1)
+                    .setScript(LUA_SCRIPT_INTERIM)
+                    .addSubscribers(GEAR_CHANGE_SUBSCRIBER)
+                    .build();
+    private static final String CONFIG_NAME_1 = METRICS_CONFIG_1.getName();
+
+    // only produces final result
+    private static final String LUA_SCRIPT_FINAL = new StringBuilder()
+            .append("function onGearChange(published_data, saved_state)\n")
+            .append("    saved_state['final_result_exists'] = true\n")
+            .append("    on_script_finished(saved_state)\n")
+            .append("end\n")
+            .toString();
+    private static final TelemetryProto.MetricsConfig METRICS_CONFIG_2 =
+            TelemetryProto.MetricsConfig.newBuilder()
+                    .setName("test_config_2")
+                    .setVersion(1)
+                    .setScript(LUA_SCRIPT_FINAL)
+                    .addSubscribers(GEAR_CHANGE_SUBSCRIBER)
+                    .build();
+    private static final String CONFIG_NAME_2 = METRICS_CONFIG_2.getName();
+
+    private static final long SCRIPT_EXECUTION_TIMEOUT_MILLIS = 30_000L;
+    private static final String FINAL_RESULT_DIR = "/data/system/car/telemetry/final";
+    private static final String INTERIM_RESULT_DIR = "/data/system/car/telemetry/interim";
+
+    @Before
+    public void setUp() throws Exception {
+        getDevice().enableAdbRoot();
+        String output = executeCommand("cmd car_service enable-feature car_telemetry_service");
+        if (!output.startsWith("Already enabled")) {
+            // revert the feature to its original setting
+            executeCommand("cmd car_service disable-feature car_telemetry_service");
+            assumeTrue("CarTelemetryService is not enabled, skipping test", false);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        executeCommand("cmd car_service telemetry remove %s", CONFIG_NAME_1);
+        executeCommand("rm %s/%s", FINAL_RESULT_DIR, CONFIG_NAME_2);
+    }
+
+    @Test
+    public void testSavingResultsAcrossReboot() throws Exception {
+        // create temp files, which will be the argument to the telemetry car shell cmd
+        File config1 = createMetricsConfigTempFile(METRICS_CONFIG_1);
+        File config2 = createMetricsConfigTempFile(METRICS_CONFIG_2);
+        config1.deleteOnExit();
+        config2.deleteOnExit();
+
+        // outputs that should be produced by the Lua scripts above
+        String scriptOutput1 = "interim_result_exists";
+        String scriptOutput2 = "final_result_exists";
+
+        // add metrics configs using car shell command
+        getDevice().executeShellV2Command("cmd car_service telemetry add " + CONFIG_NAME_1,
+                config1);
+        getDevice().executeShellV2Command("cmd car_service telemetry add " + CONFIG_NAME_2,
+                config2);
+
+        // inject gear change event, should trigger script execution for both scripts
+        executeCommand("cmd car_service inject-vhal-event %d %d",
+                GEAR_SELECTION_PROPERTY_ID, 2);
+
+        // block until script execution finishes
+        PollingCheck.waitFor(SCRIPT_EXECUTION_TIMEOUT_MILLIS, () -> {
+            String dump = dumpTelemetryService();
+            return dump.contains(scriptOutput1) && dump.contains(scriptOutput2);
+        });
+
+        // verify that both results are stored in memory, not in disk
+        assertThat(executeCommand("ls %s", INTERIM_RESULT_DIR))
+                .doesNotContain(CONFIG_NAME_1);
+        assertThat(executeCommand("ls %s", FINAL_RESULT_DIR))
+                .doesNotContain(CONFIG_NAME_2);
+
+        // trigger reboot, which should save results to disk
+        getDevice().reboot();
+        waitForCarServiceReady();
+
+        // verify data is saved across reboot
+        assertThat(dumpTelemetryService()).contains(scriptOutput1);
+        String result = executeCommand("cmd car_service telemetry get-result %s", CONFIG_NAME_2);
+        assertThat(result).contains(scriptOutput2);
+    }
+
+    private String dumpTelemetryService() throws Exception {
+        return executeCommand("dumpsys car_service --services CarTelemetryService");
+    }
+
+    private File createMetricsConfigTempFile(TelemetryProto.MetricsConfig metricsConfig)
+            throws Exception {
+        File tempFile = File.createTempFile(metricsConfig.getName(), ".bin");
+        FileOutputStream os = new FileOutputStream(tempFile);
+        os.write(metricsConfig.toByteArray());
+        os.flush();
+        os.close();
+        return tempFile;
+    }
+}
diff --git a/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml b/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
index 97f4d9a..1d5f72e 100644
--- a/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
+++ b/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
@@ -19,7 +19,8 @@
     <!-- targetSdkVersion for this test must be below 30 -->
     <uses-sdk android:targetSdkVersion="30"/>
     <application
-        android:debuggable="true">
+        android:debuggable="true"
+        android:appCategory="game">
         <uses-library android:name="android.test.runner" />
 
         <activity
diff --git a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
index 3ae0e71..af0d156 100644
--- a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
+++ b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
@@ -40,6 +40,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -58,6 +59,7 @@
 
     private int mInitialMatchContentFrameRate;
     private DisplayManager mDisplayManager;
+    private UiDevice mUiDevice;
 
 
     @Rule
@@ -66,17 +68,17 @@
 
     @Before
     public void setUp() throws Exception {
-        final UiDevice uiDevice =
-                UiDevice.getInstance(
+        mUiDevice = UiDevice.getInstance(
                         androidx.test.platform.app.InstrumentationRegistry.getInstrumentation());
-        uiDevice.wakeUp();
-        uiDevice.executeShellCommand("wm dismiss-keyguard");
+        mUiDevice.wakeUp();
+        mUiDevice.executeShellCommand("wm dismiss-keyguard");
 
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity(Manifest.permission.LOG_COMPAT_CHANGE,
                         Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
                         Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
-                        Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS);
+                        Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+                        Manifest.permission.MANAGE_GAME_MODE);
 
         mDisplayManager = mActivityRule.getActivity().getSystemService(DisplayManager.class);
         mInitialMatchContentFrameRate = toSwitchingType(
@@ -154,11 +156,23 @@
     }
 
     private void testFrameRateOverride(FrameRateObserver frameRateObserver)
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         for (Display.Mode mode : getModesToTest()) {
             setMode(mode);
-            activity.testFrameRateOverride(frameRateObserver, mode.getRefreshRate());
+            activity.testFrameRateOverride(activity.new SurfaceFrameRateOverrideBehavior(),
+                    frameRateObserver, mode.getRefreshRate());
+        }
+    }
+
+    private void testGameModeFrameRateOverride(FrameRateObserver frameRateObserver)
+            throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        for (Display.Mode mode : getModesToTest()) {
+            setMode(mode);
+            activity.testFrameRateOverride(
+                    activity.new GameModeFrameRateOverrideBehavior(mUiDevice),
+                    frameRateObserver, mode.getRefreshRate());
         }
     }
 
@@ -169,7 +183,7 @@
      */
     @Test
     public void testBackpressure()
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         testFrameRateOverride(activity.new BackpressureFrameRateObserver());
     }
@@ -181,7 +195,7 @@
      */
     @Test
     public void testChoreographer()
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         testFrameRateOverride(activity.new ChoreographerFrameRateObserver());
     }
@@ -196,7 +210,7 @@
      */
     @Test
     public void testDisplayGetRefreshRate()
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         testFrameRateOverride(activity.new DisplayGetRefreshRateFrameRateObserver());
     }
@@ -208,7 +222,7 @@
      */
     @Test
     public void testDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         testFrameRateOverride(
                 activity.new DisplayModeGetRefreshRateFrameRateObserver(
@@ -222,10 +236,73 @@
      */
     @Test
     public void testDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
-            throws InterruptedException {
+            throws InterruptedException, IOException {
         FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
         testFrameRateOverride(
                 activity.new DisplayModeGetRefreshRateFrameRateObserver(
                         /*displayModeReturnsPhysicalRefreshRateEnabled*/ false));
     }
+
+    /**
+     * Test run by
+     * FrameRateOverrideHostTest
+     * .testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateEnabled
+     */
+    @Test
+    public void testGameModeBackpressure() throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        testGameModeFrameRateOverride(activity.new BackpressureFrameRateObserver());
+    }
+
+    /**
+     * Test run by
+     * FrameRateOverrideHostTest
+     * .testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateEnabled
+     */
+    @Test
+    public void testGameModeChoreographer() throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        testGameModeFrameRateOverride(activity.new ChoreographerFrameRateObserver());
+    }
+
+    /**
+     * Test run by
+     * FrameRateOverrideHostTest
+     * .testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled
+     */
+    @Test
+    public void testGameModeDisplayGetRefreshRate() throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        testGameModeFrameRateOverride(activity.new DisplayGetRefreshRateFrameRateObserver());
+    }
+
+    /**
+     * Test run by
+     * FrameRateOverrideHostTest
+     * .testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled
+     */
+    @Test
+    public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+            throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        testGameModeFrameRateOverride(
+                activity.new DisplayModeGetRefreshRateFrameRateObserver(
+                        /*displayModeReturnsPhysicalRefreshRateEnabled*/ false));
+    }
+
+    /**
+     * Test run by
+     * FrameRateOverrideHostTest
+     * .testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled
+     */
+    @Test
+    public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+            throws InterruptedException, IOException {
+        FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+        testGameModeFrameRateOverride(
+                activity.new DisplayModeGetRefreshRateFrameRateObserver(
+                        /*displayModeReturnsPhysicalRefreshRateEnabled*/ true));
+    }
+
+
 }
diff --git a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
index 888f7f3..c54ae79 100644
--- a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
+++ b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 import android.view.Choreographer;
 import android.view.Surface;
@@ -32,6 +33,7 @@
 import android.view.SurfaceView;
 import android.view.ViewGroup;
 
+import java.io.IOException;
 import java.util.ArrayList;
 
 /**
@@ -417,39 +419,80 @@
         }
     }
 
-    private void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
-            float initialRefreshRate) throws InterruptedException {
-        Log.i(TAG, "Staring testFrameRateOverride");
-        float halfFrameRate = initialRefreshRate / 2;
+    interface FrameRateOverrideBehavior{
+        void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+                float initialRefreshRate) throws InterruptedException, IOException;
+    }
 
-        waitForRefreshRateChange(initialRefreshRate);
-        frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Initial");
+    class SurfaceFrameRateOverrideBehavior implements FrameRateOverrideBehavior {
 
-        Log.i(TAG, String.format("Setting Frame Rate to %.2f with default compatibility",
-                halfFrameRate));
-        mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
-                Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
-        waitForRefreshRateChange(halfFrameRate);
-        frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(default)");
+        @Override
+        public void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+                float initialRefreshRate) throws InterruptedException {
+            Log.i(TAG, "Staring testFrameRateOverride");
+            float halfFrameRate = initialRefreshRate / 2;
 
-        Log.i(TAG, String.format("Setting Frame Rate to %.2f with fixed source compatibility",
-                halfFrameRate));
-        mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
-                Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
-        waitForRefreshRateChange(halfFrameRate);
-        frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(fixed source)");
+            waitForRefreshRateChange(initialRefreshRate);
+            frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Initial");
 
-        Log.i(TAG, "Resetting Frame Rate setting");
-        mSurface.setFrameRate(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
-                Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
-        waitForRefreshRateChange(initialRefreshRate);
-        frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+            Log.i(TAG, String.format("Setting Frame Rate to %.2f with default compatibility",
+                    halfFrameRate));
+            mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+            waitForRefreshRateChange(halfFrameRate);
+            frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(default)");
+
+            Log.i(TAG, String.format("Setting Frame Rate to %.2f with fixed source compatibility",
+                    halfFrameRate));
+            mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+                    Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+            waitForRefreshRateChange(halfFrameRate);
+            frameRateObserver.observe(initialRefreshRate, halfFrameRate,
+                    "setFrameRate(fixed source)");
+
+            Log.i(TAG, "Resetting Frame Rate setting");
+            mSurface.setFrameRate(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+            waitForRefreshRateChange(initialRefreshRate);
+            frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+        }
+    }
+
+    class GameModeFrameRateOverrideBehavior implements FrameRateOverrideBehavior {
+        private UiDevice mUiDevice;
+        GameModeFrameRateOverrideBehavior(UiDevice uiDevice) {
+            mUiDevice = uiDevice;
+        }
+        @Override
+        public void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+                float initialRefreshRate) throws InterruptedException, IOException {
+            Log.i(TAG, "Starting testGameModeFrameRateOverride");
+
+            int initialRefreshRateInt = (int) initialRefreshRate;
+            for (int divisor = 1; initialRefreshRateInt / divisor >= 30; ++divisor) {
+                int overrideFrameRate = initialRefreshRateInt / divisor;
+                Log.i(TAG, String.format("Setting Frame Rate to %d using Game Mode",
+                        overrideFrameRate));
+
+                mUiDevice.executeShellCommand(String.format("cmd game set --mode 2 --fps %d %s",
+                        overrideFrameRate, getPackageName()));
+                waitForRefreshRateChange(overrideFrameRate);
+                frameRateObserver.observe(initialRefreshRate, overrideFrameRate,
+                        String.format("Game Mode Override(%d)", overrideFrameRate));
+            }
+
+            Log.i(TAG, "Resetting Frame Rate setting");
+            mUiDevice.executeShellCommand(String.format("cmd game reset %s", getPackageName()));
+            waitForRefreshRateChange(initialRefreshRate);
+            frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+        }
     }
 
     // The activity being intermittently paused/resumed has been observed to
     // cause test failures in practice, so we run the test with retry logic.
-    public void testFrameRateOverride(FrameRateObserver frameRateObserver, float initialRefreshRate)
-            throws InterruptedException {
+    public void testFrameRateOverride(FrameRateOverrideBehavior frameRateOverrideBehavior,
+            FrameRateObserver frameRateObserver, float initialRefreshRate)
+            throws InterruptedException, IOException {
         synchronized (mLock) {
             Log.i(TAG, "testFrameRateOverride started");
             int attempts = 0;
@@ -458,7 +501,8 @@
                 while (!testPassed) {
                     waitForPreconditions();
                     try {
-                        testFrameRateOverrideBehavior(frameRateObserver, initialRefreshRate);
+                        frameRateOverrideBehavior.testFrameRateOverrideBehavior(frameRateObserver,
+                                initialRefreshRate);
                         testPassed = true;
                     } catch (PreconditionViolatedException exc) {
                         // The logic below will retry if we're below max attempts.
diff --git a/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java b/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
index 12162d9..a8d7a9e 100644
--- a/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
+++ b/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
@@ -36,10 +36,14 @@
     @Override
     protected void setUp() throws Exception {
         installPackage(TEST_APK, true);
+        // add device config to enable game mode
+        runCommand("device_config put game_overlay " + TEST_PKG + " mode=2:mode=3");
     }
 
     @Override
     protected void tearDown() throws Exception {
+        // remove device config
+        runCommand("device_config delete game_overlay " + TEST_PKG);
         uninstallPackage(TEST_PKG, true);
     }
 
@@ -122,4 +126,84 @@
                 /*disabledChanges*/
                 ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
     }
+
+    public void testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateEnabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeBackpressure",
+                /*enabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+                /*disabledChanges*/
+                ImmutableSet.of());
+    }
+
+    public void testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateDisabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeBackpressure",
+                /*enabledChanges*/
+                ImmutableSet.of(),
+                /*disabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+    }
+
+    public void testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateEnabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeChoreographer",
+                /*enabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+                /*disabledChanges*/
+                ImmutableSet.of());
+    }
+
+    public void testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateDisabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeChoreographer",
+                /*enabledChanges*/
+                ImmutableSet.of(),
+                /*disabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+    }
+
+    public void testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeDisplayGetRefreshRate",
+                /*enabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+                /*disabledChanges*/
+                ImmutableSet.of());
+    }
+
+    public void testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeDisplayGetRefreshRate",
+                /*enabledChanges*/
+                ImmutableSet.of(),
+                /*disabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+    }
+
+    public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled",
+                /*enabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+                /*disabledChanges*/
+                ImmutableSet.of());
+    }
+
+    public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+            throws Exception {
+        runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+                "testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled",
+                /*enabledChanges*/
+                ImmutableSet.of(),
+                /*disabledChanges*/
+                ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+    }
 }
diff --git a/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java b/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
index 0507669..9fcd9b1 100644
--- a/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
+++ b/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
@@ -16,11 +16,13 @@
 package com.android.cts.graphics;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
+import com.android.compatibility.common.util.CddTest;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.util.CommandResult;
@@ -38,6 +40,8 @@
   private static final String DUMPSYS_COMMAND = "dumpsys gpu --gpuwork";
   private static final String TEST_PKG = "com.android.cts.framestatstestapp";
   private static final int PAUSE_MILLIS = 3000;
+  private static final String GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH =
+      "/sys/kernel/tracing/events/power/gpu_work_period/format";
 
   private CommandResult assertShellCommand(String command) throws DeviceNotAvailableException {
     CommandResult commandResult = getDevice().executeShellV2Command(command);
@@ -68,16 +72,21 @@
     return appUid;
   }
 
+  @CddTest(requirement = "6.1/C-6-1")
   @Test
   public void testOutputFormat() throws Exception {
-    // Execute dumpsys command.
-    CommandResult commandResult = assertShellCommand(DUMPSYS_COMMAND);
+    CommandResult commandResult =
+        getDevice()
+            .executeShellV2Command(String.format("cat %s", GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH));
 
-    // If the dumpsys command output indicates that the GPU information is not available then the
-    // test ends here.
-    assumeFalse(
-        "GPU time in state information was not available.",
-        commandResult.getStdout().contains("GPU time in state information is not available"));
+    // If we fail to cat the tracepoint format then the test ends here. If the tracing file system
+    // is inaccessible, then this test won't fail. We rely on VTS tests to ensure that the tracing
+    // file system is accessible.
+    assumeTrue(
+        String.format(
+            "Failed to cat the gpu_work_period tracepoint format at %s",
+            GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH),
+        commandResult.getStatus().equals(CommandStatus.SUCCESS));
 
     // Turn screen on.
     assertShellCommand("input keyevent KEYCODE_WAKEUP");
@@ -94,30 +103,43 @@
     // Get the UID of the test app.
     long appUid = getTestAppUid();
 
-    // Execute dumpsys command again.
+    // Execute dumpsys command.
     commandResult = assertShellCommand(DUMPSYS_COMMAND);
 
-    LogUtil.CLog.i("dumpsys output:\n%s", commandResult.getStdout());
+    assertFalse(
+        String.format(
+            "The command shows errors.\nCommand: %s\nOutput:\n%s\n",
+            DUMPSYS_COMMAND, commandResult.getStdout()),
+        commandResult.getStdout().contains("[errors:"));
 
     String[] lines = commandResult.getStdout().trim().split("\n");
     int i = 0;
     for (; i < lines.length; ++i) {
-      if (lines[i].startsWith("uid/freq: 0MHz")) {
+      if (lines[i].startsWith("gpu_id uid")) {
         break;
       }
     }
-    assertTrue("Could not find uid/freq header in output", i < lines.length);
+    assertTrue(
+        String.format(
+            "Could not find \"gpu_id uid ...\" header in output:\n%s\n", commandResult.getStdout()),
+        i < lines.length);
 
-    Pattern uidInfoPattern = Pattern.compile(String.format("(%d): \\d+", appUid));
+    Pattern uidInfoPattern = Pattern.compile(String.format("\\d+ (%d) (\\d+) (\\d+)", appUid));
     for (; i < lines.length; ++i) {
       Matcher matcher = uidInfoPattern.matcher(lines[i]);
       if (!matcher.lookingAt()) {
         continue;
       }
-      if (appUid == Long.parseLong(matcher.group(1))) {
-        break;
+      if (appUid == Long.parseLong(matcher.group(1))
+          && Long.parseLong(matcher.group(2)) > 0
+          && Long.parseLong(matcher.group(3)) > 0) {
+        // Success!
+        return;
       }
     }
-    assertTrue(String.format("Could not find UID %d in output", appUid), i < lines.length);
+    fail(
+        String.format(
+            "Could not find UID %d with non-zero active and inactive GPU time in output:\n%s\n",
+            appUid, commandResult.getStdout()));
   }
 }
diff --git a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
index fb37109..76bdaf7 100644
--- a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
+++ b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
@@ -30,6 +30,7 @@
 import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_2;
 import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_3;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -46,6 +47,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -53,6 +55,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 @LargeTest
 public class MediaRouter2Test {
@@ -77,14 +80,14 @@
         List<String> features = new ArrayList<>();
         features.add("A test feature");
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(features, /*activeScan=*/false).build();
+                new RouteDiscoveryPreference.Builder(features, /*activeScan=*/ false).build();
         mRouter2.registerRouteCallback(mExecutor, mRouterDummyCallback, preference);
     }
 
     @Test
     public void dontDedupeByDefault() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/  true).build();
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true).build();
         Map<String, MediaRoute2Info> routes =
                 waitAndGetRoutes(preference, Set.of(ROUTE_ID_1_1, ROUTE_ID_2_1, ROUTE_ID_3_1));
 
@@ -102,7 +105,7 @@
     @Test
     public void setDeduplicationPackageOrder1() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_1_PACKAGE,
@@ -126,7 +129,7 @@
     @Test
     public void setDeduplicationPackageOrder2() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_3_PACKAGE,
@@ -150,7 +153,7 @@
     @Test
     public void setDeduplicationPackageOrder3() throws Exception {
         RouteDiscoveryPreference preference =
-                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
                         .setDeduplicationPackageOrder(
                                 List.of(
                                         MEDIA_ROUTER_PROVIDER_2_PACKAGE,
@@ -171,6 +174,89 @@
         assertFalse(routes.containsKey(ROUTE_ID_3_3));
     }
 
+    @Test
+    public void testRouteCallbacks() throws Exception {
+        Set<String> addedRouteIds = new HashSet<>();
+        Set<String> removedRouteIds = new HashSet<>();
+
+        AtomicReference<CountDownLatch> addLatchRef = new AtomicReference<>();
+        AtomicReference<CountDownLatch> removeLatchRef = new AtomicReference<>();
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+
+        RouteDiscoveryPreference preference =
+                new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
+                        .setAllowedPackages(List.of(MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+                        .setDeduplicationPackageOrder(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_3_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+                        .build();
+        MediaRouter2.RouteCallback routeCallback =
+                new MediaRouter2.RouteCallback() {
+                    @Override
+                    public void onRoutesAdded(List<MediaRoute2Info> routes) {
+                        for (MediaRoute2Info route : routes) {
+                            if (!route.isSystemRoute()) {
+                                addedRouteIds.add(route.getOriginalId());
+                            }
+                        }
+                        addLatchRef.get().countDown();
+                    }
+
+                    @Override
+                    public void onRoutesRemoved(List<MediaRoute2Info> routes) {
+                        for (MediaRoute2Info route : routes) {
+                            removedRouteIds.add(route.getOriginalId());
+                        }
+                        removeLatchRef.get().countDown();
+                    }
+                };
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertFalse(removeLatchRef.get().await(WAIT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_1_1, ROUTE_ID_1_2, ROUTE_ID_1_3), addedRouteIds);
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+        RouteDiscoveryPreference preference2 =
+                new RouteDiscoveryPreference.Builder(preference)
+                        .setAllowedPackages(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE))
+                        .build();
+
+        addedRouteIds.clear();
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference2);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_2_1, ROUTE_ID_2_2, ROUTE_ID_2_3), addedRouteIds);
+        assertEquals(Set.of(ROUTE_ID_1_2), removedRouteIds);
+
+        addLatchRef.set(new CountDownLatch(1));
+        removeLatchRef.set(new CountDownLatch(1));
+        RouteDiscoveryPreference preference3 =
+                new RouteDiscoveryPreference.Builder(preference)
+                        .setAllowedPackages(
+                                List.of(
+                                        MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+                                        MEDIA_ROUTER_PROVIDER_3_PACKAGE))
+                        .build();
+
+        addedRouteIds.clear();
+        removedRouteIds.clear();
+
+        mRouter2.registerRouteCallback(mExecutor, routeCallback, preference3);
+        assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertEquals(Set.of(ROUTE_ID_3_1, ROUTE_ID_3_2), addedRouteIds);
+        assertEquals(Set.of(ROUTE_ID_1_3), removedRouteIds);
+    }
+
     // It returns original route id -> route for convenience
     private static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
         Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
index df6ebeb..32adb1e 100644
--- a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
+++ b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
@@ -66,4 +66,10 @@
         runDeviceTests(
                 MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "setDeduplicationPackageOrder3");
     }
+
+    @AppModeFull
+    @RequiresDevice
+    public void testCallback() throws Exception {
+        runDeviceTests(MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testRouteCallbacks");
+    }
 }
diff --git a/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java b/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
index 3203793..eeabeec 100644
--- a/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
+++ b/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
@@ -76,6 +76,7 @@
         }
     }
 
+    static final String CAR_SETTING_FRAG_RESOURCE_ID_REGEX = ".*:id/fragment_container_wrapper";
     static final String PACKAGE_NAME = DeviceOwnerTest.class.getPackage().getName();
     static final ComponentName RECEIVER_COMPONENT =
             new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName());
@@ -84,6 +85,7 @@
     protected PackageManager mPackageManager;
     protected boolean mIsDeviceOwner;
     private String mWorkPolicyInfoText;
+    private boolean mIsAutomotive;
 
     @Override
     protected void setUp() throws Exception {
@@ -94,9 +96,9 @@
         mDevicePolicyManager = TestAppSystemServiceFactory.getDevicePolicyManager(mContext,
                 BasicAdminReceiver.class, /* forDeviceOwner= */ true);
 
-        boolean isAutomotive = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+        mIsAutomotive = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
 
-        mWorkPolicyInfoText = isAutomotive
+        mWorkPolicyInfoText = mIsAutomotive
                 ? "Privacy Settings for Device Owner CTS host side app vehicle policy"
                 : "Your work policy info";
 
@@ -145,9 +147,10 @@
         boolean found = null != mDevice.wait(Until.findObject(By.text(mWorkPolicyInfoText)),
                 TIMEOUT_MS);
 
-        // Try to scroll the list to find the item
-        if (!found) {
-            UiScrollable scroller = new UiScrollable(new UiSelector().scrollable(true));
+        // For automotive UI, try to scroll the privacy list to find the item
+        if (!found && mIsAutomotive) {
+            UiScrollable scroller = new UiScrollable(new UiSelector()
+                    .resourceIdMatches(CAR_SETTING_FRAG_RESOURCE_ID_REGEX));
             try {
                 // Swipe far away from the edges to avoid triggering navigation gestures
                 scroller.setSwipeDeadZonePercentage(DEADZONE_PCT);
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index c03b9b4..e356ea6 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -684,8 +684,6 @@
         sleep(500);
         setScreenBrightness(100);
         sleep(500);
-        setScreenBrightness(140);
-        sleep(500);
 
 
         wl.release();
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 8ae8d4f..33422c1 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -600,11 +600,9 @@
 
         Set<Integer> screenMin = new HashSet<>(Arrays.asList(47));
         Set<Integer> screen100 = new HashSet<>(Arrays.asList(100));
-        Set<Integer> screen140 = new HashSet<>(Arrays.asList(140));
-        // Set<Integer> screenMax = new HashSet<>(Arrays.asList(255));
 
         // Add state sets to the list in order.
-        List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100, screen140);
+        List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100);
 
         ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 atomTag);
@@ -619,7 +617,7 @@
 
         AtomTestUtils.popUntilFind(data, screenMin,
                 atom -> atom.getScreenBrightnessChanged().getLevel());
-        AtomTestUtils.popUntilFindFromEnd(data, screen140,
+        AtomTestUtils.popUntilFindFromEnd(data, screen100,
                 atom -> atom.getScreenBrightnessChanged().getLevel());
         // Assert that the events happened in the expected order.
         AtomTestUtils.assertStatesOccurredInOrder(stateSet, data, AtomTestUtils.WAIT_TIME_SHORT,
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index 9836e73..a8f9132 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -29,6 +29,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
+
 import android.content.ClipData;
 import android.content.ContentResolver;
 import android.content.Intent;
@@ -283,8 +285,9 @@
         addImage(mCloudPrimaryMediaGenerator, /* localId */ null, CLOUD_ID1);
 
         // Notification fails because the calling cloud provider isn't enabled
-        assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
-                        CloudProviderPrimary.AUTHORITY)).isFalse();
+        assertThrows("Unauthorized cloud media notification", SecurityException.class,
+                () -> MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+                        CloudProviderPrimary.AUTHORITY, COLLECTION_1));
 
         // Sleep because the notification API throttles requests with a 1s delay
         Thread.sleep(1500);
@@ -298,12 +301,13 @@
         setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
         assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
                         CloudProviderPrimary.AUTHORITY)).isTrue();
-        assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
-                        CloudProviderPrimary.AUTHORITY)).isTrue();
 
-        // Notification fails with a different provider enabled within the same app
-        assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
-                        CloudProviderSecondary.AUTHORITY)).isFalse();
+        MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+                CloudProviderPrimary.AUTHORITY, COLLECTION_1);
+
+        assertThrows("Unauthorized cloud media notification", SecurityException.class,
+                () -> MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+                        CloudProviderSecondary.AUTHORITY, COLLECTION_1));
 
         // Sleep because the notification API throttles requests with a 1s delay
         Thread.sleep(1500);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index 1b9149a..fcef908 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -33,6 +33,7 @@
 import android.net.Uri;
 import android.provider.MediaStore;
 
+import androidx.test.filters.SdkSuppress;
 import androidx.test.uiautomator.UiObject;
 import androidx.test.uiautomator.UiSelector;
 
@@ -69,8 +70,13 @@
         mActivity.finish();
     }
 
+    /**
+     * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+     * in a platform code change and is available Android T onwards.
+     */
     @Test
     @RequireRunOnWorkProfile
+    @SdkSuppress(minSdkVersion = 32, codeName = "T")
     public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
         final int imageCount = 2;
         createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);
@@ -107,9 +113,28 @@
         }
     }
 
+    /**
+     * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+     * in a platform code change and is available Android T onwards. Before that it needs to be
+     * explicitly allowlisted by the device admin.
+     */
+    @Test
+    @RequireRunOnWorkProfile
+    @SdkSuppress(maxSdkVersion = 31, codeName = "S")
+    public void testWorkApp_cannotAccessPersonalProfile_beforeT() throws Exception {
+        assertBlockedByAdmin(/* isInvokedFromWorkProfile */ true);
+    }
+
+    /**
+     * ACTION_PICK_IMAGES is allowlisted by default from work to personal only (not vice-a-versa)
+     */
     @Test
     @EnsureHasWorkProfile
     public void testPersonalApp_cannotAccessWorkProfile_default() throws Exception {
+        assertBlockedByAdmin(/* isInvokedFromWorkProfile */ false);
+    }
+
+    private void assertBlockedByAdmin(boolean isInvokedFromWorkProfile) throws Exception {
         Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
         // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
         intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
@@ -120,19 +145,22 @@
         profileButton.click();
         mDevice.waitForIdle();
 
-        // By default, ACTION_PICK_IMAGES is only allowlisted to access personal
-        // content from work profile, but not vice-a-versa.
-        assertBlockedByAdminDialog();
+        assertBlockedByAdminDialog(isInvokedFromWorkProfile);
     }
 
-    private void assertBlockedByAdminDialog() {
+    private void assertBlockedByAdminDialog(boolean isInvokedFromWorkProfile) {
         final String dialogTitle = "Blocked by your admin";
         assertWithMessage("Timed out while waiting for blocked by admin dialog to appear")
                 .that(new UiObject(new UiSelector().textContains(dialogTitle))
                         .waitForExists(SHORT_TIMEOUT))
                 .isTrue();
 
-        final String dialogDescription = "Accessing work data from a personal app is not permitted";
+        final String dialogDescription;
+        if (isInvokedFromWorkProfile) {
+            dialogDescription = "Accessing personal data from a work app is not permitted";
+        } else {
+            dialogDescription = "Accessing work data from a personal app is not permitted";
+        }
         assertWithMessage("Blocked by admin description is not as expected")
                 .that(new UiObject(new UiSelector().textContains(dialogDescription)).exists())
                 .isTrue();
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 0eb619c..b9f8f33 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -276,7 +276,7 @@
         swipeLeftAndWait();
 
         // Deselect one item
-        clickAndWait(findPreviewSelectCheckButton());
+        clickAndWait(findPreviewSelectedCheckButton());
 
         // Return selected items
         clickAndWait(findPreviewAddButton());
@@ -556,9 +556,9 @@
                 REGEX_PACKAGE_NAME + ":id/button_view_selected"));
     }
 
-    private static UiObject findPreviewSelectCheckButton() {
+    private static UiObject findPreviewSelectedCheckButton() {
         return new UiObject(new UiSelector().resourceIdMatches(
-                REGEX_PACKAGE_NAME + ":id/preview_select_check_button"));
+                REGEX_PACKAGE_NAME + ":id/preview_selected_check_button"));
     }
 
 
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index fa07976..a4ec998 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -48,13 +48,13 @@
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mockito;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -95,7 +95,7 @@
 
         setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
         assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
-                        CloudProviderPrimary.AUTHORITY)).isTrue();
+                CloudProviderPrimary.AUTHORITY)).isTrue();
 
         mSurfaceControllerListener = CloudProviderPrimary.getMockSurfaceControllerListener();
         mAssertInOrder = Mockito.inOrder(mSurfaceControllerListener);
@@ -113,7 +113,7 @@
 
     @Test
     public void testBasicVideoPreview() throws Exception {
-        initCloudProviderWithVideo(Pair.create(null, CLOUD_ID1));
+        initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
 
         launchPreviewMultiple(/* count */ 1);
 
@@ -121,7 +121,7 @@
         verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID1);
         // Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
         // CloudMediaProvider
-        verifyPlaybackEventReady(surfaceId);
+        verifyPlaybackStartedWhenPlayerReady(surfaceId);
 
         // TODO(b/215187981): Add test for onMediaPause()
 
@@ -144,9 +144,9 @@
     }
 
     @Test
-    @Ignore("Re-enable once b/219861183 is fixed")
     public void testSwipeAdjacentVideoPreview() throws Exception {
-        initCloudProviderWithVideo(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2));
+        initCloudProviderWithVideo(
+                Arrays.asList(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2)));
 
         launchPreviewMultiple(/* count */ 2);
 
@@ -154,14 +154,13 @@
         verifyInitialVideoPreviewSetup(surfaceIdForFirstVideoPreview, CLOUD_ID2);
         // Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
         // CloudMediaProvider
-        verifyPlaybackEventReady(surfaceIdForFirstVideoPreview);
+        verifyPlaybackStartedWhenPlayerReady(surfaceIdForFirstVideoPreview);
 
         // Swipe left preview mode
         swipeLeftAndWait();
 
         // Remote Preview calls onSurfaceCreated with monotonically increasing surfaceIds
         final int surfaceIdForSecondVideoPreview = 1;
-
         verifyAdjacentVideoSwipe(surfaceIdForFirstVideoPreview, surfaceIdForSecondVideoPreview,
                 CLOUD_ID1);
 
@@ -180,10 +179,9 @@
     }
 
     @Test
-    @Ignore("Re-enable once b/219861183 is fixed")
     public void testSwipeImageVideoPreview() throws Exception {
-        initCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
-        initCloudProviderWithVideo(Pair.create(null, CLOUD_ID2));
+        initCloudProviderWithImage(Arrays.asList(Pair.create(null, CLOUD_ID1)));
+        initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID2)));
         launchPreviewMultiple(/* count */ 2);
 
         // Remote Preview calls onSurfaceCreated with monotonically increasing surfaceIds
@@ -191,7 +189,7 @@
         verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID2);
         // Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
         // CloudMediaProvider
-        verifyPlaybackEventReady(surfaceId);
+        verifyPlaybackStartedWhenPlayerReady(surfaceId);
 
         // Swipe left preview mode
         swipeLeftAndWait();
@@ -209,10 +207,7 @@
         surfaceId++;
         verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID2);
 
-        // TODO (b/218871686): Remote Handler should wait for PLAYBACK_EVENT_READY to be sent.
-        // Once the above bug is fixed remove the following and call
-        // verifyPlaybackEventReady(surfaceId) instead
-        mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
+        verifyPlaybackStartedWhenPlayerReady(surfaceId);
 
         final UiObject addButton = findPreviewAddButton();
         addButton.click();
@@ -226,9 +221,10 @@
      *
      * @param oldSurfaceId the Surface ID which we are swiping away from
      * @param newSurfaceId the Surface ID to which we are swiping
-     * @param newMediaId the media ID of the video we are swiping to
+     * @param newMediaId   the media ID of the video we are swiping to
      */
-    private void verifyAdjacentVideoSwipe(int oldSurfaceId, int newSurfaceId, String newMediaId) {
+    private void verifyAdjacentVideoSwipe(int oldSurfaceId, int newSurfaceId, String newMediaId)
+            throws Exception {
         mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceCreated(eq(newSurfaceId),
                 any(), eq(newMediaId));
 
@@ -236,10 +232,7 @@
         // (swipe is complete).
         mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceDestroyed(eq(oldSurfaceId));
 
-        // Media plays automatically after the previous surface is destroyed (in other words the
-        // previous video screen is not visible at all and the swipe has completed). This is because
-        // the player is already ready.
-        mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(newSurfaceId));
+        verifyPlaybackStartedWhenPlayerReady(newSurfaceId);
     }
 
     /**
@@ -249,7 +242,7 @@
      * * Surface related callbacks (onSurfaceCreated and onSurfaceChanged)
      *
      * @param surfaceId Surface ID to set up video preview on
-     * @param mediaId Media ID to set up video preview with
+     * @param mediaId   Media ID to set up video preview with
      */
     private void verifyInitialVideoPreviewSetup(int surfaceId, String mediaId) {
         // Remote Preview calls onPlayerCreate as the first call to CloudMediaProvider
@@ -265,14 +258,16 @@
                 eq(VIDEO_PIXEL_FORMAT), anyInt(), anyInt());
     }
 
-    private void verifyPlaybackEventReady(int surfaceId) {
+    private void verifyPlaybackStartedWhenPlayerReady(int surfaceId) throws Exception {
         CloudProviderPrimary.sendPlaybackEvent(surfaceId, PLAYBACK_EVENT_READY);
+        // Wait for photo picker to receive the event and invoke media play via binder calls.
+        MediaStore.waitForIdle(mContext.getContentResolver());
         mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
     }
 
-    private void initCloudProviderWithImage(Pair<String, String>... mediaPairs)
+    private void initCloudProviderWithImage(List<Pair<String, String>> mediaPairs)
             throws Exception {
-        for (Pair<String, String> pair: mediaPairs) {
+        for (Pair<String, String> pair : mediaPairs) {
             addImage(mCloudPrimaryMediaGenerator, pair.first, pair.second);
         }
 
@@ -286,9 +281,9 @@
                 R.raw.lg_g4_iso_800_jpg);
     }
 
-    private void initCloudProviderWithVideo(Pair<String, String>... mediaPairs)
+    private void initCloudProviderWithVideo(List<Pair<String, String>> mediaPairs)
             throws Exception {
-        for (Pair<String, String> pair: mediaPairs) {
+        for (Pair<String, String> pair : mediaPairs) {
             addVideo(mCloudPrimaryMediaGenerator, pair.first, pair.second);
         }
 
@@ -302,7 +297,7 @@
                 R.raw.test_video);
     }
 
-    private void launchPreviewMultiple(int count) throws  Exception {
+    private void launchPreviewMultiple(int count) throws Exception {
         final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
         // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
         intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
@@ -313,8 +308,7 @@
 
         assertThat(itemCount).isEqualTo(count);
 
-        for (int i = 0; i < itemCount; i++) {
-            final UiObject item = itemList.get(i);
+        for (final UiObject item : itemList) {
             item.click();
             mDevice.waitForIdle();
         }
@@ -322,6 +316,9 @@
         final UiObject viewSelectedButton = findViewSelectedButton();
         viewSelectedButton.click();
         mDevice.waitForIdle();
+
+        // Wait for CloudMediaProvider binder calls to finish.
+        MediaStore.waitForIdle(mContext.getContentResolver());
     }
 
     private static UiObject findViewSelectedButton() {
@@ -329,17 +326,23 @@
                 REGEX_PACKAGE_NAME + ":id/button_view_selected"));
     }
 
-    private void swipeLeftAndWait() {
+    private void swipeLeftAndWait() throws Exception {
         final int width = mDevice.getDisplayWidth();
         final int height = mDevice.getDisplayHeight();
         mDevice.swipe(width / 2, height / 2, width / 4, height / 2, 10);
         mDevice.waitForIdle();
+
+        // Wait for CloudMediaProvider binder calls to finish.
+        MediaStore.waitForIdle(mContext.getContentResolver());
     }
 
-    private void swipeRightAndWait() {
+    private void swipeRightAndWait() throws Exception {
         final int width = mDevice.getDisplayWidth();
         final int height = mDevice.getDisplayHeight();
         mDevice.swipe(width / 4, height / 2, width / 2, height / 2, 10);
         mDevice.waitForIdle();
+
+        // Wait for CloudMediaProvider binder calls to finish.
+        MediaStore.waitForIdle(mContext.getContentResolver());
     }
 }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
index b6bb357..089aa58 100755
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
@@ -144,8 +144,8 @@
         mStrokeLenPxX = (int) (GESTURE_LENGTH_INCHES * metrics.xdpi);
         // The threshold is determined by xdpi.
         mStrokeLenPxY = mStrokeLenPxX;
-        mMaxAdjustedStrokeLenPxX = metrics.heightPixels / 2;
-        mMaxAdjustedStrokeLenPxY = metrics.widthPixels / 2;
+        mMaxAdjustedStrokeLenPxX = metrics.widthPixels / 2;
+        mMaxAdjustedStrokeLenPxY = metrics.heightPixels / 2;
         final boolean screenWideEnough = metrics.widthPixels / 2 > mStrokeLenPxX;
         final boolean screenHighEnough =  metrics.heightPixels / 2 > mStrokeLenPxY;
         mScreenBigEnough = screenWideEnough && screenHighEnough;
@@ -641,14 +641,18 @@
                 adjustStrokeDurationForSlop(STROKE_MS, dx, slopAdjustedDx),
                 adjustStrokeDurationForSlop(STROKE_MS, dy, slopAdjustedDy));
 
+        final PointF tapLocation = new PointF(mTapLocation);
+        final float locationOffsetX = (fingerCount - 1) * fingerOffset;
+        tapLocation.offset(dx > 0 ? -locationOffsetX : locationOffsetX , 0);
         for (int currentFinger = 0; currentFinger < fingerCount; ++currentFinger) {
             // Make sure adjustments don't take us outside of screen boundaries.
-            assertTrue(slopAdjustedDx + (fingerOffset * currentFinger) < mMaxAdjustedStrokeLenPxX);
+            assertTrue(slopAdjustedDx + (fingerOffset * currentFinger) < (mMaxAdjustedStrokeLenPxX
+                    + locationOffsetX));
             assertTrue(slopAdjustedDy < mMaxAdjustedStrokeLenPxY);
             builder.addStroke(
                     GestureUtils.swipe(
-                            add(mTapLocation, fingerOffset * currentFinger, 0),
-                            add(mTapLocation, slopAdjustedDx + (fingerOffset * currentFinger),
+                            add(tapLocation, fingerOffset * currentFinger, 0),
+                            add(tapLocation, slopAdjustedDx + (fingerOffset * currentFinger),
                                     slopAdjustedDy),
                             slopAdjustedStrokeDuration));
         }
@@ -657,9 +661,9 @@
 
     private float adjustStrokeDeltaForSlop(int fingerCount, float strokeDelta) {
         if (strokeDelta > 0.0f) {
-            return strokeDelta + (fingerCount * mScaledTouchSlop);
+            return Math.max(strokeDelta, fingerCount * mScaledTouchSlop + 10);
         } else if (strokeDelta < 0.0f) {
-            return strokeDelta - (fingerCount * mScaledTouchSlop);
+            return Math.min(strokeDelta, -(fingerCount * mScaledTouchSlop + 10));
         }
         return strokeDelta;
     }
diff --git a/tests/app/src/android/app/cts/NearbyDeviceTest.kt b/tests/app/src/android/app/cts/NearbyDeviceTest.kt
new file mode 100644
index 0000000..07b2364
--- /dev/null
+++ b/tests/app/src/android/app/cts/NearbyDeviceTest.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts
+
+import android.media.NearbyDevice
+import android.os.Parcel
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests for [android.media.NearbyDevice]. */
+@RunWith(AndroidJUnit4::class)
+class NearbyDeviceTest {
+
+    @Test
+    fun getMediaRoute2Id_returnsIdPassedIn() {
+        val id = "testIdHere"
+        val nearbyDevice = NearbyDevice(id, NearbyDevice.RANGE_UNKNOWN)
+
+        assertThat(nearbyDevice.mediaRoute2Id).isEqualTo(id)
+    }
+
+    @Test
+    fun getRangeZone_returnsRangeZonePassedIn() {
+        val rangeZone = NearbyDevice.RANGE_WITHIN_REACH
+        val nearbyDevice = NearbyDevice("id", rangeZone)
+
+        assertThat(nearbyDevice.rangeZone).isEqualTo(rangeZone)
+    }
+
+    @Test
+    fun writeToAndCreateFromParcel_resultHasCorrectIdAndRangeZone() {
+        val id = "testIdHere"
+        val rangeZone = NearbyDevice.RANGE_WITHIN_REACH
+        val nearbyDevice = NearbyDevice(id, rangeZone)
+
+        val parcel = Parcel.obtain()
+        nearbyDevice.writeToParcel(parcel, 0)
+        parcel.setDataPosition(0)
+
+        val resultFromParcel = NearbyDevice.CREATOR.createFromParcel(parcel)
+
+        assertThat(resultFromParcel.mediaRoute2Id).isEqualTo(id)
+        assertThat(resultFromParcel.rangeZone).isEqualTo(rangeZone)
+    }
+}
diff --git a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
index 7094e26..82000a4 100644
--- a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
@@ -151,7 +151,10 @@
      */
     private void verifyNotificationBubbleState(int id, boolean shouldBeBubble) {
         // FLAG_BUBBLE relies on notification being posted, wait for notification listener
-        sleep();
+        try {
+            Thread.sleep(700);
+        } catch (InterruptedException ignored) {
+        }
 
         for (StatusBarNotification sbn : mListener.mPosted) {
             if (sbn.getId() == id) {
diff --git a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java b/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
index 6769cf8..98b1bca 100644
--- a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
+++ b/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
@@ -40,7 +40,7 @@
 public class PropertyInvalidatedCacheTests {
 
     // Configuration for creating caches
-    private static final int MODULE = PropertyInvalidatedCache.MODULE_TEST;
+    private static final String MODULE = PropertyInvalidatedCache.MODULE_TEST;
     private static final String API = "testApi";
 
     // This class is a proxy for binder calls.  It contains a counter that increments
@@ -216,11 +216,11 @@
             this(MODULE, API);
         }
 
-        TestCache(int module, String api) {
+        TestCache(String module, String api) {
             this(module, api, new TestQuery());
         }
 
-        TestCache(int module, String api, TestQuery query) {
+        TestCache(String module, String api, TestQuery query) {
             super(4, module, api, "testCache7", query);
             mQuery = query;
             setTestMode(true);
diff --git a/tests/camera/OWNERS b/tests/camera/OWNERS
index d1d18b4..9270e30 100644
--- a/tests/camera/OWNERS
+++ b/tests/camera/OWNERS
@@ -1,2 +1,5 @@
 # Bug component: 41727
 include platform/frameworks/av:/camera/OWNERS
+
+per-file *ImageReader* = file:platform/frameworks/base:/graphics/java/android/graphics/OWNERS
+per-file *ImageWriter* = file:platform/frameworks/base:/graphics/java/android/graphics/OWNERS
\ No newline at end of file
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index cbbaea8..5db96a4 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -1853,6 +1853,10 @@
             mCollector.expectTrue("The recommended 10-bit dynamic range profile must " +
                             "not be the same as standard",
                     recommendedProfile != DynamicRangeProfiles.STANDARD);
+            mCollector.expectTrue("HLG10 profile must not have extra latency!",
+                    !dynamicProfiles.isExtraLatencyPresent(DynamicRangeProfiles.HLG10));
+            mCollector.expectTrue("STANDARD profile must not have extra latency!",
+                    !dynamicProfiles.isExtraLatencyPresent(DynamicRangeProfiles.STANDARD));
 
             // Verify constraints validity. For example if HLG10 advertises support for HDR10, then
             // there shouldn't be any HDR10 constraints related to HLG10.
diff --git a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
index 82760f0..2a65d76 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
@@ -128,6 +128,20 @@
                 torchStrength = mCameraManager.getTorchStrengthLevel(id);
                 assertEquals(torchStrength, minLevel);
 
+                try {
+                    mCameraManager.turnOnTorchWithStrengthLevel(id, 0);
+                    fail("turnOnTorchWithStrengthLevel with strengthLevel = 0 must fail.");
+                } catch (IllegalArgumentException e) {
+                    Log.v(TAG, e.getMessage());
+                }
+
+                try {
+                    mCameraManager.turnOnTorchWithStrengthLevel(id, maxLevel + 1);
+                    fail("turnOnTorchWithStrengthLevel with strengthLevel" + (maxLevel + 1) + " must fail.");
+                } catch (IllegalArgumentException e) {
+                    Log.v(TAG, e.getMessage());
+                }
+
                 // Turn off the torch and verify if the strength level gets
                 // reset to default level.
                 mCameraManager.setTorchMode(id, false);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
index 3fd524a..1ae61a5 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
@@ -290,6 +290,7 @@
             ImageWriter writer = new ImageWriter
                 .Builder(surface)
                 .setWidthAndHeight(imageWriterWidth, imageWriterHeight)
+                .setMaxImages(MAX_NUM_IMAGES)
                 .setImageFormat(ImageFormat.YV12)
                 .setUsage(usage)
                 .build();
@@ -298,8 +299,8 @@
             // ImageFormat.YV12 HAL dataspace is DataSpace.DATASPACE_JFIF
             assertEquals(imageWriterWidth, writer.getWidth());
             assertEquals(imageWriterHeight, writer.getHeight());
+            assertEquals(MAX_NUM_IMAGES, writer.getMaxImages());
             assertEquals(DataSpace.DATASPACE_JFIF, writer.getDataSpace());
-            assertEquals(imageWriterHeight, writer.getHeight());
             assertEquals(usage, writer.getUsage());
 
             assertEquals(DataSpace.DATASPACE_JFIF, image.getDataSpace());
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
index 3bc4743..44abc72 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
@@ -27,6 +27,7 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_SECURE_LOCK_SCREEN;
 
 import static com.android.bedstead.metricsrecorder.truth.MetricQueryBuilderSubject.assertThat;
 import static com.android.bedstead.remotedpc.RemoteDpc.DPC_COMPONENT_NAME;
@@ -59,6 +60,7 @@
 
 // TODO(b/191640667): Parameterize the length limit tests with multiple limits
 @RunWith(BedsteadJUnit4.class)
+@RequireFeature(FEATURE_SECURE_LOCK_SCREEN)
 public final class ResetPasswordWithTokenTest {
 
     private static final String NOT_COMPLEX_PASSWORD = "1234";
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 ac61724..032890ea 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
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.server.wm.TestJournalProvider;
-import android.view.OnBackInvokedCallback;
-import android.view.OnBackInvokedDispatcher;
+import android.window.OnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
 
 import androidx.annotation.Nullable;
 
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index 308d3b9..ff60f60 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -16,6 +16,7 @@
 
 package android.server.wm.jetpack.utils;
 
+import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
 import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getResumedActivityById;
@@ -39,6 +40,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
 import androidx.window.extensions.embedding.SplitInfo;
 import androidx.window.extensions.embedding.SplitPairRule;
 import androidx.window.extensions.embedding.SplitRule;
@@ -242,14 +244,22 @@
             layoutDir = primaryActivity.getResources().getConfiguration().getLayoutDirection();
         }
 
+        // Compute the expected bounds
         final float splitRatio = splitRule.getSplitRatio();
         final Rect parentBounds = getMaximumActivityBounds(primaryActivity);
         final Rect expectedPrimaryActivityBounds = new Rect();
         final Rect expectedSecondaryActivityBounds = new Rect();
         getExpectedPrimaryAndSecondaryBounds(layoutDir, splitRatio, parentBounds,
                 expectedPrimaryActivityBounds, expectedSecondaryActivityBounds);
+
+        final ActivityEmbeddingComponent activityEmbeddingComponent = getWindowExtensions()
+                .getActivityEmbeddingComponent();
+
+        // Verify that both activities are embedded and that the bounds are correct
+        assertTrue(activityEmbeddingComponent.isActivityEmbedded(primaryActivity));
         assertEquals(expectedPrimaryActivityBounds, getActivityBounds(primaryActivity));
         if (secondaryActivity != null) {
+            assertTrue(activityEmbeddingComponent.isActivityEmbedded(secondaryActivity));
             assertEquals(expectedSecondaryActivityBounds, getActivityBounds(secondaryActivity));
         }
     }
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 f4db285..326052b 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,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.uiautomator.UiDevice;
 import android.view.KeyEvent;
-import android.view.OnBackInvokedCallback;
+import android.window.OnBackInvokedCallback;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
@@ -35,6 +35,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import org.junit.Ignore;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -61,6 +63,7 @@
         mInstrumentation.getUiAutomation().adoptShellPermissionIdentity();
     }
 
+    @Ignore ("b/222208384")
     @Test
     public void registerCallback_initialized() {
         CountDownLatch latch = registerBackCallback();
@@ -68,6 +71,7 @@
         invokeBackAndAssertCallbackIsCalled(latch);
     }
 
+    @Ignore ("b/222208384")
     @Test
     public void registerCallback_created() {
         mScenario.moveToState(Lifecycle.State.CREATED);
@@ -77,6 +81,7 @@
         invokeBackAndAssertCallbackIsCalled(latch);
     }
 
+    @Ignore ("b/222208384")
     @Test
     public void registerCallback_resumed() {
         mScenario.moveToState(Lifecycle.State.CREATED);
@@ -86,6 +91,7 @@
         invokeBackAndAssertCallbackIsCalled(latch);
     }
 
+    @Ignore ("b/222208384")
     @Test
     public void onBackPressedNotCalled() {
         mScenario.moveToState(Lifecycle.State.CREATED)
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index ca997ab..0fda662 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -38,6 +38,7 @@
 import android.server.wm.cts.R;
 import android.view.Gravity;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.RelativeLayout;
@@ -45,16 +46,20 @@
 
 import androidx.test.filters.FlakyTest;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 @Presubmit
 @FlakyTest(detail = "Promote once confirmed non-flaky")
 public class KeepClearRectsTests extends WindowManagerTestBase {
+    private static final long FOCUS_VIEW_CHECK_TIMEOUT = 3000;
     private static final List<Rect> TEST_KEEP_CLEAR_RECTS =
             Arrays.asList(new Rect(0, 0, 25, 25),
                           new Rect(30, 0, 50, 25),
@@ -220,7 +225,7 @@
     }
 
     @Test
-    public void testSetPreferKeepClearOverridesMultipleRects() {
+    public void testSetPreferKeepClearCombinesWithMultipleRects() {
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
         final TestActivity activity = mTestSession.getActivity();
         final ComponentName componentName = activity.getComponentName();
@@ -232,7 +237,9 @@
                            getKeepClearRectsForActivity(activity));
 
         mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
-        assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds), componentName),
+        final List<Rect> combinedRects = new ArrayList<>(TEST_KEEP_CLEAR_RECTS);
+        combinedRects.add(viewBounds);
+        assertSameElements(getRectsInScreenSpace(combinedRects, componentName),
                            getKeepClearRectsForActivity(activity));
 
         mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(false));
@@ -316,6 +323,38 @@
     }
 
     @Test
+    public void testFocusedViewDeclaredAsKeepClearArea() throws Exception {
+        int preferKeepClearForFocusDelay = ViewConfiguration.get(
+                mContext).getPreferKeepClearForFocusDelay();
+
+        assumeTrue(preferKeepClearForFocusDelay >= 0);
+
+        mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
+        final TestActivity activity = mTestSession.getActivity();
+
+        final Rect viewBounds = new Rect(0, 0, 60, 60);
+        final View v = createTestViewInActivity(activity, viewBounds);
+        assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+
+        mTestSession.runOnMainSyncAndWait(() -> {
+            v.setFocusable(true);
+            v.requestFocus();
+        });
+
+        PollingCheck.check("Expected focused view bounds as keep clear area",
+                preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+                () -> hasSameElements(
+                        getRectsInScreenSpace(Arrays.asList(viewBounds),
+                                activity.getComponentName()),
+                        getKeepClearRectsForActivity(activity)));
+
+        mTestSession.runOnMainSyncAndWait(() -> v.setFocusable(false));
+        PollingCheck.check("Expected no keep clear areas after clearing focus, but found some",
+                preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+                () -> hasSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity)));
+    }
+
+    @Test
     public void testKeepClearRectsGetTranslatedToWindowSpace() {
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
         final TestActivity activity = mTestSession.getActivity();
@@ -350,15 +389,17 @@
             v.setPreferKeepClear(false);
             v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
         });
-        assertSameElements(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName),
+        List<Rect> expectedRectsInScreenSpace =
+                getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName);
+        assertSameElements(expectedRectsInScreenSpace,
                            getKeepClearRectsForActivity(activity));
 
         activity.finishAndRemoveTask();
-        mWmState.waitAndAssertActivityRemoved(componentName);
-        assertSameElements(EMPTY_LIST, getKeepClearRectsOnDefaultDisplay());
+        assertTrue(Collections.disjoint(
+                expectedRectsInScreenSpace,
+                getKeepClearRectsOnDefaultDisplay()));
     }
 
-
     @Test
     public void testKeepClearRectsOnDisplayTwoWindows() {
         mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
@@ -371,7 +412,7 @@
         assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds), componentName),
                            getKeepClearRectsForActivity(activity));
 
-        final String title = "KeepCleasrRectsTestWindow";
+        final String title = "KeepClearRectsTestWindow";
         mTestSession.runOnMainSyncAndWait(() -> {
             final View testView = new View(activity);
             testView.setPreferKeepClear(true);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index 6742666..4cf56b9 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -511,12 +511,12 @@
     }
 
     @Test
-    public void testLaunchFromLauncherWithEmptyIconOptions() throws Exception {
+    public void testLaunchFromLauncherWithSolidColorOptions() throws Exception {
         assumeFalse(isLeanBack());
         final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
         TestJournalProvider.TestJournalContainer.start();
         final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
-                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent ->
                 intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true), noIconOptions);
         mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, STATE_RESUMED);
@@ -573,9 +573,9 @@
     }
 
     @Test
-    public void testLaunchActivitiesWithEmptyOptions() throws Exception {
+    public void testLaunchActivitiesWithSolidColorOptions() throws Exception {
         final ActivityOptions options = ActivityOptions.makeBasic()
-                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
 
         final Intent[] intents = new Intent[] {
                 new Intent().setComponent(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY)
@@ -673,7 +673,7 @@
         assumeFalse(isLeanBack());
         final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
         final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
-                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+                .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
 
         startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
                 intent -> {}, noIconOptions);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index a611731..c1d815c 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -152,6 +152,7 @@
     private String mInputMethodWindowAppToken = null;
     private boolean mDisplayFrozen;
     private boolean mSanityCheckFocusedWindow = true;
+    private boolean mWindowFramesValid;
 
     static String appStateToString(int appState) {
         switch (appState) {
@@ -322,6 +323,7 @@
 
             retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty()
                     || mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null)
+                    || !mWindowFramesValid
                     || (mTopResumedActivityRecord == null
                     || mResumedActivitiesInRootTasks.isEmpty())
                     && !mKeyguardControllerState.keyguardShowing;
@@ -348,6 +350,9 @@
         if (mFocusedApp == null) {
             logE("No Focused App...");
         }
+        if (!mWindowFramesValid) {
+            logE("Window Frames Invalid...");
+        }
     }
 
     private byte[] executeShellCommand(String cmd) {
@@ -431,6 +436,7 @@
             mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
         }
         mDisplayFrozen = state.displayFrozen;
+        mWindowFramesValid = state.windowFramesValid;
     }
 
     private void reset() {
@@ -452,6 +458,7 @@
         mPinnedStackMovementBounds.setEmpty();
         mInputMethodWindowAppToken = null;
         mDisplayFrozen = false;
+        mWindowFramesValid = false;
     }
 
     public String getFocusedApp() {
diff --git a/tests/inputmethod/Android.bp b/tests/inputmethod/Android.bp
index 4902be2..268bf55 100644
--- a/tests/inputmethod/Android.bp
+++ b/tests/inputmethod/Android.bp
@@ -32,6 +32,7 @@
         "androidx.test.uiautomator_uiautomator",
         "compatibility-device-util-axt",
         "cts-wm-util",
+        "cts-inputmethod-util",
         "ctstestrunner-axt",
         "CtsMockInputMethodLib",
         "CtsMockSpellCheckerLib",
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index 6dd1836..1bb3122 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -19,6 +19,7 @@
      package="android.view.inputmethod.cts"
      android:targetSandboxVersion="2">
 
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
     <application android:label="CtsInputMethodTestCases"
          android:multiArch="true"
@@ -26,48 +27,7 @@
 
         <uses-library android:name="android.test.runner"/>
 
-        <activity android:name="android.view.inputmethod.cts.util.TestActivity"
-             android:theme="@style/no_starting_window"
-             android:label="TestActivity"
-             android:configChanges="fontScale|smallestScreenSize|screenSize|screenLayout|orientation"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
-            </intent-filter>
-        </activity>
-        <activity android:name="android.view.inputmethod.cts.util.TestActivity2"
-                  android:theme="@style/no_starting_window"
-                  android:label="TestActivity2"
-                  android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.inputmethod.cts.util.StateInitializeActivity"
-             android:theme="@style/no_starting_window"
-             android:label="StateInitializeActivity"
-             android:configChanges="fontScale"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
-            </intent-filter>
-        </activity>
-
-        <!--
-                      In order to test window-focus-stealing from other process, let this service run in a
-                      separate process. -->
-        <service android:name="android.view.inputmethod.cts.util.WindowFocusStealerService"
-             android:process=":focusstealer"
-             android:exported="false">
-        </service>
-
-        <service android:name="android.view.inputmethod.cts.util.WindowFocusHandleService"
-             android:exported="false">
-        </service>
+        <!-- TestActivity etc are merged from util/AndroidManifest.xml -->
 
     </application>
 
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index a7bcdce..d03bf4b 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -367,8 +367,15 @@
                     }
                     case "requestCursorUpdates": {
                         final int cursorUpdateMode = command.getExtras().getInt("cursorUpdateMode");
-                        return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
-                                cursorUpdateMode);
+                        final int cursorUpdateFilter =
+                                command.getExtras().getInt("cursorUpdateFilter", -1);
+                        if (cursorUpdateFilter == -1) {
+                            return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
+                                    cursorUpdateMode);
+                        } else {
+                            return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
+                                    cursorUpdateMode, cursorUpdateFilter);
+                        }
                     }
                     case "getHandler":
                         return getMemorizedOrCurrentInputConnection().getHandler();
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 2133846..a779410 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -1149,6 +1149,34 @@
     }
 
     /**
+     * Lets {@link MockIme} to call {@link InputConnection#requestCursorUpdates(int, int)} with the
+     * given parameters.
+     *
+     * <p>This triggers {@code getCurrentInputConnection().requestCursorUpdates(
+     * cursorUpdateMode, cursorUpdateFilter)}.
+     * </p>
+     *
+     * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from
+     * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the
+     * value returned from the API.</p>
+     *
+     * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p>
+     *
+     * @param cursorUpdateMode to be passed as the {@code cursorUpdateMode} parameter
+     * @param cursorUpdateFilter to be passed as the {@code cursorUpdateFilter} parameter
+     * @return {@link ImeCommand} object that can be passed to
+     *         {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to
+     *         wait until this event is handled by {@link MockIme}
+     */
+    @NonNull
+    public ImeCommand callRequestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
+        final Bundle params = new Bundle();
+        params.putInt("cursorUpdateMode", cursorUpdateMode);
+        params.putInt("cursorUpdateFilter", cursorUpdateFilter);
+        return callCommandInternal("requestCursorUpdates", params);
+    }
+
+    /**
      * Lets {@link MockIme} to call {@link InputConnection#getHandler()} with the given parameters.
      *
      * <p>This triggers {@code getCurrentInputConnection().getHandler()}.</p>
diff --git a/tests/inputmethod/res/values/colors.xml b/tests/inputmethod/res/values/colors.xml
deleted file mode 100644
index 1d87ea8..0000000
--- a/tests/inputmethod/res/values/colors.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2017 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- -->
-
-<resources>
-    <drawable name="blue">#770000ff</drawable>
-</resources>
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index 31b7a92..e8ff4f0 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -454,6 +454,7 @@
 
             final AtomicReference<EditText> editTextRef = new AtomicReference<>();
             final AtomicInteger requestCursorUpdatesCallCount = new AtomicInteger();
+            final AtomicInteger requestCursorUpdatesWithFilterCallCount = new AtomicInteger();
             TestActivity.startSync(activity -> {
                 final LinearLayout layout = new LinearLayout(activity);
                 layout.setOrientation(LinearLayout.VERTICAL);
@@ -472,6 +473,13 @@
                                 }
                                 return false;
                             }
+
+                            @Override
+                            public boolean requestCursorUpdates(
+                                    int cursorUpdateMode, int cursorUpdateFilter) {
+                                requestCursorUpdatesWithFilterCallCount.incrementAndGet();
+                                return requestCursorUpdates(cursorUpdateMode | cursorUpdateFilter);
+                            }
                         };
                     }
                 };
@@ -538,6 +546,37 @@
                     TIMEOUT).getArguments().getParcelable("cursorAnchorInfo");
             assertNotNull(receivedCursorAnchorInfo1);
             assertEquals(receivedCursorAnchorInfo1, originalCursorAnchorInfo1);
+
+            requestCursorUpdatesCallCount.set(0);
+            requestCursorUpdatesWithFilterCallCount.set(0);
+            // Request Cursor updates with Mode and Filter
+            // Make sure that InputConnection#requestCursorUpdates() returns true with mode and
+            // data filter.
+            builder = new EditorBoundsInfo.Builder();
+            builder.setEditorBounds(new RectF(1f, 1f, 2f, 3f));
+            final CursorAnchorInfo originalCursorAnchorInfo2 = new CursorAnchorInfo.Builder()
+                    .setMatrix(new Matrix())
+                    .setEditorBoundsInfo(builder.build())
+                    .build();
+            assertTrue(expectCommand(stream,
+                    imeSession.callRequestCursorUpdates(
+                            InputConnection.CURSOR_UPDATE_IMMEDIATE,
+                                    InputConnection.CURSOR_UPDATE_FILTER_EDITOR_BOUNDS
+                                    | InputConnection.CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS
+                                    | InputConnection.CURSOR_UPDATE_FILTER_INSERTION_MARKER),
+                    TIMEOUT).getReturnBooleanValue());
+
+            // Make sure that requestCursorUpdates() actually gets called only once.
+            assertEquals(1, requestCursorUpdatesCallCount.get());
+            assertEquals(1, requestCursorUpdatesWithFilterCallCount.get());
+            runOnMainSync(() -> editText.getContext().getSystemService(InputMethodManager.class)
+                    .updateCursorAnchorInfo(editText, originalCursorAnchorInfo2));
+
+            final CursorAnchorInfo receivedCursorAnchorInfo2 = expectEvent(stream,
+                    event -> "onUpdateCursorAnchorInfo".equals(event.getEventName()),
+                    TIMEOUT).getArguments().getParcelable("cursorAnchorInfo");
+            assertNotNull(receivedCursorAnchorInfo2);
+            assertEquals(receivedCursorAnchorInfo2, originalCursorAnchorInfo2);
         }
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index c68149f..265940f2 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -16,6 +16,8 @@
 
 package android.view.inputmethod.cts;
 
+import static android.provider.Settings.Global.STYLUS_HANDWRITING_ENABLED;
+
 import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
@@ -26,8 +28,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import android.Manifest;
 import android.content.Context;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
@@ -43,10 +47,14 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
 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;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -61,13 +69,44 @@
 public class StylusHandwritingTest extends EndToEndImeTestBase {
     private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
     private static final long NOT_EXPECT_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
+    private static final int SETTING_VALUE_ON = 1;
+    private static final int SETTING_VALUE_OFF = 0;
     private static final String TEST_MARKER_PREFIX =
             "android.view.inputmethod.cts.StylusHandwritingTest";
 
+    private Context mContext;
+    private int mHwInitialState;
+    private boolean mShouldRestoreInitialHwState;
+
+    @Rule
+    public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+            InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+            Manifest.permission.WRITE_SECURE_SETTINGS);
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        mHwInitialState = Settings.Global.getInt(mContext.getContentResolver(),
+                STYLUS_HANDWRITING_ENABLED, SETTING_VALUE_OFF);
+        if (mHwInitialState != SETTING_VALUE_ON) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    STYLUS_HANDWRITING_ENABLED, SETTING_VALUE_ON);
+            mShouldRestoreInitialHwState = true;
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mShouldRestoreInitialHwState) {
+            mShouldRestoreInitialHwState = false;
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    STYLUS_HANDWRITING_ENABLED, mHwInitialState);
+        }
+    }
+
     @Test
     public void testHandwritingStartAndFinish() throws Exception {
-        final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
-                .getTargetContext().getSystemService(InputMethodManager.class);
+        final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
         try (MockImeSession imeSession = MockImeSession.create(
                 InstrumentationRegistry.getInstrumentation().getContext(),
                 InstrumentationRegistry.getInstrumentation().getUiAutomation(),
@@ -120,8 +159,7 @@
      */
     @Test
     public void testHandwritingStylusEvents() throws Exception {
-        final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
-                .getTargetContext().getSystemService(InputMethodManager.class);
+        final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
         try (MockImeSession imeSession = MockImeSession.create(
                 InstrumentationRegistry.getInstrumentation().getContext(),
                 InstrumentationRegistry.getInstrumentation().getUiAutomation(),
diff --git a/tests/inputmethod/tests32/Android.bp b/tests/inputmethod/tests32/Android.bp
new file mode 100644
index 0000000..fa09833
--- /dev/null
+++ b/tests/inputmethod/tests32/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+    name: "CtsInputMethodTestCases32",
+    defaults: ["cts_defaults"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    compile_multilib: "both",
+    libs: ["android.test.runner"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "compatibility-device-util-axt",
+        "cts-wm-util",
+        "cts-inputmethod-util",
+        "ctstestrunner-axt",
+        "CtsMockInputMethodLib",
+        "CtsMockSpellCheckerLib",
+        "CtsLegacyImeClientTestLib",
+        "testng",
+        "kotlin-test",
+    ],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+        "src/**/I*.aidl",
+    ],
+    aidl: {
+        local_include_dirs: ["src"],
+    },
+    sdk_version: "test_current",
+}
diff --git a/tests/inputmethod/tests32/AndroidManifest.xml b/tests/inputmethod/tests32/AndroidManifest.xml
new file mode 100644
index 0000000..3813e47
--- /dev/null
+++ b/tests/inputmethod/tests32/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.view.inputmethod.cts.sdk32">
+
+    <uses-sdk android:targetSdkVersion="32" />
+
+    <application android:label="CtsInputMethodSdk28TestCases" />
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.view.inputmethod.cts.sdk32" />
+
+</manifest>
diff --git a/tests/inputmethod/tests32/AndroidTest.xml b/tests/inputmethod/tests32/AndroidTest.xml
new file mode 100644
index 0000000..9c5b128
--- /dev/null
+++ b/tests/inputmethod/tests32/AndroidTest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration description="Config for CTS InputMethodFramework SDK 32 compatibility test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="inputmethod" />
+    <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
+    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsInputMethodTestCases32.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>
+    <!--
+        TODO(yukawa): come up with a proper way to take care of devices that do not support
+        installable IMEs.  Ideally target_preparer should have an option to annotate required
+        features, e.g. android.software.input_methods so that we can conditionally install APKs
+        based on the feature supported in the target device.
+    -->
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+        <option name="run-command" value="wm dismiss-keyguard" />
+    </target_preparer>
+
+    <!--
+        A (separate) standalone test app APK is needed to test implicit app-visibility from the IME
+        process to the IME target process, because if the IME target process is directly interacting
+        with MockIme process via MockImeSession, then the system would already give the MockIme an
+        implicit app-visibility back to the test app.  To fully test app-visibility scenario,
+        MockImeSession cannot be used in the process where the focused Activity is hosted.
+    -->
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <!--
+            In order to simulate the scenario where the IME client process is normally
+            installed, explicitly set false here.  Otherwise, the test APP will be installed under
+            force-queryable mode, which makes the test useless.
+        -->
+        <option name="force-queryable" value="false" />
+        <option name="test-file-name" value="CtsInputMethodStandaloneTestApp.apk" />
+    </target_preparer>
+
+    <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.mockime"  />
+        <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.mockime" />
+        <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS android.view.inputmethod.ctstestapp"  />
+        <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS android.view.inputmethod.ctstestapp" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.view.inputmethod.cts.sdk32" />
+        <option name="runtime-hint" value="1m" />
+    </test>
+</configuration>
diff --git a/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt b/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt
new file mode 100644
index 0000000..6d1907c
--- /dev/null
+++ b/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.view.inputmethod.cts.sdk32
+
+import android.content.Context
+import android.view.inputmethod.InputMethodManager
+import android.view.inputmethod.cts.util.EndToEndImeTestBase
+import android.view.inputmethod.cts.util.InputMethodVisibilityVerifier.expectImeVisible
+import android.view.inputmethod.cts.util.MockTestActivityUtil
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.cts.mockime.ImeSettings
+import com.android.cts.mockime.MockImeSession
+import org.junit.Assert.assertEquals
+import org.junit.AssumptionViolatedException
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.TimeUnit
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class InputMethodManagerTest : EndToEndImeTestBase() {
+
+    val context: Context = InstrumentationRegistry.getInstrumentation().getContext()
+    val uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
+
+    @Test
+    fun getInputMethodWindowVisibleHeight_returnsZeroIfNotFocused() {
+        val imm = context.getSystemService(InputMethodManager::class.java)!!
+        MockImeSession.create(context, uiAutomation, ImeSettings.Builder()).use { session ->
+            MockTestActivityUtil.launchSync(false /* instant */, TIMEOUT).use {
+                session.callRequestShowSelf(0)
+                expectImeVisible(TIMEOUT)
+                assertEquals(
+                        "Only IME target UID may observe the visible height of the IME",
+                        0,
+                        imm.reflectivelyGetInputMethodWindowVisibleHeight()
+                )
+            }
+        }
+    }
+
+    fun InputMethodManager.reflectivelyGetInputMethodWindowVisibleHeight() =
+        try {
+            InputMethodManager::class.java
+                    .getMethod("getInputMethodWindowVisibleHeight")
+                    .invoke(this) as Int
+        } catch (_: NoSuchMethodError) {
+            throw AssumptionViolatedException("getInputMethodWindowVisibleHeight doesn't exist")
+        }
+
+    companion object {
+        val TIMEOUT = TimeUnit.SECONDS.toMillis(5)
+    }
+}
diff --git a/tests/inputmethod/util/Android.bp b/tests/inputmethod/util/Android.bp
new file mode 100644
index 0000000..5637f79
--- /dev/null
+++ b/tests/inputmethod/util/Android.bp
@@ -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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+    name: "cts-inputmethod-util",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "androidx.test.uiautomator_uiautomator",
+        "compatibility-device-util-axt",
+        "cts-wm-util",
+        "ctstestrunner-axt",
+        "CtsMockInputMethodLib",
+        "CtsMockSpellCheckerLib",
+        "CtsLegacyImeClientTestLib",
+        "testng",
+        "kotlin-test",
+    ],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+        "src/**/I*.aidl",
+    ],
+    aidl: {
+        local_include_dirs: ["src"],
+    },
+    sdk_version: "test_current",
+}
diff --git a/tests/inputmethod/util/AndroidManifest.xml b/tests/inputmethod/util/AndroidManifest.xml
new file mode 100644
index 0000000..fecb46b
--- /dev/null
+++ b/tests/inputmethod/util/AndroidManifest.xml
@@ -0,0 +1,71 @@
+<?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.view.inputmethod.cts.util"
+     android:targetSandboxVersion="2">
+
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+    <application
+         android:multiArch="true"
+         android:supportsRtl="true">
+
+        <activity android:name="android.view.inputmethod.cts.util.TestActivity"
+            android:theme="@style/no_starting_window"
+            android:label="TestActivity"
+            android:configChanges="fontScale|smallestScreenSize|screenSize|screenLayout|orientation"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
+        <activity android:name="android.view.inputmethod.cts.util.TestActivity2"
+            android:theme="@style/no_starting_window"
+            android:label="TestActivity2"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.inputmethod.cts.util.StateInitializeActivity"
+            android:theme="@style/no_starting_window"
+            android:label="StateInitializeActivity"
+            android:configChanges="fontScale"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
+
+        <!-- In order to test window-focus-stealing from other process, let this service run in a
+             separate process. -->
+        <service android:name="android.view.inputmethod.cts.util.WindowFocusStealerService"
+            android:process=":focusstealer"
+            android:exported="false">
+        </service>
+
+        <service android:name="android.view.inputmethod.cts.util.WindowFocusHandleService"
+            android:exported="false">
+        </service>
+
+    </application>
+
+</manifest>
diff --git a/tests/inputmethod/res/values/styles.xml b/tests/inputmethod/util/res/values/styles.xml
similarity index 100%
rename from tests/inputmethod/res/values/styles.xml
rename to tests/inputmethod/util/res/values/styles.xml
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
similarity index 96%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
index 6992015..2a673ee 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
+++ b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
@@ -168,6 +168,11 @@
         return false;
     }
 
+    @Override
+    public boolean requestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
+        return false;
+    }
+
     @Nullable
     @Override
     public Handler getHandler() {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarInfo.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/StateInitializeActivity.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity2.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity2.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity2.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity2.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestUtils.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestUtils.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestWebView.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestWebView.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealer.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index 072222b..ff5ca6d 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -16,6 +16,7 @@
 
 package android.mediav2.cts;
 
+import android.media.AudioFormat;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaExtractor;
@@ -47,6 +48,7 @@
 import static android.mediav2.cts.CodecTestBase.SupportClass.*;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * Validate decode functionality of listed decoder components
@@ -78,22 +80,17 @@
         mSupportRequirements = supportRequirements;
     }
 
-    static short[] setUpAudioReference(String file) throws IOException {
+    static ByteBuffer readAudioReferenceFile(String file) throws IOException {
         File refFile = new File(file);
-        short[] refData;
+        ByteBuffer refBuffer;
         try (FileInputStream refStream = new FileInputStream(refFile)) {
             FileChannel fileChannel = refStream.getChannel();
             int length = (int) refFile.length();
-            ByteBuffer refBuffer = ByteBuffer.allocate(length);
+            refBuffer = ByteBuffer.allocate(length);
             refBuffer.order(ByteOrder.LITTLE_ENDIAN);
             fileChannel.read(refBuffer);
-            refData = new short[length / 2];
-            refBuffer.position(0);
-            for (int i = 0; i < length / 2; i++) {
-                refData[i] = refBuffer.getShort();
-            }
         }
-        return refData;
+        return refBuffer;
     }
 
     private ArrayList<MediaCodec.BufferInfo> createSubFrames(ByteBuffer buffer, int sfCount) {
@@ -137,13 +134,13 @@
         // SupportClass
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3",
-                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.022f, -1L,
+                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.026749f, -1L,
                         CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3",
-                        "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.60f, -1L,
+                        "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.603081f, -1L,
                         CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_16kbps_amrwb.3gp",
-                        "bbb_1ch_16kHz_s16le.raw", "bbb_1ch_16kHz_23kbps_amrwb.3gp", 2393.598f,
+                        "bbb_1ch_16kHz_s16le.raw", "bbb_1ch_16kHz_23kbps_amrwb.3gp", 2393.5979f,
                         -1L, CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_10kbps_amrnb.3gp",
                         "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_8kbps_amrnb.3gp", -1.0f, -1L,
@@ -157,13 +154,13 @@
                 {MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_2ch_44kHz.wav", "bbb_2ch_44kHz_s16le.raw",
                         "bbb_1ch_16kHz.wav", 0.0f, -1L, CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav",
-                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.08678f, -1L,
+                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.087402f, -1L,
                         CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav",
-                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.4131f, -1L,
+                        "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.413954f, -1L,
                         CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav",
-                        "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.02698f, -1L,
+                        "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.026978f, -1L,
                         CODEC_ALL},
                 {MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_1ch_16kHz_vorbis.mka",
                         "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_vorbis.mka", -1.0f, -1L,
@@ -195,11 +192,47 @@
     private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mime,
             String testFile, String refFile, float rmsError, long checksum);
 
-    static void verify(OutputManager outBuff, String refFile, float rmsError, long refCRC)
-            throws IOException {
+    static void verify(OutputManager outBuff, String refFile, float rmsError, int audioFormat,
+            long refCRC) throws IOException {
         if (rmsError >= 0) {
-            short[] refData = setUpAudioReference(mInpPrefix + refFile);
-            float currError = outBuff.getRmsError(refData);
+            int bytesPerSample = AudioFormat.getBytesPerSample(audioFormat);
+            ByteBuffer bb = readAudioReferenceFile(mInpPrefix + refFile);
+            bb.position(0);
+            int bufferSize = bb.limit();
+            assertEquals (0, bufferSize % bytesPerSample);
+            Object refObject = null;
+            int refObjectLen = bufferSize / bytesPerSample;
+            switch (audioFormat) {
+                case AudioFormat.ENCODING_PCM_8BIT:
+                    refObject = new byte[refObjectLen];
+                    bb.get((byte[]) refObject);
+                    break;
+                case AudioFormat.ENCODING_PCM_16BIT:
+                    refObject = new short[refObjectLen];
+                    bb.asShortBuffer().get((short[]) refObject);
+                    break;
+                case AudioFormat.ENCODING_PCM_24BIT_PACKED:
+                    refObject = new int[refObjectLen];
+                    int[] refArray = (int[]) refObject;
+                    for (int i = 0, j = 0; i < bufferSize; i += 3, j++) {
+                        int byte1 = (bb.get() & 0xff);
+                        int byte2 = (bb.get() & 0xff);
+                        int byte3 = (bb.get() & 0xff);
+                        refArray[j] =  byte1 | (byte2 << 8) | (byte3 << 16);
+                    }
+                    break;
+                case AudioFormat.ENCODING_PCM_32BIT:
+                    refObject = new int[refObjectLen];
+                    bb.asIntBuffer().get((int[]) refObject);
+                    break;
+                case AudioFormat.ENCODING_PCM_FLOAT:
+                    refObject = new float[refObjectLen];
+                    bb.asFloatBuffer().get((float[]) refObject);
+                    break;
+                default:
+                    fail("unrecognized audio encoding type " + audioFormat);
+            }
+            float currError = outBuff.getRmsError(refObject, audioFormat);
             float errMargin = rmsError * RMS_ERROR_TOLERANCE;
             assertTrue(String.format("%s rms error too high ref/exp/got %f/%f/%f", refFile,
                     rmsError, errMargin, currError), currError <= errMargin);
@@ -295,7 +328,11 @@
                 }
             }
             mCodec.release();
-            if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
+            if (mSaveToMem) {
+                int audioEncoding = mIsAudio ? format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+                        AudioFormat.ENCODING_PCM_16BIT) : AudioFormat.ENCODING_INVALID;
+                verify(mOutputBuff, mRefFile, mRmsError, audioEncoding, mRefCRC);
+            }
             assertTrue(nativeTestSimpleDecode(mCodecName, null, mMime, mInpPrefix + mTestFile,
                     mInpPrefix + mRefFile, mRmsError, ref.getCheckSumBuffer()));
         }
@@ -512,7 +549,6 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
                 /* TODO(b/147348711) */
                 if (false) mCodec.stop();
                 else mCodec.reset();
@@ -538,7 +574,6 @@
                 doWork(Integer.MAX_VALUE);
                 queueEOS();
                 waitForAllOutputs();
-                if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
                 /* TODO(b/147348711) */
                 if (false) mCodec.stop();
                 else mCodec.reset();
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 4dd9923..1938b8f 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -16,6 +16,8 @@
 
 package android.mediav2.cts;
 
+import android.media.AudioFormat;
+import android.media.MediaCodec;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 
@@ -32,6 +34,7 @@
 import java.util.List;
 
 import static android.mediav2.cts.CodecTestBase.SupportClass.*;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -44,21 +47,43 @@
  */
 @RunWith(Parameterized.class)
 public class CodecDecoderValidationTest extends CodecDecoderTestBase {
-    private static final String LOG_TAG = CodecDecoderValidationTest.class.getSimpleName();
-
+    private static final String MEDIA_TYPE_RAW = MediaFormat.MIMETYPE_AUDIO_RAW;
+    private static final String MEDIA_TYPE_AMRNB = MediaFormat.MIMETYPE_AUDIO_AMR_NB;
+    private static final String MEDIA_TYPE_AMRWB = MediaFormat.MIMETYPE_AUDIO_AMR_WB;
+    private static final String MEDIA_TYPE_MP3 = MediaFormat.MIMETYPE_AUDIO_MPEG;
+    private static final String MEDIA_TYPE_AAC = MediaFormat.MIMETYPE_AUDIO_AAC;
+    private static final String MEDIA_TYPE_FLAC = MediaFormat.MIMETYPE_AUDIO_FLAC;
+    private static final String MEDIA_TYPE_VORBIS = MediaFormat.MIMETYPE_AUDIO_VORBIS;
+    private static final String MEDIA_TYPE_OPUS = MediaFormat.MIMETYPE_AUDIO_OPUS;
+    private static final String MEDIA_TYPE_MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
+    private static final String MEDIA_TYPE_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
+    private static final String MEDIA_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+    private static final String MEDIA_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
+    private static final String MEDIA_TYPE_HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
+    private static final String MEDIA_TYPE_VP9 = MediaFormat.MIMETYPE_VIDEO_VP9;
+    private static final String MEDIA_TYPE_AV1 = MediaFormat.MIMETYPE_VIDEO_AV1;
     private final String[] mSrcFiles;
     private final String mRefFile;
     private final float mRmsError;
     private final long mRefCRC;
+    private final int mSampleRate;
+    private final int mChannelCount;
+    private final int mWidth;
+    private final int mHeight;
     private final SupportClass mSupportRequirements;
 
     public CodecDecoderValidationTest(String decoder, String mime, String[] srcFiles,
-            String refFile, float rmsError, long refCRC, SupportClass supportRequirements) {
+            String refFile, float rmsError, long refCRC, int sampleRate, int channelCount,
+            int width, int height, SupportClass supportRequirements) {
         super(decoder, mime, null);
         mSrcFiles = srcFiles;
         mRefFile = refFile;
         mRmsError = rmsError;
         mRefCRC = refCRC;
+        mSampleRate = sampleRate;
+        mChannelCount = channelCount;
+        mWidth = width;
+        mHeight = height;
         mSupportRequirements = supportRequirements;
     }
 
@@ -68,394 +93,485 @@
         final boolean needAudio = true;
         final boolean needVideo = true;
         // mediaType, array list of test files (underlying elementary stream is same, except they
-        // are placed in different containers), ref file, rms error, checksum, SupportClass
+        // are placed in different containers), ref file, rms error, checksum, sample rate,
+        // channel count, width, height, SupportClass
         final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
                 // vp9 test vectors with no-show frames signalled in alternate ways
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
-                        "bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm",
-                        "bbb_340x280_768kbps_30fps_vp9.webm"}, null, -1.0f, 4122701060L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
-                        "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm",
-                        "bbb_520x390_1mbps_30fps_vp9.webm"}, null, -1.0f, 1201859039L, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_340x280_768kbps_30fps_vp9.webm",
+                        "bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm"},
+                        null, -1.0f, 4122701060L, -1, -1, 340, 280, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_520x390_1mbps_30fps_vp9.webm",
+                        "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm"},
+                        null, -1.0f, 1201859039L, -1, -1, 520, 390, CODEC_ALL},
 
                 // mpeg2 test vectors with interlaced fields signalled in alternate ways
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
-                        "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
-                        "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4"}, null, -1.0f,
-                        -1L, CODEC_ALL},
-
-                // clips with crop parameters
-//                /* TODO(b/163299340) */
-//                {MediaFormat.MIMETYPE_VIDEO_HEVC, new String[]{"bbb_560x280_1mbps_30fps_hevc.mkv"},
-//                        null, -1.0f, 26298353L, CODEC_ALL},
-//                /* TODO(b/163299340) */
-//                {MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{"bbb_504x224_768kbps_30fps_avc.mp4"},
-//                        null, -1.0f, 4060874918L, CODEC_ALL},
+                {MEDIA_TYPE_MPEG2, new String[]{"bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
+                        "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4"},
+                        null, -1.0f, -1L, -1, -1, 512, 288, CODEC_ALL},
 
                 // misc mp3 test vectors
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_1ch_16kHz_lame_vbr.mp3"},
-                        "bbb_1ch_16kHz_s16le.raw", 119.256f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_2ch_44kHz_lame_vbr.mp3"},
-                        "bbb_2ch_44kHz_s16le.raw", 53.066f, -1L, CODEC_ALL},
+                {MEDIA_TYPE_MP3, new String[]{"bbb_1ch_16kHz_lame_vbr.mp3"},
+                        "bbb_1ch_16kHz_s16le.raw", 119.256073f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_vbr.mp3"},
+                        "bbb_2ch_44kHz_s16le.raw", 53.069080f, -1L, 44100, 2, -1, -1, CODEC_ALL},
 
                 // mp3 test vectors with CRC
-                {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
-                        "bbb_2ch_44kHz_s16le.raw", 104.09f, -1L, CODEC_ALL},
+                {MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
+                        "bbb_2ch_44kHz_s16le.raw", 104.089027f, -1L, 44100, 2, -1, -1, CODEC_ALL},
 
                 // vp9 test vectors with AQ mode enabled
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9" +
-                        ".webm"}, null, -1.0f, 1319105122L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9" +
-                        ".webm"}, null, -1.0f, 4128150660L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9" +
-                        ".webm"}, null, -1.0f, 156928091L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9" +
-                        ".webm"}, null, -1.0f, 3902485256L, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
+                        null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
+                        null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
+                        null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ALL},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
+                        null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ALL},
 
                 // video test vectors of non standard sizes
-                {MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
-                        "bbb_642x642_2mbps_30fps_mpeg2.mp4"}, null, -1.0f, -1L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{
-                        "bbb_642x642_1mbps_30fps_avc.mp4"}, null, -1.0f, 3947092788L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_VP8, new String[]{
-                        "bbb_642x642_1mbps_30fps_vp8.webm"}, null, -1.0f, 516982978L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_HEVC, new String[]{
-                        "bbb_642x642_768kbps_30fps_hevc.mp4"}, null, -1.0f, 3018465268L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
-                        "bbb_642x642_768kbps_30fps_vp9.webm"}, null, -1.0f, 4032809269L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_AV1, new String[]{
-                        "bbb_642x642_768kbps_30fps_av1.mp4"}, null, -1.0f, 3684481474L, CODEC_ANY},
-                {MediaFormat.MIMETYPE_VIDEO_MPEG4, new String[]{
-                        "bbb_130x130_192kbps_15fps_mpeg4.mp4"}, null, -1.0f, -1L, CODEC_ANY},
+                {MEDIA_TYPE_MPEG2, new String[]{"bbb_642x642_2mbps_30fps_mpeg2.mp4"},
+                        null, -1.0f, -1L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_AVC, new String[]{"bbb_642x642_1mbps_30fps_avc.mp4"},
+                        null, -1.0f, 3947092788L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_VP8, new String[]{"bbb_642x642_1mbps_30fps_vp8.webm"},
+                        null, -1.0f, 516982978L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_HEVC, new String[]{"bbb_642x642_768kbps_30fps_hevc.mp4"},
+                        null, -1.0f, 3018465268L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_VP9, new String[]{"bbb_642x642_768kbps_30fps_vp9.webm"},
+                        null, -1.0f, 4032809269L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_AV1, new String[]{"bbb_642x642_768kbps_30fps_av1.mp4"},
+                        null, -1.0f, 3684481474L, -1, -1, 642, 642, CODEC_ANY},
+                {MEDIA_TYPE_MPEG4, new String[]{"bbb_130x130_192kbps_15fps_mpeg4.mp4"},
+                        null, -1.0f, -1L, -1, -1, 130, 130, CODEC_ANY},
 
-                //  audio test vectors covering cdd sec 5.1.3
-                // amr nb
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
-                        "audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
+                // audio test vectors covering cdd sec 5.1.3
+                // amrnb
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
 
-                // amr wb
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
-                        "audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-
-                // flac
-                // TODO(add content for 96kHz and 192kHz)
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_8kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_12kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_12kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_16kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_22kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_24kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_32kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_44kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_48kHz_lvl4_flac.mka"},
-                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_8kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_12kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_12kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_16kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_22kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_24kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_32kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_44kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_48kHz_lvl4_flac.mka"},
-                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
+                // amrwb
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
 
                 // opus
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_1ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_2ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_5ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
-                        "audio/bbb_6ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_8kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_12kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_16kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_24kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_32kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_48kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_8kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_12kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_16kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_24kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_32kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_48kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_8kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_12kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_16kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_24kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_32kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_48kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_8kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_12kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_16kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_24kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_32kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_48kHz_opus.ogg"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+
+                // vorbis
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_8kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_12kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 12000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_16kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_24kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_32kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_48kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_8kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_12kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 12000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_16kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_24kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_32kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_48kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/highres_1ch_96kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 96000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_VORBIS, new String[]{"audio/highres_2ch_96kHz_q10_vorbis.ogg"},
+                        null, -1.0f, -1L, 96000, 2, -1, -1, CODEC_ALL},
+
+                // flac
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_8kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_12kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_12kHz_s16le_3s.raw", 0.0f, -1L, 12000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_16kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_22kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_24kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_32kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_44kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_48kHz_lvl4_flac.mka"},
+                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_8kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_12kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_12kHz_s16le_3s.raw", 0.0f, -1L, 12000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_16kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_22kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_24kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_32kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_44kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_48kHz_lvl4_flac.mka"},
+                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_96kHz_lvl4_flac.mka"},
+                        "audio/highres_1ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_176kHz_lvl4_flac.mka"},
+                        "audio/highres_1ch_176kHz_s16le_5s.raw", 0.0f, -1L, 176400, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_192kHz_lvl4_flac.mka"},
+                        "audio/highres_1ch_192kHz_s16le_5s.raw", 0.0f, -1L, 192000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_96kHz_lvl4_flac.mka"},
+                        "audio/highres_2ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_176kHz_lvl4_flac.mka"},
+                        "audio/highres_2ch_176kHz_s16le_5s.raw", 0.0f, -1L, 176400, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_192kHz_lvl4_flac.mka"},
+                        "audio/highres_2ch_192kHz_s16le_5s.raw", 0.0f, -1L, 192000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_FLAC, new String[]{"audio/sd_2ch_48kHz_lvl4_flac.mka"},
+                        "audio/sd_2ch_48kHz_f32le.raw", 3.446394f, -1L, 48000, 2, -1, -1,
+                        CODEC_ALL},
 
                 // raw
-                // TODO: add content for larger sampling rates and float pcm
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_8kHz.wav"},
-                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_16kHz.wav"},
-                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_22kHz.wav"},
-                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_24kHz.wav"},
-                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_32kHz.wav"},
-                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_44kHz.wav"},
-                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_48kHz.wav"},
-                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_8kHz.wav"},
-                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_16kHz.wav"},
-                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_22kHz.wav"},
-                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_24kHz.wav"},
-                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_32kHz.wav"},
-                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_44kHz.wav"},
-                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_48kHz.wav"},
-                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_8kHz.wav"},
+                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_16kHz.wav"},
+                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_22kHz.wav"},
+                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_24kHz.wav"},
+                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_32kHz.wav"},
+                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_44kHz.wav"},
+                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_48kHz.wav"},
+                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_8kHz.wav"},
+                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_16kHz.wav"},
+                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_22kHz.wav"},
+                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_24kHz.wav"},
+                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_32kHz.wav"},
+                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_44kHz.wav"},
+                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_48kHz.wav"},
+                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/highres_1ch_96kHz.wav"},
+                        "audio/highres_1ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_RAW, new String[]{"audio/highres_2ch_96kHz.wav"},
+                        "audio/highres_2ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 2, -1, -1,
+                        CODEC_ALL},
 
                 // aac-lc
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_8kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 26.907248f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_12kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_12kHz_s16le_3s.raw", 23.366642f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 21.354156f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 25.980762f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.362852f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 28.635643f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 29.291637f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_lc.m4a"},
-                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 29.325756f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_8kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 26.362852f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_12kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_12kHz_s16le_3s.raw", 21.931713f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 22.068077f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 25.317978f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 25.651510f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.294687f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 27.313000f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_lc.m4a"},
-                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 27.676704f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_8kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_8kHz_s16le_3s.raw", 43.116123f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_12kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_12kHz_s16le_3s.raw", 35.972210f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_16kHz_s16le_3s.raw", 32.710854f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_22kHz_s16le_3s.raw", 39.281040f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_24kHz_s16le_3s.raw", 40.951191f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_32kHz_s16le_3s.raw", 49.436829f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_44kHz_s16le_3s.raw", 43.886215f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_lc.m4a"},
-                        "audio/bbb_5ch_48kHz_s16le_3s.raw", 44.271889f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_8kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_8kHz_s16le_3s.raw", 39.661064f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_12kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_12kHz_s16le_3s.raw", 34.971416f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_16kHz_s16le_3s.raw", 29.068884f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_22kHz_s16le_3s.raw", 29.427877f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_24kHz_s16le_3s.raw", 30.331501f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_32kHz_s16le_3s.raw", 33.926392f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_44kHz_s16le_3s.raw", 31.733263f, -1L, CODEC_ALL},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_lc.m4a"},
-                        "audio/bbb_6ch_48kHz_s16le_3s.raw", 31.032242f, -1L, CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_8kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_8kHz_s16le_3s.raw", 26.910906f, -1L, 8000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_12kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_12kHz_s16le_3s.raw", 23.380817f, -1L, 12000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_16kHz_s16le_3s.raw", 21.368309f, -1L, 16000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 25.995440f, -1L, 22050, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.373266f, -1L, 24000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 28.642658f, -1L, 32000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 29.294861f, -1L, 44100, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_lc.m4a"},
+                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 29.335669f, -1L, 48000, 1, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_8kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_8kHz_s16le_3s.raw", 26.381552f, -1L, 8000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_12kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_12kHz_s16le_3s.raw", 21.934900f, -1L, 12000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_16kHz_s16le_3s.raw", 22.072184f, -1L, 16000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 25.334206f, -1L, 22050, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 25.653538f, -1L, 24000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.312286f, -1L, 32000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 27.316111f, -1L, 44100, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_lc.m4a"},
+                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 27.684767f, -1L, 48000, 2, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_8kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_8kHz_s16le_3s.raw", 43.121964f, -1L, 8000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_12kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_12kHz_s16le_3s.raw", 35.983891f, -1L, 12000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_16kHz_s16le_3s.raw", 32.720196f, -1L, 16000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_22kHz_s16le_3s.raw", 39.286514f, -1L, 22050, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_24kHz_s16le_3s.raw", 40.963005f, -1L, 24000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_32kHz_s16le_3s.raw", 49.437782f, -1L, 32000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_44kHz_s16le_3s.raw", 43.891609f, -1L, 44100, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_lc.m4a"},
+                        "audio/bbb_5ch_48kHz_s16le_3s.raw", 44.275997f, -1L, 48000, 5, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_8kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_8kHz_s16le_3s.raw", 39.666485f, -1L, 8000, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_12kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_12kHz_s16le_3s.raw", 34.979305f, -1L, 12000, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_16kHz_s16le_3s.raw", 29.069729f, -1L, 16000, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_22kHz_s16le_3s.raw", 29.440094f, -1L, 22050, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_24kHz_s16le_3s.raw", 30.333755f, -1L, 24000, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_32kHz_s16le_3s.raw", 33.927166f, -1L, 32000, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_44kHz_s16le_3s.raw", 31.733339f, -1L, 44100, 6, -1, -1,
+                        CODEC_ALL},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_lc.m4a"},
+                        "audio/bbb_6ch_48kHz_s16le_3s.raw", 31.033596f, -1L, 48000, 6, -1, -1,
+                        CODEC_ALL},
 
                 // aac-he
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_5ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_6ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-
-                // aac-eld
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_16kHz_s16le_3s.raw", -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 24.959969f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.495283f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 31.464266f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 33.852623f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_eld.m4a"},
-                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 33.136082f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_16kHz_s16le_3s.raw", -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 24.959969f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 26.962938f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.784887f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 29.223278f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_eld.m4a"},
-                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 29.171904f, -1L, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 16000, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 22050, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 24000, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 32000, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 44100, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 16000, 6, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 22050, 6, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 24000, 6, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 32000, 6, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 44100, 6, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_he.m4a"},
+                        null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_DEFAULT},
 
                 // aac-hev2
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_16kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_22kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_24kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_32kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_44kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
-                        "audio/bbb_2ch_48kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_hev2.m4a"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
+
+                // aac-eld
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_16kHz_s16le_3s.raw", -1.000000f, -1L, 16000, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_22kHz_s16le_3s.raw", 24.969662f, -1L, 22050, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.498655f, -1L, 24000, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_32kHz_s16le_3s.raw", 31.468872f, -1L, 32000, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_44kHz_s16le_3s.raw", 33.866409f, -1L, 44100, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_eld.m4a"},
+                        "audio/bbb_1ch_48kHz_s16le_3s.raw", 33.148113f, -1L, 48000, 1, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_16kHz_s16le_3s.raw", -1.000000f, -1L, 16000, 2, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_22kHz_s16le_3s.raw", 24.979313f, -1L, 22050, 2, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_24kHz_s16le_3s.raw", 26.977774f, -1L, 24000, 2, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.790754f, -1L, 32000, 2, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_44kHz_s16le_3s.raw", 29.236626f, -1L, 44100, 2, -1, -1,
+                        CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_eld.m4a"},
+                        "audio/bbb_2ch_48kHz_s16le_3s.raw", 29.183796f, -1L, 48000, 2, -1, -1,
+                        CODEC_DEFAULT},
 
                 // aac-usac
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_8kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_8kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
-                {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_usac.m4a"},
-                        null, -1.0f, -1L, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_8kHz_usac.m4a"},
+                        null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_usac.m4a"},
+                        null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_usac.m4a"},
+                        null, -1.0f, -1L, 22050, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_usac.m4a"},
+                        null, -1.0f, -1L, 24000, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_usac.m4a"},
+                        null, -1.0f, -1L, 32000, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_usac.m4a"},
+                        null, -1.0f, -1L, 44100, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_usac.m4a"},
+                        null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_8kHz_usac.m4a"},
+                        null, -1.0f, -1L, 8000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_usac.m4a"},
+                        null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_usac.m4a"},
+                        null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_usac.m4a"},
+                        null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_usac.m4a"},
+                        null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_usac.m4a"},
+                        null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+                {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_usac.m4a"},
+                        null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
         });
         return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
     }
@@ -472,11 +588,32 @@
             mExtractor.release();
         }
         checkFormatSupport(mCodecName, mMime, formats, null, mSupportRequirements);
-        final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
         {
             OutputManager ref = null;
+            mSaveToMem = true;
+            int audioEncoding = AudioFormat.ENCODING_INVALID;
             for (String file : mSrcFiles) {
-                decodeToMemory(file, mCodecName, 0, mode, Integer.MAX_VALUE);
+                mOutputBuff = new OutputManager();
+                mCodec = MediaCodec.createByCodecName(mCodecName);
+                MediaFormat format = setUpSource(file);
+                if (mIsAudio) {
+                    audioEncoding = format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+                            AudioFormat.ENCODING_PCM_16BIT);
+                }
+                configureCodec(format, false, true, false);
+                mCodec.start();
+                mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+                doWork(Integer.MAX_VALUE);
+                queueEOS();
+                waitForAllOutputs();
+                mOutFormat = mCodec.getOutputFormat();
+                if (mIsAudio) {
+                    assertEquals(mOutFormat.getInteger(MediaFormat.KEY_PCM_ENCODING,
+                            AudioFormat.ENCODING_PCM_16BIT), audioEncoding);
+                }
+                mCodec.stop();
+                mCodec.release();
+                mExtractor.release();
                 String log = String.format("codec: %s, test file: %s:: ", mCodecName, file);
                 assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
                 assertTrue(log + "no input sent", 0 != mInputCount);
@@ -493,10 +630,16 @@
                     assertTrue(log + "decoder outputs are not identical",
                             ref.equalsInterlaced(mOutputBuff));
                 } else {
-                    assertTrue(log + "decoder outputs are not identical", ref.equals(mOutputBuff));
+                    assertEquals(log + "decoder outputs are not identical", ref, mOutputBuff);
                 }
+                assertEquals("sample rate mismatch", mSampleRate,
+                        mOutFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE, -1));
+                assertEquals("channel count mismatch", mChannelCount,
+                        mOutFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT, -1));
+                assertEquals("width mismatch", mWidth, getWidth(mOutFormat));
+                assertEquals("height mismatch", mHeight, getHeight(mOutFormat));
             }
-            CodecDecoderTest.verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
+            CodecDecoderTest.verify(ref, mRefFile, mRmsError, audioEncoding, mRefCRC);
         }
     }
 }
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index dacaf5b..d07a1df 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -21,6 +21,7 @@
 import android.graphics.ImageFormat;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
+import android.media.AudioFormat;
 import android.media.Image;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
@@ -437,18 +438,70 @@
         outPtsList.clear();
     }
 
-    float getRmsError(short[] refData) {
-        long totalErrorSquared = 0;
-        assertTrue(0 == (memIndex & 1));
-        short[] shortData = new short[memIndex / 2];
-        ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()
-                .get(shortData);
-        if (refData.length != shortData.length) return Float.MAX_VALUE;
-        for (int i = 0; i < shortData.length; i++) {
-            int d = shortData[i] - refData[i];
-            totalErrorSquared += d * d;
+    float getRmsError(Object refObject, int audioFormat) {
+        double totalErrorSquared = 0;
+        double avgErrorSquared;
+        int bytesPerSample = AudioFormat.getBytesPerSample(audioFormat);
+        if (refObject instanceof float[]) {
+            if (audioFormat != AudioFormat.ENCODING_PCM_FLOAT) return Float.MAX_VALUE;
+            float[] refData = (float[]) refObject;
+            if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+            float[] floatData = new float[refData.length];
+            ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer()
+                    .get(floatData);
+            for (int i = 0; i < refData.length; i++) {
+                float d = floatData[i] - refData[i];
+                totalErrorSquared += d * d;
+            }
+            avgErrorSquared = (totalErrorSquared / refData.length);
+        } else if (refObject instanceof int[]) {
+            int[] refData = (int[]) refObject;
+            int[] intData;
+            if (audioFormat == AudioFormat.ENCODING_PCM_24BIT_PACKED) {
+                if (refData.length != (memIndex / bytesPerSample)) return Float.MAX_VALUE;
+                intData = new int[refData.length];
+                for (int i = 0, j = 0; i < memIndex; i += 3, j++) {
+                    intData[j] =  memory[j] | (memory[j + 1] << 8) | (memory[j + 2] << 16);
+                }
+            } else if (audioFormat == AudioFormat.ENCODING_PCM_32BIT) {
+                if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+                intData = new int[refData.length];
+                ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
+                        .get(intData);
+            } else {
+                return Float.MAX_VALUE;
+            }
+            for (int i = 0; i < intData.length; i++) {
+                float d = intData[i] - refData[i];
+                totalErrorSquared += d * d;
+            }
+            avgErrorSquared = (totalErrorSquared / refData.length);
+        } else if (refObject instanceof short[]) {
+            short[] refData = (short[]) refObject;
+            if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+            if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) return Float.MAX_VALUE;
+            short[] shortData = new short[refData.length];
+            ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()
+                    .get(shortData);
+            for (int i = 0; i < shortData.length; i++) {
+                float d = shortData[i] - refData[i];
+                totalErrorSquared += d * d;
+            }
+            avgErrorSquared = (totalErrorSquared / refData.length);
+        } else if (refObject instanceof byte[]) {
+            byte[] refData = (byte[]) refObject;
+            if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+            if (audioFormat != AudioFormat.ENCODING_PCM_8BIT) return Float.MAX_VALUE;
+            byte[] byteData = new byte[refData.length];
+            ByteBuffer.wrap(memory, 0, memIndex).get(byteData);
+            for (int i = 0; i < byteData.length; i++) {
+                float d = byteData[i] - refData[i];
+                totalErrorSquared += d * d;
+            }
+            avgErrorSquared = (totalErrorSquared / refData.length);
+        } else {
+            return Float.MAX_VALUE;
         }
-        long avgErrorSquared = (totalErrorSquared / shortData.length);
         return (float) Math.sqrt(avgErrorSquared);
     }
 
@@ -1201,7 +1254,17 @@
             MediaFormat format = mExtractor.getTrackFormat(trackID);
             if (mMime.equalsIgnoreCase(format.getString(MediaFormat.KEY_MIME))) {
                 mExtractor.selectTrack(trackID);
-                if (!mIsAudio) {
+                if (mIsAudio) {
+                    // as per cdd, pcm/wave must support PCM_{8, 16, 24, 32, float} and flac must
+                    // support PCM_{16, float}. For raw media type let extractor manage the
+                    // encoding type directly. For flac, basing on bits-per-sample select the type
+                    if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+                        if (format.getInteger("bits-per-sample", 16) > 16) {
+                            format.setInteger(MediaFormat.KEY_PCM_ENCODING,
+                                    AudioFormat.ENCODING_PCM_FLOAT);
+                        }
+                    }
+                } else {
                     if (mSurface == null) {
                         // COLOR_FormatYUV420Flexible must be supported by all components
                         format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
@@ -1444,8 +1507,8 @@
     private static final String LOG_TAG = CodecEncoderTestBase.class.getSimpleName();
 
     // files are in WorkDir.getMediaDirString();
-    private static final String mInputAudioFile = "bbb_2ch_44kHz_s16le.raw";
-    private static final String mInputVideoFile = "bbb_cif_yuv420p_30fps.yuv";
+    private static final String INPUT_AUDIO_FILE = "bbb_2ch_44kHz_s16le.raw";
+    private static final String INPUT_VIDEO_FILE = "bbb_cif_yuv420p_30fps.yuv";
     private final int INP_FRM_WIDTH = 352;
     private final int INP_FRM_HEIGHT = 288;
 
@@ -1487,7 +1550,7 @@
         mSampleRate = 8000;
         mAsyncHandle = new CodecAsyncHandler();
         mIsAudio = mMime.startsWith("audio/");
-        mInputFile = mIsAudio ? mInputAudioFile : mInputVideoFile;
+        mInputFile = mIsAudio ? INPUT_AUDIO_FILE : INPUT_VIDEO_FILE;
     }
 
     /**
diff --git a/tests/ondevicepersonalization/Android.bp b/tests/ondevicepersonalization/Android.bp
index f676d04..738effe 100644
--- a/tests/ondevicepersonalization/Android.bp
+++ b/tests/ondevicepersonalization/Android.bp
@@ -26,6 +26,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts-ondevicepersonalization",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java b/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java
new file mode 100644
index 0000000..a5d4101
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.smartspace.cts;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem;
+import android.app.smartspace.uitemplatedata.Text;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link CarouselItem}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarouselItemTest {
+
+    private static final String TAG = "CarouselItemTest";
+
+    @Test
+    public void testCreateCarouselItem() {
+        CarouselItem item = new CarouselItem.Builder()
+                .setUpperText(new Text.Builder("upper").build())
+                .setImage(SmartspaceTestUtils.createSmartspaceIcon("icon"))
+                .setLowerText(new Text.Builder("lower").build())
+                .setTapAction(
+                        SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "item tap"))
+                .build();
+
+        assertThat(item.getUpperText()).isEqualTo(new Text.Builder("upper").build());
+        assertThat(item.getImage()).isEqualTo(SmartspaceTestUtils.createSmartspaceIcon("icon"));
+        assertThat(item.getLowerText()).isEqualTo(new Text.Builder("lower").build());
+        assertThat(item.getTapAction()).isEqualTo(
+                SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "item tap"));
+
+        Parcel parcel = Parcel.obtain();
+        parcel.setDataPosition(0);
+        item.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        CarouselItem copyItem = CarouselItem.CREATOR.createFromParcel(parcel);
+        assertThat(item).isEqualTo(copyItem);
+        parcel.recycle();
+    }
+}
diff --git a/tests/smartspace/src/android/smartspace/cts/IconTest.java b/tests/smartspace/src/android/smartspace/cts/IconTest.java
index 484af9f..ce9639b 100644
--- a/tests/smartspace/src/android/smartspace/cts/IconTest.java
+++ b/tests/smartspace/src/android/smartspace/cts/IconTest.java
@@ -41,10 +41,11 @@
         android.graphics.drawable.Icon icon = android.graphics.drawable.Icon.createWithBitmap(
                 Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8));
         Icon smartspaceIcon = new Icon.Builder(icon).setContentDescription(
-                "test content").build();
+                "test content").setShouldTint(false).build();
 
         assertThat(smartspaceIcon.getIcon()).isEqualTo(icon);
         assertThat(smartspaceIcon.getContentDescription()).isEqualTo("test content");
+        assertThat(smartspaceIcon.shouldTint()).isFalse();
 
         Parcel parcel = Parcel.obtain();
         parcel.setDataPosition(0);
diff --git a/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java b/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java
new file mode 100644
index 0000000..a338abe
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.smartspace.cts;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo;
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo;
+import android.app.smartspace.uitemplatedata.Text;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SubItemInfo}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class SubItemInfoTest {
+
+    private static final String TAG = "SubItemInfoTest";
+
+    @Test
+    public void testCreateCarouselItem() {
+        SubItemInfo itemInfo = new SubItemInfo.Builder()
+                .setText(new Text.Builder("test").build())
+                .setIcon(SmartspaceTestUtils.createSmartspaceIcon("icon"))
+                .setTapAction(
+                        SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "action"))
+                .setLoggingInfo(new SubItemLoggingInfo.Builder(0, 0)
+                        .setPackageName("package name").build())
+                .build();
+
+        assertThat(itemInfo.getText()).isEqualTo(new Text.Builder("test").build());
+        assertThat(itemInfo.getIcon()).isEqualTo(SmartspaceTestUtils.createSmartspaceIcon("icon"));
+        assertThat(itemInfo.getTapAction()).isEqualTo(
+                SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "action"));
+        assertThat(itemInfo.getLoggingInfo()).isEqualTo(new SubItemLoggingInfo.Builder(0, 0)
+                .setPackageName("package name").build());
+
+        Parcel parcel = Parcel.obtain();
+        parcel.setDataPosition(0);
+        itemInfo.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        SubItemInfo copyItemInfo = SubItemInfo.CREATOR.createFromParcel(parcel);
+        assertThat(itemInfo).isEqualTo(copyItemInfo);
+        parcel.recycle();
+    }
+}
diff --git a/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java b/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java
new file mode 100644
index 0000000..e1ddafd
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.smartspace.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SubItemLoggingInfo}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class SubItemLoggingInfoTest {
+
+    private static final String TAG = "SubItemLoggingInfoTest";
+
+    @Test
+    public void testCreateSubItemLoggingInfo() {
+        SubItemLoggingInfo itemLoggingInfo = new SubItemLoggingInfo.Builder(1, 1)
+                .setPackageName("package name").build();
+
+        assertThat(itemLoggingInfo.getInstanceId()).isEqualTo(1);
+        assertThat(itemLoggingInfo.getFeatureType()).isEqualTo(1);
+        assertThat(itemLoggingInfo.getPackageName()).isEqualTo("package name");
+
+        Parcel parcel = Parcel.obtain();
+        parcel.setDataPosition(0);
+        itemLoggingInfo.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        SubItemLoggingInfo copyItemLoggingInfo = SubItemLoggingInfo.CREATOR.createFromParcel(
+                parcel);
+        assertThat(itemLoggingInfo).isEqualTo(copyItemLoggingInfo);
+        parcel.recycle();
+    }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 78868c9..2bc4128 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -104,6 +104,7 @@
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -2373,6 +2374,7 @@
         actualStats = PollingCheck.waitFor(DEFAULT_TIMEOUT_MS,
                 () -> mUsageStatsManager.queryBroadcastResponseStats(packageName, id),
                 result -> compareStats(expectedStats, result));
+        actualStats.sort(Comparator.comparing(BroadcastResponseStats::getPackageName));
         final String errorMsg = String.format("\nEXPECTED(%d)=%s\nACTUAL(%d)=%s\n",
                 1, expectedStats,
                 actualStats.size(), Arrays.toString(actualStats.toArray()));
@@ -2392,6 +2394,7 @@
         actualStats = PollingCheck.waitFor(DEFAULT_TIMEOUT_MS,
                 () -> mUsageStatsManager.queryBroadcastResponseStats(null /* packageName */, id),
                 result -> compareStats(expectedStats, result));
+        actualStats.sort(Comparator.comparing(BroadcastResponseStats::getPackageName));
         final String errorMsg = String.format("\nEXPECTED(%d)=%s\nACTUAL(%d)=%s\n",
                 expectedStats.size(), expectedStats,
                 actualStats.size(), Arrays.toString(actualStats.toArray()));
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index 265da81..149dcc9 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -27,6 +27,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.RemoteCallback;
 import android.service.voice.VoiceInteractionSession;
@@ -36,6 +37,12 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import com.android.compatibility.common.util.PropertyUtil;
+
+import java.util.Objects;
 
 public class MainInteractionSession extends VoiceInteractionSession {
     static final String TAG = "MainInteractionSession";
@@ -125,7 +132,11 @@
                     mContentView.getViewTreeObserver().removeOnPreDrawListener(this);
                     Display d = mContentView.getDisplay();
                     Point displayPoint = new Point();
-                    d.getRealSize(displayPoint);
+                    WindowManager wm = mContext.getSystemService(WindowManager.class);
+                    WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+                    Rect bound = windowMetrics.getBounds();
+                    displayPoint.y = bound.height();
+                    displayPoint.x = bound.width();
                     DisplayCutout dc = d.getCutout();
                     if (dc != null) {
                         // Means the device has a cutout area
@@ -137,9 +148,16 @@
                             displayPoint.x -= (wi.left + wi.right);
                         }
                     }
+                    int WindowInsetTop = windowMetrics.getWindowInsets().getSystemWindowInsetTop();
+                    final String property = PropertyUtil.getProperty("ro.hardware.virtual_device");
+                    boolean isVirtual = Objects.equals(property, "1");
                     Bundle bundle = new Bundle();
-                    bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
-                    bundle.putInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT, mContentView.getHeight());
+                    bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION,
+                            Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
+                    // TODO: find reason why virtual device don't have problem
+                    bundle.putInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT,
+                            isVirtual ? mContentView.getHeight()
+                                    : mContentView.getHeight() + WindowInsetTop);
                     bundle.putInt(Utils.EXTRA_CONTENT_VIEW_WIDTH, mContentView.getWidth());
                     bundle.putParcelable(Utils.EXTRA_DISPLAY_POINT, displayPoint);
                     mRemoteCallback.sendResult(bundle);
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
index 4b0c129..cf363c2 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
@@ -227,6 +227,10 @@
   AIBinder_Weak_delete(w2);
 }
 
+TEST_F(NdkBinderTest_AIBinder, IsHandlingTransactionFalse) {
+  EXPECT_FALSE(AIBinder_isHandlingTransaction());
+}
+
 TEST_F(NdkBinderTest_AIBinder, LocalIsLocal) {
   AIBinder* binder = SampleData::newBinder();
   EXPECT_FALSE(AIBinder_isRemote(binder));
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
index 0b2dd82..6c7b933 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
@@ -16,33 +16,47 @@
 
 package android.bluetooth.cts;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHapClient;
 import android.bluetooth.BluetoothHapPresetInfo;
-import android.bluetooth.BluetoothManager;
 import android.bluetooth.BluetoothProfile;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
+import android.content.Context;
 import android.os.Build;
-import android.test.AndroidTestCase;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
-public class BluetoothHapClientTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothHapClientTest {
     private static final String TAG = BluetoothHapClientTest.class.getSimpleName();
 
     private static final int PROXY_CONNECTION_TIMEOUT_MS = 500;  // ms timeout for Proxy Connect
     private static final String PROFILE_SUPPORTED_HAP_CLIENT = "profile_supported_hap_client";
 
+    private Context mContext;
     private boolean mHasBluetooth;
     private BluetoothAdapter mAdapter;
 
@@ -52,41 +66,37 @@
     private Condition mConditionProfileIsConnected;
     private ReentrantLock mProfileConnectedlock;
 
-    @Override
+    @Before
     public void setUp() throws Exception {
-        super.setUp();
-        if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
-            mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_BLUETOOTH);
-
-            if (!mHasBluetooth) return;
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
-            BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
-            mAdapter = manager.getAdapter();
-            assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
-
-            mProfileConnectedlock = new ReentrantLock();
-            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
-            mIsProfileReady = false;
-            mBluetoothHapClient = null;
-
-            Resources bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
-                    "com.android.bluetooth");
-            int hapClientSupportId = bluetoothResources.getIdentifier(
-                    PROFILE_SUPPORTED_HAP_CLIENT, "bool", "com.android.bluetooth");
-            if (hapClientSupportId == 0) return;
-            mIsHapClientSupported = bluetoothResources.getBoolean(hapClientSupportId);
-            if (!mIsHapClientSupported) return;
-
-            mAdapter.getProfileProxy(getContext(), new BluetoothHapClientServiceListener(),
-                    BluetoothProfile.HAP_CLIENT);
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
         }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+
+        mProfileConnectedlock = new ReentrantLock();
+        mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
+        mIsProfileReady = false;
+        mBluetoothHapClient = null;
+
+        mIsHapClientSupported = TestUtils.getProfileConfigValueOrDie(BluetoothProfile.HAP_CLIENT);
+        if (!mIsHapClientSupported) {
+            return;
+        }
+
+        mAdapter.getProfileProxy(mContext, new BluetoothHapClientServiceListener(),
+                BluetoothProfile.HAP_CLIENT);
     }
 
-    @Override
+    @After
     public void tearDown() throws Exception {
-        super.tearDown();
         if (mHasBluetooth) {
             if (mAdapter != null && mBluetoothHapClient != null) {
                 mBluetoothHapClient.close();
@@ -95,14 +105,15 @@
             }
             assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
             mAdapter = null;
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .dropShellPermissionIdentity();
+            TestUtils.dropPermissionAsShellUid();
         }
     }
 
+    @Test
     public void testGetConnectedDevices() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -113,9 +124,11 @@
         assertTrue(connectedDevices.isEmpty());
     }
 
+    @Test
     public void testGetDevicesMatchingConnectionStates() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -127,9 +140,11 @@
         assertTrue(connectedDevices.isEmpty());
     }
 
+    @Test
     public void testGetConnectionState() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -146,9 +161,11 @@
                 mBluetoothHapClient.getConnectionState(testDevice));
     }
 
+    @Test
     public void testGetActivePresetIndex() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -160,9 +177,11 @@
         assertNull(mBluetoothHapClient.getActivePresetInfo(testDevice));
     }
 
+    @Test
     public void testSelectPreset() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -173,9 +192,11 @@
         mBluetoothHapClient.selectPreset(testDevice, 1);
     }
 
+    @Test
     public void testSelectPresetForGroup() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
 
@@ -184,8 +205,11 @@
         mBluetoothHapClient.selectPresetForGroup(1, 1);
     }
 
+    @Test
     public void testGetAllPresetInfo() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
+        if (shouldSkipTest()) {
+            return;
+        }
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
@@ -199,8 +223,11 @@
         assertTrue(presets.isEmpty());
     }
 
+    @Test
     public void testSetPresetName() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
+        if (shouldSkipTest()) {
+            return;
+        }
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
@@ -212,8 +239,11 @@
         mBluetoothHapClient.setPresetName(testDevice, 1 , "New Name");
     }
 
+    @Test
     public void testSetPresetNameForGroup() {
-        if (!(mHasBluetooth && mIsHapClientSupported)) return;
+        if (shouldSkipTest()) {
+            return;
+        }
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothHapClient);
@@ -223,6 +253,10 @@
         mBluetoothHapClient.setPresetNameForGroup(1, 1 , "New Name");
     }
 
+    private boolean shouldSkipTest() {
+        return !(mHasBluetooth && mIsHapClientSupported);
+    }
+
     private boolean waitForProfileConnect() {
         mProfileConnectedlock.lock();
         try {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
new file mode 100644
index 0000000..afafa39
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothHapPresetInfo;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothHapPresetInfoTest {
+    private static final int TEST_PRESET_INDEX = 15;
+    private static final String TEST_PRESET_NAME = "Test";
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsHapSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsHapSupported = TestUtils.getProfileConfigValueOrDie(BluetoothProfile.HAP_CLIENT);
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateHapPresetInfo() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothHapPresetInfo presetInfo = createBluetoothHapPresetInfoForTest(TEST_PRESET_INDEX,
+                TEST_PRESET_NAME, true /* isAvailable */, false /* isWritable */);
+        assertEquals(TEST_PRESET_INDEX, presetInfo.getIndex());
+        assertEquals(TEST_PRESET_NAME, presetInfo.getName());
+        assertTrue(presetInfo.isAvailable());
+        assertFalse(presetInfo.isWritable());
+    }
+
+    static BluetoothHapPresetInfo createBluetoothHapPresetInfoForTest(int presetIndex,
+            String presetName, boolean isAvailable, boolean isWritable) {
+        Parcel out = Parcel.obtain();
+        out.writeInt(presetIndex);
+        out.writeString(presetName);
+        out.writeBoolean(isAvailable);
+        out.writeBoolean(isWritable);
+        return BluetoothHapPresetInfo.CREATOR.createFromParcel(out);
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || !mIsHapSupported;
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
new file mode 100644
index 0000000..8536e9d
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
@@ -0,0 +1,244 @@
+/*
+ * 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_CONNECT;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BluetoothHeadsetTest extends AndroidTestCase {
+    private static final String TAG = BluetoothHeadsetTest.class.getSimpleName();
+
+    private static final int PROXY_CONNECTION_TIMEOUT_MS = 500;  // ms timeout for Proxy Connect
+    private static final String PROFILE_SUPPORTED_HEADSET = "profile_supported_hs_hfp";
+
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private UiAutomation mUiAutomation;;
+
+    private BluetoothHeadset mBluetoothHeadset;
+    private boolean mIsHeadsetSupported;
+    private boolean mIsProfileReady;
+    private Condition mConditionProfileIsConnected;
+    private ReentrantLock mProfileConnectedlock;
+
+    @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);
+
+        BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
+        mAdapter = manager.getAdapter();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mProfileConnectedlock = new ReentrantLock();
+        mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+        mIsProfileReady = false;
+        mBluetoothHeadset = null;
+
+        Resources bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
+                "com.android.bluetooth");
+        int headsetSupportId = bluetoothResources.getIdentifier(
+                PROFILE_SUPPORTED_HEADSET, "bool", "com.android.bluetooth");
+        assertTrue("resource profile_supported_hs_hfp not found", headsetSupportId != 0);
+        mIsHeadsetSupported = bluetoothResources.getBoolean(headsetSupportId);
+        if (!mIsHeadsetSupported) return;
+
+        mAdapter.getProfileProxy(getContext(), new BluetoothHeadsetServiceListener(),
+                BluetoothProfile.HEADSET);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        if (mHasBluetooth) {
+            if (mAdapter != null && mBluetoothHeadset != null) {
+                mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+                mBluetoothHeadset = null;
+                mIsProfileReady = false;
+            }
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            mUiAutomation.dropShellPermissionIdentity();
+        }
+    }
+
+    public void test_getConnectedDevices() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        assertEquals(mBluetoothHeadset.getConnectedDevices(),
+                new ArrayList<BluetoothDevice>());
+    }
+
+    public void test_getDevicesMatchingConnectionStates() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        assertEquals(mBluetoothHeadset.getDevicesMatchingConnectionStates(
+                new int[]{BluetoothProfile.STATE_CONNECTED}),
+                new ArrayList<BluetoothDevice>());
+    }
+
+    public void test_getConnectionState() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        assertEquals(mBluetoothHeadset.getConnectionState(testDevice),
+                BluetoothProfile.STATE_DISCONNECTED);
+    }
+
+    public void test_isAudioConnected() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        assertFalse(mBluetoothHeadset.isAudioConnected(testDevice));
+        assertFalse(mBluetoothHeadset.isAudioConnected(null));
+
+        // Verify the method returns false when Bluetooth is off and you supply a valid device
+        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+        assertFalse(mBluetoothHeadset.isAudioConnected(testDevice));
+    }
+
+    public void test_isNoiseReductionSupported() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        assertFalse(mBluetoothHeadset.isNoiseReductionSupported(testDevice));
+        assertFalse(mBluetoothHeadset.isNoiseReductionSupported(null));
+
+        // Verify the method returns false when Bluetooth is off and you supply a valid device
+        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+        assertFalse(mBluetoothHeadset.isNoiseReductionSupported(testDevice));
+    }
+
+    public void test_isVoiceRecognitionSupported() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(testDevice));
+        assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(null));
+
+        // Verify the method returns false when Bluetooth is off and you supply a valid device
+        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+        assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(testDevice));
+    }
+
+    public void test_sendVendorSpecificResultCode() {
+        if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothHeadset);
+
+        BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+        try {
+            mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, null, null);
+            fail("sendVendorSpecificResultCode did not throw an IllegalArgumentException when the "
+                    + "command was null");
+        } catch (IllegalArgumentException ignored) {
+        }
+
+        assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, "", ""));
+        assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(null, "", ""));
+
+        // Verify the method returns false when Bluetooth is off and you supply a valid device
+        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+        assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, "", ""));
+    }
+
+    private boolean waitForProfileConnect() {
+        mProfileConnectedlock.lock();
+        try {
+            // Wait for the Adapter to be disabled
+            while (!mIsProfileReady) {
+                if (!mConditionProfileIsConnected.await(
+                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                    // Timeout
+                    Log.e(TAG, "Timeout while waiting for Profile Connect");
+                    break;
+                } // else spurious wakeups
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "waitForProfileConnect: interrrupted");
+        } finally {
+            mProfileConnectedlock.unlock();
+        }
+        return mIsProfileReady;
+    }
+
+    private final class BluetoothHeadsetServiceListener implements
+            BluetoothProfile.ServiceListener {
+
+        @Override
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            mProfileConnectedlock.lock();
+            mBluetoothHeadset = (BluetoothHeadset) proxy;
+            mIsProfileReady = true;
+            try {
+                mConditionProfileIsConnected.signal();
+            } finally {
+                mProfileConnectedlock.unlock();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(int profile) {
+        }
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
new file mode 100644
index 0000000..af30292
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioCodecConfigMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeAudioCodecConfigMetadataTest {
+    private static final long TEST_AUDIO_LOCATION_FRONT_LEFT = 0x01;
+    // See Page 5 of Generic Audio assigned number specification
+    private static final byte[] TEST_METADATA_BYTES = {
+            // length = 0x05, type = 0x03, value = 0x00000001 (front left)
+            0x05, 0x03, 0x00, 0x00, 0x00, 0x01
+    };
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateCodecConfigMetadataFromBuilder() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                new BluetoothLeAudioCodecConfigMetadata.Builder()
+                        .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+        assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
+        // TODO: Implement implicit LTV byte conversion in the API class
+        // assertArrayEquals(TEST_METADATA_BYTES, codecMetadata.getRawMetadata());
+    }
+
+    @Test
+    public void testCreateCodecConfigMetadataFromBytes() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioCodecConfigMetadata codecMetadata =
+                BluetoothLeAudioCodecConfigMetadata.fromRawBytes(TEST_METADATA_BYTES);
+        byte[] metadataBytes = codecMetadata.getRawMetadata();
+        assertNotNull(metadataBytes);
+        assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
+        // TODO: Implement implicit LTV byte conversion in the API class
+        // assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
new file mode 100644
index 0000000..6c32580
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeAudioContentMetadataTest {
+    // "Test" in UTF-8 is "54 65 73 74"
+    private static final String TEST_PROGRAM_INFO = "Test";
+    // German language code in ISO 639-3
+    // In byte it is ASCII, 0x64, 0x65, 0x75
+    private static final String TEST_LANGUAGE = "deu";
+    // See Page 6 of Generic Audio assigned number specification
+    private static final byte[] TEST_METADATA_BYTES = {
+            // length is 0x05, type is 0x03, data is "Test" in UTF-8 "54 65 73 74" hex
+            0x05, 0x03, 0x54, 0x65, 0x73, 0x74,
+            // length is 0x04, type is 0x04, data is "deu" in ASCII "64 65 75" hex
+            0x04, 0x04, 0x64, 0x65, 0x75
+    };
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateCodecConfigMetadataFromBuilder() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioContentMetadata contentMetadata =
+                new BluetoothLeAudioContentMetadata.Builder()
+                        .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
+        assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
+        assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
+        // TODO: Implement implicit LTV byte conversion in the API class
+        // assertArrayEquals(TEST_METADATA_BYTES, contentMetadata.getRawMetadata());
+    }
+
+    @Test
+    public void testCreateCodecConfigMetadataFromBytes() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeAudioContentMetadata contentMetadata =
+                BluetoothLeAudioContentMetadata.fromRawBytes(TEST_METADATA_BYTES);
+        byte[] metadataBytes = contentMetadata.getRawMetadata();
+        assertNotNull(metadataBytes);
+        assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
+        // TODO: Implement implicit LTV byte conversion in the API class
+        // assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
+        // assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
index 1118fd8..667aa52 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
@@ -16,26 +16,29 @@
 
 package android.bluetooth.cts;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastAssistant;
-import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.os.Build;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.ApiLevelUtil;
 
@@ -44,7 +47,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
@@ -56,15 +61,13 @@
 
 
     private static final int PROXY_CONNECTION_TIMEOUT_MS = 500;  // ms timeout for Proxy Connect
-    private static final String PROFILE_SUPPORTED_LE_BROADCAST_ASSISTANT = "profile_supported_bass";
-    private static final int LE_AUDIO_PROFILE_CONSTANT = 22;
 
     private Context mContext;
     private boolean mHasBluetooth;
     private BluetoothAdapter mAdapter;
 
     private BluetoothLeBroadcastAssistant mBluetoothLeBroadcastAssistant;
-    private boolean mIsLeBroadcastAssistantSupported;
+    private boolean mIsBroadcastAssistantSupported;
     private boolean mIsProfileReady;
     private Condition mConditionProfileIsConnected;
     private ReentrantLock mProfileConnectedlock;
@@ -75,16 +78,12 @@
         if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
             return;
         }
-        mHasBluetooth = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_BLUETOOTH);
-
+        mHasBluetooth = TestUtils.hasBluetooth();
         if (!mHasBluetooth) {
             return;
         }
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
-            .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
-        BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
-        mAdapter = manager.getAdapter();
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
         mProfileConnectedlock = new ReentrantLock();
@@ -92,22 +91,14 @@
         mIsProfileReady = false;
         mBluetoothLeBroadcastAssistant = null;
 
-        Resources bluetoothResources = null;
-        try {
-            bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
-                    "com.android.bluetooth");
-        } catch (PackageManager.NameNotFoundException e) {
-            return;
-        }
-        int leBroadcastAssistantSupportId = bluetoothResources.getIdentifier(
-                PROFILE_SUPPORTED_LE_BROADCAST_ASSISTANT, "bool", "com.android.bluetooth");
-        if (leBroadcastAssistantSupportId == 0) {
-            return;
-        }
-        mIsLeBroadcastAssistantSupported = bluetoothResources.getBoolean(
-                leBroadcastAssistantSupportId);
-        if (!mIsLeBroadcastAssistantSupported) {
-            return;
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
         }
 
         mAdapter.getProfileProxy(mContext, new ServiceListener(),
@@ -125,15 +116,186 @@
             }
             assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
             mAdapter = null;
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .dropShellPermissionIdentity();
+            TestUtils.dropPermissionAsShellUid();
         }
     }
 
     @Test
-    public void testGetConnectedDevices() {
-        if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
+    public void test_addSource() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
 
+        // TODO When implemented
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .addSource(null, null, true));
+
+        mBluetoothLeBroadcastAssistant.removeSource(null, 0);
+    }
+
+    @Test
+    public void test_getAllSources() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // TODO When implemented
+
+        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+        // Verify returns empty list if bluetooth is not enabled
+        assertTrue(mBluetoothLeBroadcastAssistant.getAllSources(null).isEmpty());
+    }
+
+    @Test
+    public void test_setConnectionPolicy() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // TODO When implemented
+        assertFalse(mBluetoothLeBroadcastAssistant.setConnectionPolicy(null,
+                    BluetoothProfile.CONNECTION_POLICY_FORBIDDEN));
+        assertEquals(mBluetoothLeBroadcastAssistant.getConnectionPolicy(null),
+                BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+    }
+
+    @Test
+    public void test_getMaximumSourceCapacity() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // TODO When implemented
+        assertEquals(mBluetoothLeBroadcastAssistant.getMaximumSourceCapacity(null), 0);
+    }
+
+    @Test
+    public void test_isSearchInProgress() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // TODO When implemented
+        assertFalse(mBluetoothLeBroadcastAssistant.isSearchInProgress());
+    }
+
+    @Test
+    public void test_modifySource() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // TODO When implemented
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .modifySource(null, 0, null));
+    }
+
+    @Test
+    public void test_registerCallback() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        Executor executor = mContext.getMainExecutor();
+        BluetoothLeBroadcastAssistant.Callback callback =
+                new BluetoothLeBroadcastAssistant.Callback() {
+                    @Override
+                    public void onSearchStarted(int reason) {}
+                    @Override
+                    public void onSearchStartFailed(int reason) {}
+                    @Override
+                    public void onSearchStopped(int reason) {}
+                    @Override
+                    public void onSearchStopFailed(int reason) {}
+                    @Override
+                    public void onSourceFound(BluetoothLeBroadcastMetadata source) {}
+                    @Override
+                    public void onSourceAdded(BluetoothDevice sink, int sourceId, int reason) {}
+                    @Override
+                    public void onSourceAddFailed(BluetoothDevice sink,
+                            BluetoothLeBroadcastMetadata source, int reason) {}
+                    @Override
+                    public void onSourceModified(BluetoothDevice sink, int sourceId, int reason) {}
+                    @Override
+                    public void onSourceModifyFailed(
+                            BluetoothDevice sink, int sourceId, int reason) {}
+                    @Override
+                    public void onSourceRemoved(BluetoothDevice sink, int sourceId, int reason) {}
+                    @Override
+                    public void onSourceRemoveFailed(
+                            BluetoothDevice sink, int sourceId, int reason) {}
+                    @Override
+                    public void onReceiveStateChanged(BluetoothDevice sink, int sourceId,
+                            BluetoothLeBroadcastReceiveState state) {}
+                };
+        // empty calls to callback override
+        callback.onSearchStarted(0);
+        callback.onSearchStartFailed(0);
+        callback.onSearchStopped(0);
+        callback.onSearchStopFailed(0);
+        callback.onSourceFound(null);
+        callback.onSourceAdded(null, 0, 0);
+        callback.onSourceAddFailed(null, null, 0);
+        callback.onSourceModified(null, 0, 0);
+        callback.onSourceModifyFailed(null, 0, 0);
+        callback.onSourceRemoved(null, 0, 0);
+        callback.onSourceRemoveFailed(null, 0, 0);
+        callback.onReceiveStateChanged(null, 0, null);
+
+        // Verify parameter
+        assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+                .registerCallback(null, callback));
+        assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+                .registerCallback(executor, null));
+        assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+                .unregisterCallback(null));
+
+
+        // TODO When implemented
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .registerCallback(executor, callback));
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .unregisterCallback(callback));
+    }
+
+    @Test
+    public void test_startSearchingForSources() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        assertTrue(waitForProfileConnect());
+        assertNotNull(mBluetoothLeBroadcastAssistant);
+
+        // Verify parameter
+        assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+                .startSearchingForSources(null));
+
+        // TODO When implemented
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .startSearchingForSources(new ArrayList<>()));
+        assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+                .stopSearchingForSources());
+    }
+
+    @Test
+    public void testGetConnectedDevices() {
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcastAssistant);
 
@@ -147,8 +309,9 @@
 
     @Test
     public void testGetDevicesMatchingConnectionStates() {
-        if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcastAssistant);
 
@@ -162,7 +325,9 @@
 
     @Test
     public void testGetConnectionState() {
-        if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
+        if (shouldSkipTest()) {
+            return;
+        }
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcastAssistant);
@@ -187,10 +352,14 @@
         }
         if (mAdapter.isLeAudioBroadcastAssistantSupported()
                 == BluetoothStatusCodes.FEATURE_NOT_SUPPORTED) {
-            assertFalse(mIsLeBroadcastAssistantSupported);
+            assertFalse(mIsBroadcastAssistantSupported);
             return;
         }
-        assertTrue(mIsLeBroadcastAssistantSupported);
+        assertTrue(mIsBroadcastAssistantSupported);
+    }
+
+    private boolean shouldSkipTest() {
+        return !(mHasBluetooth && mIsBroadcastAssistantSupported);
     }
 
     private boolean waitForProfileConnect() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
new file mode 100644
index 0000000..7390b82
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeBroadcastChannel;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastChannelTest {
+    private static final int TEST_CHANNEL_INDEX = 42;
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateBroadcastChannelFromBuilder() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeBroadcastChannel channel =
+                new BluetoothLeBroadcastChannel.Builder()
+                        .setSelected(true)
+                        .setChannelIndex(TEST_CHANNEL_INDEX)
+                        .setCodecMetadata(null)
+                        .build();
+        assertTrue(channel.isSelected());
+        assertEquals(TEST_CHANNEL_INDEX, channel.getChannelIndex());
+        assertNull(channel.getCodecMetadata());
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
index c03ad8e..5651320 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
@@ -16,30 +16,116 @@
 
 package android.bluetooth.cts;
 
-import static org.junit.Assert.assertEquals;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class BluetoothLeBroadcastMetadataTest {
+    private static final String TEST_MAC_ADDRESS = "00:11:22:33:44:55";
+    private static final int TEST_BROADCAST_ID = 42;
+    private static final int TEST_ADVERTISER_SID = 1234;
+    private static final int TEST_PA_SYNC_INTERVAL = 100;
+    private static final int TEST_PRESENTATION_DELAY_MS = 345;
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
     @Test
     public void testCreateMetadataFromBuilder() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothDevice testDevice =
+                mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);
         BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder();
         BluetoothLeBroadcastMetadata metadata =
-                builder.setEncrypted(false).setBroadcastCode(null)
-                        .setPaSyncInterval(1)
-                        .setPresentationDelayMicros(2)
-                        .setBroadcastId(3)
+                builder.setEncrypted(false)
+                        .setSourceDevice(testDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM)
+                        .setSourceAdvertisingSid(TEST_ADVERTISER_SID)
+                        .setBroadcastId(TEST_BROADCAST_ID)
+                        .setBroadcastCode(null)
+                        .setPaSyncInterval(TEST_PA_SYNC_INTERVAL)
+                        .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS)
                         .build();
-        assertEquals(1, metadata.getPaSyncInterval());
-        assertEquals(2, metadata.getPresentationDelayMicros());
-        assertEquals(3, metadata.getBroadcastId());
+        assertEquals(testDevice, metadata.getSourceDevice());
+        assertEquals(BluetoothDevice.ADDRESS_TYPE_RANDOM, metadata.getSourceAddressType());
+        assertEquals(TEST_BROADCAST_ID, metadata.getBroadcastId());
+        assertNull(metadata.getBroadcastCode());
+        assertEquals(TEST_PA_SYNC_INTERVAL, metadata.getPaSyncInterval());
+        assertEquals(TEST_PRESENTATION_DELAY_MS, metadata.getPresentationDelayMicros());
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
     }
 }
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
new file mode 100644
index 0000000..cc28740
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastReceiveStateTest {
+    private static final int TEST_SOURCE_ID = 42;
+    private static final int TEST_SOURCE_ADDRESS_TYPE = BluetoothDevice.ADDRESS_TYPE_RANDOM;
+    private static final String TEST_MAC_ADDRESS = "00:11:22:33:44:55";
+    private static final int TEST_ADVERTISER_SID = 1234;
+    private static final int TEST_BROADCAST_ID = 45;
+    private static final int TEST_PA_SYNC_STATE =
+            BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED;
+    private static final int TEST_BIG_ENCRYPTION_STATE =
+            BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED;
+    private static final int TEST_NUM_SUBGROUPS = 1;
+    private static final Long[] TEST_BIS_SYNC_STATE = {1L};
+    private static final BluetoothLeAudioContentMetadata[] TEST_SUBGROUP_METADATA = {null};
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateBroadcastReceiveState() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothDevice testDevice =
+                mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, TEST_SOURCE_ADDRESS_TYPE);
+        BluetoothLeBroadcastReceiveState state = createBroadcastReceiveStateForTest(
+                TEST_SOURCE_ID,
+                TEST_SOURCE_ADDRESS_TYPE,
+                testDevice,
+                TEST_ADVERTISER_SID,
+                TEST_BROADCAST_ID,
+                TEST_PA_SYNC_STATE,
+                TEST_BIG_ENCRYPTION_STATE,
+                null /* badCode */,
+                TEST_NUM_SUBGROUPS,
+                Arrays.asList(TEST_BIS_SYNC_STATE),
+                Arrays.asList(TEST_SUBGROUP_METADATA));
+        assertEquals(TEST_SOURCE_ID, state.getSourceId());
+        assertEquals(TEST_SOURCE_ADDRESS_TYPE, state.getSourceAddressType());
+        assertEquals(testDevice, state.getSourceDevice());
+        assertEquals(TEST_ADVERTISER_SID, state.getSourceAdvertisingSid());
+        assertEquals(TEST_BROADCAST_ID, state.getBroadcastId());
+        assertEquals(TEST_PA_SYNC_STATE, state.getPaSyncState());
+        assertEquals(TEST_BIG_ENCRYPTION_STATE, state.getBigEncryptionState());
+        assertNull(state.getBadCode());
+        assertEquals(TEST_NUM_SUBGROUPS, state.getNumSubgroups());
+        assertArrayEquals(TEST_BIS_SYNC_STATE, state.getBisSyncState().toArray(new Long[0]));
+        assertArrayEquals(TEST_SUBGROUP_METADATA,
+                state.getSubgroupMetadata().toArray(new BluetoothLeAudioContentMetadata[0]));
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+    }
+
+    static BluetoothLeBroadcastReceiveState createBroadcastReceiveStateForTest(
+            int sourceId, int sourceAddressType,
+            BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId,
+            int paSyncState, int bigEncryptionState, byte[] badCode, int numSubgroups,
+            List<Long> bisSyncState,
+            List<BluetoothLeAudioContentMetadata> subgroupMetadata) {
+        Parcel out = Parcel.obtain();
+        out.writeInt(sourceId);
+        out.writeInt(sourceAddressType);
+        out.writeTypedObject(sourceDevice, 0);
+        out.writeInt(sourceAdvertisingSid);
+        out.writeInt(broadcastId);
+        out.writeInt(paSyncState);
+        out.writeInt(bigEncryptionState);
+
+        if (badCode != null) {
+            out.writeInt(badCode.length);
+            out.writeByteArray(badCode);
+        } else {
+            // -1 indicates that there is no "bad broadcast code"
+            out.writeInt(-1);
+        }
+        out.writeInt(numSubgroups);
+        out.writeList(bisSyncState);
+        out.writeTypedList(subgroupMetadata);
+        return BluetoothLeBroadcastReceiveState.CREATOR.createFromParcel(out);
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
new file mode 100644
index 0000000..3ad73c7
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeBroadcastChannel;
+import android.bluetooth.BluetoothLeBroadcastSubgroup;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastSubgroupTest {
+    private static final int TEST_CODEC_ID = 42;
+    private static final BluetoothLeBroadcastChannel[] TEST_CHANNELS = {null};
+
+    private Context mContext;
+    private boolean mHasBluetooth;
+    private BluetoothAdapter mAdapter;
+    private boolean mIsBroadcastSourceSupported;
+    private boolean mIsBroadcastAssistantSupported;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+            return;
+        }
+        mHasBluetooth = TestUtils.hasBluetooth();
+        if (!mHasBluetooth) {
+            return;
+        }
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
+        assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+        mIsBroadcastAssistantSupported =
+                mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+        if (mIsBroadcastAssistantSupported) {
+            boolean isBroadcastAssistantEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastAssistantEnabledInConfig);
+        }
+
+        mIsBroadcastSourceSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (!mIsBroadcastSourceSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(
+                            BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mHasBluetooth) {
+            assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+            mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
+        }
+    }
+
+    @Test
+    public void testCreateBroadcastSubgroupFromBuilder() {
+        if (shouldSkipTest()) {
+            return;
+        }
+        BluetoothLeBroadcastSubgroup.Builder builder = new BluetoothLeBroadcastSubgroup.Builder()
+                .setCodecId(TEST_CODEC_ID)
+                .setCodecSpecificConfig(null)
+                .setContentMetadata(null)
+                .setNoChannelPreference(true);
+        for (BluetoothLeBroadcastChannel channel : TEST_CHANNELS) {
+            builder.addChannel(channel);
+        }
+        BluetoothLeBroadcastSubgroup subgroup = builder.build();
+        assertEquals(TEST_CODEC_ID, subgroup.getCodecId());
+        assertArrayEquals(TEST_CHANNELS,
+                subgroup.getChannels().toArray(new BluetoothLeBroadcastChannel[0]));
+    }
+
+    private boolean shouldSkipTest() {
+        return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+    }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
index 1ad8e3b..d73f721 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth.cts;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -24,12 +27,9 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcast;
-import android.bluetooth.BluetoothManager;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.os.Build;
 import android.util.Log;
 
@@ -73,14 +73,12 @@
         if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
             return;
         }
-        mHasBluetooth = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_BLUETOOTH);
-
+        mHasBluetooth = TestUtils.hasBluetooth();
         if (!mHasBluetooth) {
             return;
         }
-        BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
-        mAdapter = manager.getAdapter();
+        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+        mAdapter = TestUtils.getBluetoothAdapterOrDie();
         assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
 
         mProfileConnectedlock = new ReentrantLock();
@@ -88,20 +86,14 @@
         mIsProfileReady = false;
         mBluetoothLeBroadcast = null;
 
-        Resources bluetoothResources = null;
-        try {
-            bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
-                    "com.android.bluetooth");
-        } catch (PackageManager.NameNotFoundException e) {
-            return;
+        mIsLeBroadcastSupported =
+                mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+        if (mIsLeBroadcastSupported) {
+            boolean isBroadcastSourceEnabledInConfig =
+                    TestUtils.getProfileConfigValueOrDie(BluetoothProfile.LE_AUDIO_BROADCAST);
+            assertTrue("Config must be true when profile is supported",
+                    isBroadcastSourceEnabledInConfig);
         }
-        int leBroadcastSupportId = bluetoothResources.getIdentifier(
-                PROFILE_SUPPORTED_LE_BROADCAST, "bool", "com.android.bluetooth");
-        if (leBroadcastSupportId == 0) {
-            return;
-        }
-        mIsLeBroadcastSupported = bluetoothResources.getBoolean(
-                leBroadcastSupportId);
         if (!mIsLeBroadcastSupported) {
             return;
         }
@@ -121,13 +113,15 @@
             }
             assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
             mAdapter = null;
+            TestUtils.dropPermissionAsShellUid();
         }
     }
 
     @Test
     public void testGetConnectedDevices() {
-        if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcast);
 
@@ -140,8 +134,9 @@
 
     @Test
     public void testGetDevicesMatchingConnectionStates() {
-        if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
-
+        if (shouldSkipTest()) {
+            return;
+        }
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcast);
 
@@ -155,7 +150,9 @@
 
     @Test
     public void testGetConnectionState() {
-        if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
+        if (shouldSkipTest()) {
+            return;
+        }
 
         assertTrue(waitForProfileConnect());
         assertNotNull(mBluetoothLeBroadcast);
@@ -186,6 +183,10 @@
         assertTrue(mIsLeBroadcastSupported);
     }
 
+    private boolean shouldSkipTest() {
+        return !(mHasBluetooth && mIsLeBroadcastSupported);
+    }
+
     private boolean waitForProfileConnect() {
         mProfileConnectedlock.lock();
         try {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java b/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
index 7c4c454..6da32e3 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
@@ -16,30 +16,168 @@
 
 package android.bluetooth.cts;
 
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
 import android.bluetooth.le.ScanRecord;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.provider.Settings;
 import android.util.Log;
 
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import junit.framework.Assert;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * Utility class for Bluetooth CTS test.
  */
 class TestUtils {
     /**
+     * Bluetooth package name
+     */
+    static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+
+    /**
+     * Get the Config.xml name tag for a particular Bluetooth profile
+     * @param profile profile id from {@link BluetoothProfile}
+     * @return config name tag, or null if the tag name is not available
+     */
+    @Nullable static String profileIdToConfigTag(int profile) {
+        switch (profile) {
+            case BluetoothProfile.A2DP:
+                return "profile_supported_a2dp";
+            case BluetoothProfile.A2DP_SINK:
+                return "profile_supported_a2dp_sink";
+            case BluetoothProfile.HEADSET:
+                return "profile_supported_hs_hfp";
+            case BluetoothProfile.HEADSET_CLIENT:
+                return "profile_supported_hfpclient";
+            case BluetoothProfile.HID_HOST:
+                return "profile_supported_hid_host";
+            case BluetoothProfile.OPP:
+                return "profile_supported_opp";
+            case BluetoothProfile.PAN:
+                return "profile_supported_pan";
+            case BluetoothProfile.PBAP:
+                return "profile_supported_pbap";
+            case BluetoothProfile.GATT:
+                return "profile_supported_gatt";
+            case BluetoothProfile.MAP:
+                return "profile_supported_map";
+            // Hidden profile
+            // case BluetoothProfile.AVRCP:
+            //    return "profile_supported_avrcp_target";
+            case BluetoothProfile.AVRCP_CONTROLLER:
+                return "profile_supported_avrcp_controller";
+            case BluetoothProfile.SAP:
+                return "profile_supported_sap";
+            case BluetoothProfile.PBAP_CLIENT:
+                return "profile_supported_pbapclient";
+            case BluetoothProfile.MAP_CLIENT:
+                return "profile_supported_mapmce";
+            case BluetoothProfile.HID_DEVICE:
+                return "profile_supported_hid_device";
+            case BluetoothProfile.LE_AUDIO:
+                return "profile_supported_le_audio";
+            case BluetoothProfile.LE_AUDIO_BROADCAST:
+                return "profile_supported_le_audio_broadcast";
+            case BluetoothProfile.VOLUME_CONTROL:
+                return "profile_supported_vc";
+            // Hidden profile
+            // case BluetoothProfile.MCP_SERVER:
+            //    return "profile_supported_mcp_server";
+            case BluetoothProfile.CSIP_SET_COORDINATOR:
+                return "profile_supported_csip_set_coordinator";
+            // Hidden profile
+            // case BluetoothProfile.LE_CALL_CONTROL:
+            //    return "profile_supported_le_call_control";
+            case BluetoothProfile.HAP_CLIENT:
+                return "profile_supported_hap_client";
+            case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT:
+                return "profile_supported_bass_client";
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Checks if a particular Bluetooth profile is configured for this device
+     * Fail the test if profile config status cannot be obtained
+     */
+    static boolean getProfileConfigValueOrDie(int profile) {
+        String profileConfigValueTag = profileIdToConfigTag(profile);
+        assertNotNull(profileConfigValueTag);
+        assertNotEquals("profile tag cannot be empty", 0, profileConfigValueTag.length());
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        Resources bluetoothResources = null;
+        try {
+            bluetoothResources = context.getPackageManager().getResourcesForApplication(
+                    BLUETOOTH_PACKAGE_NAME);
+        } catch (PackageManager.NameNotFoundException e) {
+            fail("Cannot get Bluetooth package resource");
+        }
+        int resourceId = bluetoothResources.getIdentifier(
+                profileConfigValueTag, "bool", BLUETOOTH_PACKAGE_NAME);
+        if (resourceId == 0) {
+            return false;
+        }
+        return bluetoothResources.getBoolean(resourceId);
+    }
+
+    /**
+     * Checks whether this device has Bluetooth feature
+     * @return true if this device has Bluetooth feature
+     */
+    static boolean hasBluetooth() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        return context.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_BLUETOOTH);
+    }
+
+    /**
+     * Adopt shell UID's permission via {@link android.app.UiAutomation}
+     * @param permission permission to adopt
+     */
+    static void adoptPermissionAsShellUid(@NonNull String permission) {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .adoptShellPermissionIdentity(permission);
+    }
+
+    /**
+     * Drop all permissions adopted as shell UID
+     */
+    static void dropPermissionAsShellUid() {
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .dropShellPermissionIdentity();
+    }
+
+    /**
+     * Get {@link BluetoothAdapter} via {@link android.bluetooth.BluetoothManager}
+     * Fail the test if {@link BluetoothAdapter} is null
+     * @return instance of {@link BluetoothAdapter}
+     */
+    @NonNull static BluetoothAdapter getBluetoothAdapterOrDie() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        BluetoothManager manager = context.getSystemService(BluetoothManager.class);
+        assertNotNull(manager);
+        BluetoothAdapter adapter = manager.getAdapter();
+        assertNotNull(adapter);
+        return adapter;
+    }
+
+    /**
      * Utility method to call hidden ScanRecord.parseFromBytes method.
      */
     static ScanRecord parseScanRecord(byte[] bytes) {
diff --git a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
index 6c706be..0b744d8 100644
--- a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
+++ b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
@@ -35,6 +35,7 @@
 import android.os.UserManager;
 import android.util.Log;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.SystemUtil;
@@ -99,6 +100,7 @@
                 .contains("dumpServiceStacks ANR file path=/data/anr/anr_");
     }
 
+    @FlakyTest(bugId = 222167696)
     @Test
     public void testSendUserLifecycleEventAndOnUserRemoved() throws Exception {
         // Add listener to check if user started
@@ -129,7 +131,9 @@
             // check the dump stack
             assertLastUserRemoved(userId);
         } finally {
-            if (!userRemoved) userManager.removeUser(response.getUser());
+            if (!userRemoved && response != null && response.isSuccessful()) {
+                userManager.removeUser(response.getUser());
+            }
             carUserManager.removeListener(listener);
             InstrumentationRegistry.getInstrumentation().getUiAutomation()
                     .dropShellPermissionIdentity();
diff --git a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
index d0d9b04..0c62806 100644
--- a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
@@ -48,7 +48,7 @@
 @RunWith(AndroidJUnit4.class)
 public class CarTelemetryManagerTest extends CarApiTestBase {
 
-    /* Test MetricsConfig that does nothing. */
+    /** Test MetricsConfig that does nothing. */
     private static final TelemetryProto.MetricsConfig TEST_CONFIG =
             TelemetryProto.MetricsConfig.newBuilder()
                     .setName("test_config")
@@ -57,7 +57,7 @@
                     .build();
     private static final String TEST_CONFIG_NAME = TEST_CONFIG.getName();
 
-    /* MetricsConfig with simple script that listens for parking brake change. */
+    /** MetricsConfig with simple script that listens for parking brake change. */
     private static final String PARKING_BRAKE_CHANGE_SCRIPT = new StringBuilder()
             .append("function onParkingBrakeChange(published_data, saved_state)\n")
             .append("    result = {data = \"Hello World!\"}\n")
@@ -86,7 +86,7 @@
                     .build();
     private static final String PARKING_BRAKE_CONFIG_NAME = PARKING_BRAKE_CONFIG.getName();
 
-    /*
+    /**
      * MetricsConfig with a bad script that listens for parking brake change, will produce error.
      */
     private static final TelemetryProto.MetricsConfig ERROR_CONFIG =
diff --git a/tests/tests/car_builtin/AndroidManifest.xml b/tests/tests/car_builtin/AndroidManifest.xml
index ef09db3..d86153d 100644
--- a/tests/tests/car_builtin/AndroidManifest.xml
+++ b/tests/tests/car_builtin/AndroidManifest.xml
@@ -18,6 +18,7 @@
     package="android.car.cts.builtin">
     <uses-feature android:name="android.hardware.type.automotive" />
 
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
     <application android:description="@string/app_description">
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
index f5012b5..bc3fc04 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
@@ -43,11 +43,6 @@
     private static final int OWNING_UID = -1;
 
     @Test
-    public void testGetInstance() throws Exception {
-        assertThat(ActivityManagerHelper.getInstance()).isNotNull();
-    }
-
-    @Test
     public void testCheckComponentPermission() throws Exception {
         // not requested from Manifest
         assertComponentPermissionNotGranted(NOT_REQUESTED_PERMISSION_CAR_MILEAGE);
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
index 42e5968..2c2e3f1 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
@@ -16,7 +16,10 @@
 
 package android.car.cts.builtin.content.pm;
 
+import static android.car.builtin.content.pm.PackageManagerHelper.PROPERTY_CAR_SERVICE_PACKAGE_NAME;
+
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.car.builtin.content.pm.PackageManagerHelper;
 import android.car.cts.builtin.R;
@@ -26,6 +29,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -119,6 +123,21 @@
         // builtin API
     }
 
+    @Test
+    public void testCarServicePackageName() throws Exception {
+        // The property must exist.
+        String packageName = SystemProperties.get(
+                PROPERTY_CAR_SERVICE_PACKAGE_NAME, /* def= */null);
+
+        assertWithMessage("Property %s not defined", PROPERTY_CAR_SERVICE_PACKAGE_NAME).that(
+                packageName).isNotNull();
+
+        // The package must exist.
+        PackageInfo info = mPackageManager.getPackageInfo(packageName, /* flags= */ 0);
+
+        assertWithMessage("Package %s not found", packageName).that(info).isNotNull();
+    }
+
     private boolean hasActivity(String activityName, ActivityInfo[] activities) {
         return Arrays.stream(activities).anyMatch(a -> activityName.equals(a.name));
     }
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
index af5a0a2..9217465 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
@@ -38,20 +38,20 @@
     public void testSetDisplayState() {
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
         Context context = instrumentation.getContext();
-        PowerManagerHelper helper = new PowerManagerHelper(context);
         PowerManager powerManager = context.getSystemService(PowerManager.class);
         UiAutomation uiAutomation = instrumentation.getUiAutomation();
 
         uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.DEVICE_POWER);
 
         try {
-            helper.setDisplayState(/* on= */ true, SystemClock.uptimeMillis());
+            PowerManagerHelper.setDisplayState(context, /* on= */ true, SystemClock.uptimeMillis());
             assertWithMessage("Screen on").that(powerManager.isInteractive()).isTrue();
 
-            helper.setDisplayState(/* on= */ false, SystemClock.uptimeMillis());
+            PowerManagerHelper.setDisplayState(context, /* on= */ false,
+                    SystemClock.uptimeMillis());
             assertWithMessage("Screen on").that(powerManager.isInteractive()).isFalse();
 
-            helper.setDisplayState(/* on= */ true, SystemClock.uptimeMillis());
+            PowerManagerHelper.setDisplayState(context, /* on= */ true, SystemClock.uptimeMillis());
             assertWithMessage("Screen on").that(powerManager.isInteractive()).isTrue();
         } finally {
             uiAutomation.dropShellPermissionIdentity();
diff --git a/tests/tests/companion/Android.bp b/tests/tests/companion/Android.bp
index 22a45e8..6d465ce 100644
--- a/tests/tests/companion/Android.bp
+++ b/tests/tests/companion/Android.bp
@@ -76,6 +76,38 @@
 }
 
 android_test {
+    name: "CtsCompanionDeviceManagerNoCompanionServicesTestCases",
+    srcs: [
+        "noservices/src/**/*.kt",
+    ],
+    manifest: "noservices/AndroidManifest.xml",
+    test_config: "noservices/AndroidTest.xml",
+
+    platform_apis: true,
+    static_libs: [
+        "androidx.test.ext.junit",
+        "cts-companion-common",
+        "junit",
+        "kotlin-test",
+    ],
+    libs: [
+        "android.test.base",
+        "android.test.runner",
+    ],
+
+    defaults: ["cts_defaults"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+
+    // TODO(b/211264986) Change both SDK versions to T (33) once it's formally defined.
+    min_sdk_version: "current",
+    target_sdk_version: "current",
+}
+
+android_test {
     name: "CtsCompanionDeviceManagerUiAutomationTestCases",
     srcs: [
         "uiautomation/src/**/*.kt",
diff --git a/tests/tests/companion/common/AndroidManifest.xml b/tests/tests/companion/common/AndroidManifest.xml
index bf91897..febd8a0 100644
--- a/tests/tests/companion/common/AndroidManifest.xml
+++ b/tests/tests/companion/common/AndroidManifest.xml
@@ -34,7 +34,6 @@
 
             <property android:name="android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"
                       android:value="true" />
-
         </service>
 
         <service
@@ -47,6 +46,26 @@
             </intent-filter>
         </service>
 
+        <!-- Service does not require BIND_COMPANION_DEVICE_SERVICE -->
+        <service
+                android:name=".MissingPermissionCompanionService"
+                android:exported="true"
+                android:label="Secondary Companion Service">
+            <intent-filter>
+                <action android:name="android.companion.CompanionDeviceService" />
+            </intent-filter>
+        </service>
+
+        <!--
+        Service does not declare an intent-filter for "android.companion.CompanionDeviceService"
+        action
+        -->
+        <service
+                android:name=".MissingIntentFilterActionCompanionService"
+                android:exported="true"
+                android:label="Primary Companion Service"
+                android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE"/>
+
         <activity
                 android:name=".CompanionActivity"
                 android:exported="false"
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
index 4c16478..4d09333 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
@@ -135,4 +135,14 @@
 
 class SecondaryCompanionService : CompanionService<SecondaryCompanionService>(Companion) {
     companion object : InstanceHolder<SecondaryCompanionService>()
+}
+
+class MissingPermissionCompanionService
+    : CompanionService<MissingPermissionCompanionService>(Companion) {
+    companion object : InstanceHolder<MissingPermissionCompanionService>()
+}
+
+class MissingIntentFilterActionCompanionService
+    : CompanionService<MissingIntentFilterActionCompanionService>(Companion) {
+    companion object : InstanceHolder<MissingIntentFilterActionCompanionService>()
 }
\ No newline at end of file
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
index 812238d..b650324 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
@@ -16,10 +16,12 @@
 
 package android.companion.cts.common
 
+import android.Manifest
 import android.annotation.CallSuper
 import android.app.Instrumentation
 import android.app.UiAutomation
 import android.companion.AssociationInfo
+import android.companion.AssociationRequest
 import android.companion.CompanionDeviceManager
 import android.content.Context
 import android.content.pm.PackageManager
@@ -36,6 +38,7 @@
 import java.io.IOException
 import kotlin.test.assertEquals
 import kotlin.test.assertFalse
+import kotlin.test.assertIs
 import kotlin.test.assertTrue
 import kotlin.time.Duration
 import kotlin.time.Duration.Companion.seconds
@@ -112,6 +115,23 @@
         }
     }
 
+    protected fun createSelfManagedAssociation(displayName: String): Int {
+        val callback = RecordingCallback()
+        val request: AssociationRequest = AssociationRequest.Builder()
+                .setSelfManaged(true)
+                .setDisplayName(displayName)
+                .build()
+        callback.assertInvokedByActions {
+            withShellPermissionIdentity(Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) {
+                cdm.associate(request, SIMPLE_EXECUTOR, callback)
+            }
+        }
+
+        val callbackInvocation = callback.invocations.first()
+        assertIs<RecordingCallback.OnAssociationCreated>(callbackInvocation)
+        return callbackInvocation.associationInfo.id
+    }
+
     private fun CompanionDeviceManager.disassociateAll() =
             allAssociations.forEach { disassociate(it.id) }
 }
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
index 15202bd..54cc1e6 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
@@ -17,14 +17,12 @@
 package android.companion.cts.core
 
 import android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED
-import android.companion.AssociationRequest
 import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
 import android.companion.cts.common.DEVICE_DISPLAY_NAME_B
 import android.companion.cts.common.MAC_ADDRESS_A
+import android.companion.cts.common.MissingIntentFilterActionCompanionService
+import android.companion.cts.common.MissingPermissionCompanionService
 import android.companion.cts.common.PrimaryCompanionService
-import android.companion.cts.common.RecordingCallback
-import android.companion.cts.common.RecordingCallback.OnAssociationCreated
-import android.companion.cts.common.SIMPLE_EXECUTOR
 import android.companion.cts.common.SecondaryCompanionService
 import android.companion.cts.common.assertEmpty
 import android.companion.cts.common.waitFor
@@ -36,7 +34,6 @@
 import kotlin.test.assertContentEquals
 import kotlin.test.assertFailsWith
 import kotlin.test.assertFalse
-import kotlin.test.assertIs
 import kotlin.test.assertTrue
 import kotlin.time.Duration.Companion.milliseconds
 import kotlin.time.Duration.Companion.seconds
@@ -63,23 +60,35 @@
 
         cdm.notifyDeviceAppeared(associationId)
 
-        assertTrue("Both Services - Primary and Secondary - should be bound now") {
+        assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
+                "now") {
             waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
                 PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
             }
         }
+        assertFalse("CompanionDeviceServices that do not require " +
+                "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
+                "\"android.companion.CompanionDeviceService\" action should not be bound") {
+            MissingPermissionCompanionService.isBound ||
+                    MissingIntentFilterActionCompanionService.isBound
+        }
 
-        // Check that only the primary services has received the onDeviceAppeared() callback...
+        // Check that only the primary CompanionDeviceService has received the onDeviceAppeared()
+        // callback...
         PrimaryCompanionService.waitAssociationToAppear(associationId)
         assertContentEquals(
                 actual = PrimaryCompanionService.associationIdsForConnectedDevices,
                 expected = setOf(associationId)
         )
-        // ... while the non-primary service - has NOT. (Give it 1 more second.)
+        // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
+        // have NOT. (Give it 1 more second.)
         sleep(1000)
         assertEmpty(SecondaryCompanionService.connectedDevices)
+        assertEmpty(MissingPermissionCompanionService.connectedDevices)
+        assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
 
-        assertFalse("Both Services - Primary and Secondary - should stay bound") {
+        assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+                "bound ") {
             waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
                 !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
             }
@@ -105,11 +114,18 @@
 
         cdm.notifyDeviceAppeared(idA)
 
-        assertTrue("Both Services - Primary and Secondary - should be bound now") {
+        assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
+                "now") {
             waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
                 PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
             }
         }
+        assertFalse("CompanionDeviceServices that do not require " +
+                "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
+                "\"android.companion.CompanionDeviceService\" action should not be bound") {
+            MissingPermissionCompanionService.isBound ||
+                    MissingIntentFilterActionCompanionService.isBound
+        }
 
         // Check that only the primary services has received the onDeviceAppeared() callback...
         PrimaryCompanionService.waitAssociationToAppear(idA)
@@ -117,9 +133,12 @@
             actual = PrimaryCompanionService.associationIdsForConnectedDevices,
             expected = setOf(idA)
         )
-        // ... while the non-primary service - has NOT. (Give it 1 more second.)
+        // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
+        // have NOT. (Give it 1 more second.)
         sleep(1000)
         assertEmpty(SecondaryCompanionService.connectedDevices)
+        assertEmpty(MissingPermissionCompanionService.connectedDevices)
+        assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
 
         cdm.notifyDeviceAppeared(idB)
 
@@ -130,8 +149,9 @@
             expected = setOf(idA, idB)
         )
 
-        // Make sure both services stay bound.
-        assertFalse("Both Services - Primary and Secondary - should stay bound") {
+        // Make sure both valid services stay bound.
+        assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+                "bound ") {
             waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
                 !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
             }
@@ -141,10 +161,11 @@
         cdm.notifyDeviceDisappeared(idA)
 
         PrimaryCompanionService.waitAssociationToDisappear(idA)
-        // Both services should stay bound for as long as there is at least
-        // one connected device - device B in this case.
-        assertFalse("Both Services - Primary and Secondary - should stay bound") {
-            waitFor(timeout = 3.seconds, interval = 1.seconds) {
+        // Both valid services should stay bound for as long as there is at least one connected
+        // device - device B in this case.
+        assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+                "bound ") {
+            waitFor(timeout = 3.seconds, interval = 1.milliseconds) {
                 !PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
             }
         }
@@ -183,21 +204,4 @@
             cdm.notifyDeviceAppeared(id)
         }
     }
-
-    private fun createSelfManagedAssociation(displayName: String): Int {
-        val callback = RecordingCallback()
-        val request: AssociationRequest = AssociationRequest.Builder()
-            .setSelfManaged(true)
-            .setDisplayName(displayName)
-            .build()
-        callback.assertInvokedByActions {
-            withShellPermissionIdentity(REQUEST_COMPANION_SELF_MANAGED) {
-                cdm.associate(request, SIMPLE_EXECUTOR, callback)
-            }
-        }
-
-        val callbackInvocation = callback.invocations.first()
-        assertIs<OnAssociationCreated>(callbackInvocation)
-        return callbackInvocation.associationInfo.id
-    }
 }
\ No newline at end of file
diff --git a/tests/tests/companion/noservices/AndroidManifest.xml b/tests/tests/companion/noservices/AndroidManifest.xml
new file mode 100644
index 0000000..a851ff4
--- /dev/null
+++ b/tests/tests/companion/noservices/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?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.companion.cts.noservices">
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.companion.cts.noservices"
+        android:label="CompanionDeviceManager No-CompanionDeviceServices CTS tests">
+
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+    <application>
+        <!--
+        "Re-define" PrimaryCompanionService and SecondaryCompanionService services defined in
+        common/AndroidManifest.xml. This should leave the package without any valid
+        CompanionDeviceServices.
+        -->
+        <service
+            android:name="android.companion.cts.common.PrimaryCompanionService"
+            android:enabled="false" />
+        <service
+            android:name="android.companion.cts.common.SecondaryCompanionService"
+            android:enabled="false" />
+    </application>
+
+</manifest>
+
diff --git a/tests/tests/companion/noservices/AndroidTest.xml b/tests/tests/companion/noservices/AndroidTest.xml
new file mode 100644
index 0000000..fd7a954
--- /dev/null
+++ b/tests/tests/companion/noservices/AndroidTest.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.
+-->
+<configuration description="Configuration for No-Companion-Devices-Services CTS tests for CompanionDeviceManager">
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+    <option name="not-shardable" value="true" />
+    <option name="test-suite-tag" value="cts" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsCompanionDeviceManagerNoCompanionServicesTestCases.apk" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.companion.cts.noservices" />
+        <option name="runtime-hint" value="1s" />
+    </test>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="am wait-for-broadcast-idle" />
+    </target_preparer>
+</configuration>
diff --git a/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt b/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt
new file mode 100644
index 0000000..92d468c
--- /dev/null
+++ b/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.companion.cts.noservices
+
+import android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED
+import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
+import android.companion.cts.common.MissingIntentFilterActionCompanionService
+import android.companion.cts.common.MissingPermissionCompanionService
+import android.companion.cts.common.PrimaryCompanionService
+import android.companion.cts.common.SecondaryCompanionService
+import android.companion.cts.common.TestBase
+import android.companion.cts.common.waitFor
+import android.platform.test.annotations.AppModeFull
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertFalse
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+
+/**
+ * Tests CDM handling the case when the companion application does not define a valid
+ * [CompanionDeviceService][android.companion.CompanionDeviceService].
+ *
+ * Build/Install/Run:
+ * atest CtsCompanionDeviceManagerNoCompanionServicesTestCases:NoCompanionDeviceServiceTest
+ */
+@AppModeFull(reason = "CompanionDeviceManager APIs are not available to the instant apps.")
+@RunWith(AndroidJUnit4::class)
+class NoCompanionDeviceServiceTest : TestBase() {
+
+    /**
+     * Ensures that CDM service DOES NOT try to bind
+     * [CompanionDeviceServices][android.companion.CompanionDeviceService] that do not meet all the
+     * requirements, as well as that the system's stability in case when the companion applications
+     * do not define any valid CompanionDeviceServices.
+     */
+    @Test
+    fun test_noService() =
+            withShellPermissionIdentity(REQUEST_COMPANION_SELF_MANAGED) {
+                val associationId = createSelfManagedAssociation(DEVICE_DISPLAY_NAME_A)
+
+                // This should neither throw an Exception nor cause system to crash, even when the
+                // companion application does not define any valid CompanionDeviceServices.
+                // (If the system crashes this instrumentation test won't complete).
+                cdm.notifyDeviceAppeared(associationId)
+
+                // Every 100ms check if any of the services is bound or received a callback.
+                assertFalse("None of the services should be bound or receive a callback") {
+                    waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
+                        val isBound = PrimaryCompanionService.isBound ||
+                                SecondaryCompanionService.isBound ||
+                                MissingPermissionCompanionService.isBound ||
+                                MissingIntentFilterActionCompanionService.isBound
+                        val receivedCallback =
+                                PrimaryCompanionService.connectedDevices.isNotEmpty() ||
+                                SecondaryCompanionService.connectedDevices.isNotEmpty() ||
+                                MissingPermissionCompanionService.connectedDevices.isNotEmpty() ||
+                                MissingIntentFilterActionCompanionService.connectedDevices
+                                        .isNotEmpty()
+                        return@waitFor isBound || receivedCallback
+                    }
+                }
+
+                // This should neither throw an Exception nor cause system to crash, even when the
+                // companion application does not define any valid CompanionDeviceServices.
+                // (If the system crashes this instrumentation test won't complete).
+                cdm.notifyDeviceDisappeared(associationId)
+            }
+}
\ No newline at end of file
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 7736065..da8a7ab 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -44,8 +44,11 @@
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.pm.ApkChecksum;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.DataLoaderParams;
@@ -57,9 +60,12 @@
 import android.content.pm.Signature;
 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;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.platform.test.annotations.AppModeFull;
 import android.util.PackageUtils;
@@ -73,6 +79,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -93,6 +100,7 @@
 import java.util.List;
 import java.util.Optional;
 import java.util.Random;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
@@ -235,6 +243,15 @@
         }
     }
 
+    private static void writeFileToSession(PackageInstaller.Session session, String name,
+            String apk) throws IOException {
+        File file = new File(createApkPath(apk));
+        try (OutputStream os = session.openWrite(name, 0, file.length());
+             InputStream is = new FileInputStream(file)) {
+            writeFullStream(is, os, file.length());
+        }
+    }
+
     @Before
     public void onBefore() throws Exception {
         // Check if Incremental is allowed and revert to non-dataloader installation.
@@ -597,6 +614,78 @@
     }
 
     @Test
+    public void testDontKillWithSplit() throws Exception {
+        installPackage(TEST_HW5);
+
+        getUiAutomation().adoptShellPermissionIdentity();
+        try {
+            final PackageInstaller installer = getPackageInstaller();
+            final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+            params.setAppPackageName(TEST_APP_PACKAGE);
+            params.setDontKillApp(true);
+
+            final int sessionId = installer.createSession(params);
+            PackageInstaller.Session session = installer.openSession(sessionId);
+            assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+            writeFileToSession(session, "hw5_split0", TEST_HW5_SPLIT0);
+
+            final CompletableFuture<Boolean> result = new CompletableFuture<>();
+            session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+                @Override
+                public void send(int code, Intent intent, String resolvedType,
+                        IBinder whitelistToken, IIntentReceiver finishedReceiver,
+                        String requiredPermission, Bundle options) throws RemoteException {
+                    boolean dontKillApp =
+                            (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+                    result.complete(dontKillApp);
+                }
+            }));
+
+            // We are adding split. OK to have the flag.
+            assertTrue(result.get());
+        } finally {
+            getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+
+    @Test
+    public void testDontKillRemovedWithBaseApk() throws Exception {
+        installPackage(TEST_HW5);
+
+        getUiAutomation().adoptShellPermissionIdentity();
+        try {
+            final PackageInstaller installer = getPackageInstaller();
+            final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+            params.setAppPackageName(TEST_APP_PACKAGE);
+            params.setDontKillApp(true);
+
+            final int sessionId = installer.createSession(params);
+            PackageInstaller.Session session = installer.openSession(sessionId);
+            assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+            writeFileToSession(session, "hw7", TEST_HW7);
+
+            final CompletableFuture<Boolean> result = new CompletableFuture<>();
+            session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+                @Override
+                public void send(int code, Intent intent, String resolvedType,
+                        IBinder whitelistToken, IIntentReceiver finishedReceiver,
+                        String requiredPermission, Bundle options) throws RemoteException {
+                    boolean dontKillApp =
+                            (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+                    result.complete(dontKillApp);
+                }
+            }));
+
+            // We are updating base.apk. Flag to be removed.
+            assertFalse(result.get());
+        } finally {
+            getUiAutomation().dropShellPermissionIdentity();
+        }
+    }
+
+    @Test
     public void testDataLoaderParamsApiV1() throws Exception {
         if (!mStreaming) {
             return;
@@ -1309,6 +1398,7 @@
         }
     }
 
+    @Ignore
     @Test
     public void testGetFirstInstallTime() throws Exception {
         final int currentUser = getContext().getUserId();
@@ -1433,6 +1523,7 @@
         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
     }
 
+    @Ignore
     @Test
     public void testPackageFullyRemovedBroadcastAfterUninstall() throws IOException {
         final int currentUser = getContext().getUserId();
@@ -1483,7 +1574,7 @@
         final ApplicationInfo info = pm.getApplicationInfo(
                 name, PackageManager.ApplicationInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY));
         assertEquals(ApplicationInfo.FLAG_SYSTEM, info.flags & ApplicationInfo.FLAG_SYSTEM);
-        assertTrue(info.sourceDir.startsWith("/apex/com.android.supplementalprocess"));
+        assertTrue(info.sourceDir.startsWith("/apex/com.android.adservices"));
     }
 
     @Test
@@ -1606,8 +1697,9 @@
     private boolean isAppInstalled(String packageName) throws IOException {
         final String commandResult = executeShellCommand("pm list packages");
         final int prefixLength = "package:".length();
-        return Arrays.stream(commandResult.split("\\r?\\n"))
-                .anyMatch(line -> line.substring(prefixLength).equals(packageName));
+        return Arrays.stream(commandResult.split("\\r?\\n")).anyMatch(
+                line -> line.length() > prefixLength && line.substring(prefixLength).equals(
+                        packageName));
     }
 
     private boolean isAppInstalledForUser(String packageName, int userId) throws IOException {
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
index eb51afa..e2346c4 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
@@ -28,6 +28,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.database.sqlite.SQLiteDebug;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteGlobal;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQuery;
@@ -289,6 +290,59 @@
         }
     }
 
+    /**
+     * Tests a scenario in WAL mode with multiple connections, when a connection should see schema
+     * changes made from another connection.
+     */
+    public void testWalSchemaChangeVisibilityOnDowngrade() {
+        File dbPath = mContext.getDatabasePath(TEST_DATABASE_NAME);
+        SQLiteDatabase.deleteDatabase(dbPath);
+        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
+        db.execSQL("CREATE TABLE test_table (_id INTEGER PRIMARY KEY AUTOINCREMENT"
+                + ", _key INTEGER DEFAULT 1234)");
+        db.execSQL("CREATE TABLE test_table2 (_id INTEGER PRIMARY KEY AUTOINCREMENT)");
+        db.setVersion(2);
+        try (Cursor cursor = db.rawQuery("select * from test_table", null)) {
+            assertEquals(2, cursor.getColumnCount());
+        }
+        try (Cursor cursor = db.rawQuery("select * from test_table2", null)) {
+            assertEquals(1, cursor.getColumnCount());
+        }
+        db.close();
+        mOpenHelper = new MockOpenHelper(mContext, TEST_DATABASE_NAME, null, 1) {
+            {
+                setWriteAheadLoggingEnabled(true);
+            }
+
+            @Override
+            public void onCreate(SQLiteDatabase db) {
+            }
+
+            @Override
+            public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+                if (newVersion == 1) {
+                    // Drop all tables
+                    db.execSQL("DROP TABLE IF EXISTS test_table");
+                    db.execSQL("DROP TABLE IF EXISTS test_table2");
+
+                    // Recreate test_table with one column _id
+                    db.execSQL("CREATE TABLE test_table"
+                            + " (_id INTEGER PRIMARY KEY AUTOINCREMENT)");
+                }
+            }
+        };
+        // Check if the test_table has only one column.
+        try (Cursor cursor = mOpenHelper.getReadableDatabase()
+                .rawQuery("select * from test_table", null)) {
+            assertEquals(1, cursor.getColumnCount());
+        }
+        // Check if the test_table2 has been dropped.
+        try (Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(
+                "select name from sqlite_master where type='table' and name='test_table2'", null)) {
+            assertEquals(0, cursor.getCount());
+        }
+    }
+
     public void testSetWriteAheadLoggingDisablesCompatibilityWal() {
         // Verify that compatibility WAL is not enabled, if an application explicitly disables WAL
 
diff --git a/tests/tests/gamemanager/Android.bp b/tests/tests/gamemanager/Android.bp
index 827d41f..4e8b4b7 100644
--- a/tests/tests/gamemanager/Android.bp
+++ b/tests/tests/gamemanager/Android.bp
@@ -28,6 +28,8 @@
 
     data: [
         ":CtsGameTestApp",
+        ":CtsGameTestAppWithBatteryMode",
+        ":CtsGameTestAppWithPerformanceMode",
         ":CtsLegacyGameTestApp",
         ":CtsNotGameTestApp",
     ],
diff --git a/tests/tests/gamemanager/AndroidTest.xml b/tests/tests/gamemanager/AndroidTest.xml
index be17c48..fb23c6c 100644
--- a/tests/tests/gamemanager/AndroidTest.xml
+++ b/tests/tests/gamemanager/AndroidTest.xml
@@ -30,6 +30,8 @@
         <option name="push" value="CtsLegacyGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsLegacyGameTestApp.apk" />
         <option name="push" value="CtsNotGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsNotGameTestApp.apk" />
         <option name="push" value="CtsGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestApp.apk" />
+        <option name="push" value="CtsGameTestAppWithBatteryMode.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestAppWithBatteryMode.apk" />
+        <option name="push" value="CtsGameTestAppWithPerformanceMode.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestAppWithPerformanceMode.apk" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp b/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp
new file mode 100644
index 0000000..b428860
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsGameTestAppWithBatteryMode",
+    srcs: [
+        "src/**/*.java",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "guava",
+    ],
+    defaults: ["cts_support_defaults"],
+    min_sdk_version: "current",
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml b/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml
new file mode 100644
index 0000000..9834584
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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.gamemanager.cts.app.gametestapp.battery">
+
+    <application android:appCategory="game">
+        <uses-library android:name="android.test.runner"/>
+        <meta-data android:name="android.game_mode_config"
+                   android:resource="@xml/game_mode_config" />
+        <activity android:name=".GameTestAppMainActivity"
+                  android:label="GameTestAppMainActivity"
+                  android:visibleToInstantApps="true"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml b/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml
new file mode 100644
index 0000000..a1991a1
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<game-mode-config
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:supportsBatteryGameMode="true"
+    android:supportsPerformanceGameMode="false"
+    android:allowGameAngleDriver="true"
+    android:allowGameDownscaling="true"
+/>
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java b/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
new file mode 100644
index 0000000..7e2536c
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.gamemanager.cts.app;
+
+import android.app.Activity;
+import android.app.GameManager;
+import android.content.Context;
+import android.os.Bundle;
+
+public class GameTestAppMainActivity extends Activity {
+
+    private static final String TAG = "GameTestAppMainActivity";
+
+    Context mContext;
+    GameManager mGameManager;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getApplicationContext();
+        mGameManager = mContext.getSystemService(GameManager.class);
+    }
+
+    public String getPackageName() {
+        return mContext.getPackageName();
+    }
+
+    public int getGameMode() {
+        return mGameManager.getGameMode();
+    }
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp
new file mode 100644
index 0000000..b783a75
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "CtsGameTestAppWithPerformanceMode",
+    srcs: [
+        "src/**/*.java",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "guava",
+    ],
+    defaults: ["cts_support_defaults"],
+    min_sdk_version: "current",
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml
new file mode 100644
index 0000000..a6174b9
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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.gamemanager.cts.app.gametestapp.performance">
+
+    <application android:appCategory="game">
+        <uses-library android:name="android.test.runner"/>
+        <meta-data android:name="android.game_mode_config"
+                   android:resource="@xml/game_mode_config" />
+        <activity android:name=".GameTestAppMainActivity"
+                  android:label="GameTestAppMainActivity"
+                  android:visibleToInstantApps="true"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml
new file mode 100644
index 0000000..492075c9
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<game-mode-config
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:supportsBatteryGameMode="false"
+    android:supportsPerformanceGameMode="true"
+    android:allowGameAngleDriver="true"
+    android:allowGameDownscaling="true"
+/>
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
new file mode 100644
index 0000000..7e2536c
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.gamemanager.cts.app;
+
+import android.app.Activity;
+import android.app.GameManager;
+import android.content.Context;
+import android.os.Bundle;
+
+public class GameTestAppMainActivity extends Activity {
+
+    private static final String TAG = "GameTestAppMainActivity";
+
+    Context mContext;
+    GameManager mGameManager;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getApplicationContext();
+        mGameManager = mContext.getSystemService(GameManager.class);
+    }
+
+    public String getPackageName() {
+        return mContext.getPackageName();
+    }
+
+    public int getGameMode() {
+        return mGameManager.getGameMode();
+    }
+}
diff --git a/tests/tests/gamemanager/OWNERS b/tests/tests/gamemanager/OWNERS
index 986180d..d0186b0 100644
--- a/tests/tests/gamemanager/OWNERS
+++ b/tests/tests/gamemanager/OWNERS
@@ -1,3 +1,3 @@
 # Bug component: 878256
 lpy@google.com
-timvp@google.com
+xwxw@google.com
diff --git a/tests/tests/gamemanager/res/xml/game_mode_config.xml b/tests/tests/gamemanager/res/xml/game_mode_config.xml
index 492075c9..e013590 100644
--- a/tests/tests/gamemanager/res/xml/game_mode_config.xml
+++ b/tests/tests/gamemanager/res/xml/game_mode_config.xml
@@ -18,7 +18,7 @@
 
 <game-mode-config
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:supportsBatteryGameMode="false"
+    android:supportsBatteryGameMode="true"
     android:supportsPerformanceGameMode="true"
     android:allowGameAngleDriver="true"
     android:allowGameDownscaling="true"
diff --git a/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java b/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
index 7c47072..f6c14be 100644
--- a/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
+++ b/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
@@ -54,14 +54,27 @@
     private static final Pattern GAME_LOADING_REGEX =
             Pattern.compile("^GAME_LOADING\\t(\\d*)\\t\\d*$", Pattern.MULTILINE);
     private static final String APK_DIRECTORY = "/data/local/tmp/cts/gamemanager/test/apps/";
+
     private static final String NOT_GAME_TEST_APP_APK_PATH =
             APK_DIRECTORY + "CtsNotGameTestApp.apk";
     private static final String NOT_GAME_TEST_APP_PACKAGE_NAME =
             "android.gamemanager.cts.app.notgametestapp";
+
     private static final String GAME_TEST_APP_APK_PATH =
             APK_DIRECTORY + "CtsGameTestApp.apk";
     private static final String GAME_TEST_APP_PACKAGE_NAME =
             "android.gamemanager.cts.app.gametestapp";
+
+    private static final String GAME_TEST_APP_WITH_BATTERY_APK_PATH =
+            APK_DIRECTORY + "CtsGameTestAppWithBatteryMode.apk";
+    private static final String GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME =
+            "android.gamemanager.cts.app.gametestapp.battery";
+
+    private static final String GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH =
+            APK_DIRECTORY + "CtsGameTestAppWithPerformanceMode.apk";
+    private static final String GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME =
+            "android.gamemanager.cts.app.gametestapp.performance";
+
     private static final int TEST_LABEL = 1;
     private static final int TEST_QUALITY = 2;
 
@@ -78,6 +91,8 @@
     public void setUp() {
         TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
+        TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
+        TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
 
         mActivityRule.getScenario().onActivity(activity -> {
             mActivity = activity;
@@ -93,21 +108,35 @@
     public void tearDown() throws Exception {
         TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
+        TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
+        TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
     }
 
     @Test
     public void testIsAngleEnabled() throws Exception {
+        final String packageName = GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME;
+        assertTrue(TestUtil.installPackage(GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH));
+        Thread.sleep(500);
+
         // enable Angle for BATTERY mode.
-        runShellCommand("device_config put game_overlay " + mActivity.getPackageName()
+        runShellCommand("device_config put game_overlay " + packageName
                 + " mode=3,useAngle=true");
+        Thread.sleep(500);
+
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
-                (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
-                        GameManager.GAME_MODE_BATTERY));
-        assertTrue(mGameManager.isAngleEnabled(mActivity.getPackageName()));
+                (gameManager) -> gameManager.setGameMode(packageName,
+                        GameManager.GAME_MODE_BATTERY), "android.permission.MANAGE_GAME_MODE");
+        assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+                (gameManager) -> gameManager.isAngleEnabled(packageName),
+                "android.permission.MANAGE_GAME_MODE"));
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
-                (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
-                        GameManager.GAME_MODE_PERFORMANCE));
-        assertFalse(mGameManager.isAngleEnabled(mActivity.getPackageName()));
+                (gameManager) -> gameManager.setGameMode(packageName,
+                        GameManager.GAME_MODE_PERFORMANCE), "android.permission.MANAGE_GAME_MODE");
+        assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+                (gameManager) -> gameManager.isAngleEnabled(packageName),
+                "android.permission.MANAGE_GAME_MODE"));
+
+        TestUtil.uninstallPackage(packageName);
     }
 
     /**
@@ -340,4 +369,40 @@
 
         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
     }
+
+    /**
+     * Test that GameManager::getGameModeInfo() returns correct values for a game when it only
+     * supports battery mode.
+     */
+    @Test
+    public void testGetGameModeInfoWithBatteryMode() throws InterruptedException {
+        final String packageName = GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME;
+        assertTrue(TestUtil.installPackage(GAME_TEST_APP_WITH_BATTERY_APK_PATH));
+        // When an app is installed, some propagation work for the configuration will
+        // be set up asynchronously, hence wait for 500ms here.
+        Thread.sleep(500);
+
+        GameModeInfo gameModeInfo =
+                ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+                        (gameManager) -> gameManager.getGameModeInfo(packageName),
+                        "android.permission.MANAGE_GAME_MODE");
+        assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
+                2, gameModeInfo.getAvailableGameModes().length);
+        assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
+                GameManager.GAME_MODE_STANDARD, gameModeInfo.getActiveGameMode());
+
+        // Attempt to set the game mode to battery.
+        ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
+                (gameManager) -> gameManager.setGameMode(packageName,
+                        GameManager.GAME_MODE_BATTERY));
+        gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+                (gameManager) -> gameManager.getGameModeInfo(packageName),
+                "android.permission.MANAGE_GAME_MODE");
+        assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
+                2, gameModeInfo.getAvailableGameModes().length);
+        assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
+                GameManager.GAME_MODE_BATTERY, gameModeInfo.getActiveGameMode());
+
+        TestUtil.uninstallPackage(packageName);
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java b/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
index 436c1dc..9247ab0 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
+++ b/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
@@ -18,6 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.graphics.Paint;
+import android.graphics.text.PositionedGlyphs;
+import android.graphics.text.TextRunShaper;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -46,4 +49,23 @@
 
         assertThat(FontFileTestUtil.containsEmojiCompatMetadata(emojiFont)).isTrue();
     }
+
+    public String getFontName(String chars) {
+        Paint paint = new Paint();
+
+        PositionedGlyphs glyphs = TextRunShaper.shapeTextRun(
+                chars, 0, chars.length(), 0, chars.length(), 0f, 0f, false, paint);
+        assertThat(glyphs.glyphCount()).isEqualTo(1);
+        assertThat(glyphs.getFont(0)).isNotNull();
+        File file = glyphs.getFont(0).getFile();
+        assertThat(file).isNotNull();
+        assertThat(file.getParent()).isEqualTo("/system/fonts");
+
+        return file.getName();
+    }
+
+    @Test
+    public void doNotDrawLegacy() {
+        assertThat(getFontName("\u263A")).isNotEqualTo("NotoColorEmojiLegacy.ttf");
+    }
 }
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
index 80a7983..ca8d1ec 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
@@ -2022,6 +2022,10 @@
         }
     }
 
+    public void testGetHalVersion() {
+        assertNotEquals(null, AudioManager.getHalVersion());
+    }
+
     private void assertStreamVolumeEquals(int stream, int expectedVolume) throws Exception {
         assertStreamVolumeEquals(stream, expectedVolume,
                 "Unexpected stream volume for stream=" + stream);
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java b/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
index 5c1821b..af4dc75 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
@@ -57,7 +57,6 @@
     @Before
     public void setUp() throws Exception {
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        assumeTrue(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
 
         mAudioManager = context.getSystemService(AudioManager.class);
         mAudioManager.setMode(AudioManager.MODE_NORMAL);
@@ -66,6 +65,8 @@
                 .getUiAutomation()
                 .adoptShellPermissionIdentity(Manifest.permission.CALL_AUDIO_INTERCEPTION,
                         Manifest.permission.MODIFY_PHONE_STATE);
+
+        assumeTrue(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
     }
 
     /** Test teardown */
diff --git a/tests/tests/media/drm/Android.bp b/tests/tests/media/drmframework/Android.bp
similarity index 90%
rename from tests/tests/media/drm/Android.bp
rename to tests/tests/media/drmframework/Android.bp
index 05545db..e7ebf7a 100644
--- a/tests/tests/media/drm/Android.bp
+++ b/tests/tests/media/drmframework/Android.bp
@@ -21,7 +21,7 @@
 }
 
 android_test {
-    name: "CtsMediaDrmTestCases",
+    name: "CtsMediaDrmFrameworkTestCases",
     defaults: ["cts_defaults"],
     // include both the 32 and 64 bit versions
     compile_multilib: "both",
@@ -33,8 +33,8 @@
     ],
     aaptflags: [
         "--auto-add-overlay",
-        // Give com.android.media.drm.cts Java files access to the R class
-        "--extra-packages com.android.media.drm.cts",
+        // Give com.android.media.drmframework.cts Java files access to the R class
+        "--extra-packages com.android.media.drmframework.cts",
 
         // Do not compress these files:
         "-0 .vp9",
diff --git a/tests/tests/media/drm/AndroidManifest.xml b/tests/tests/media/drmframework/AndroidManifest.xml
similarity index 93%
rename from tests/tests/media/drm/AndroidManifest.xml
rename to tests/tests/media/drmframework/AndroidManifest.xml
index e7aa4cd..fd146bd 100644
--- a/tests/tests/media/drm/AndroidManifest.xml
+++ b/tests/tests/media/drmframework/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-     package="android.media.drm.cts"
+     package="android.media.drmframework.cts"
      android:targetSandboxVersion="2">
 
     <uses-sdk android:minSdkVersion="29"
@@ -36,7 +36,7 @@
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-         android:targetPackage="android.media.drm.cts"
+         android:targetPackage="android.media.drmframework.cts"
          android:label="CTS tests of android MediaDrm">
         <meta-data android:name="listener"
              android:value="com.android.cts.runner.CtsTestRunListener"/>
diff --git a/tests/tests/media/drm/AndroidTest.xml b/tests/tests/media/drmframework/AndroidTest.xml
similarity index 82%
rename from tests/tests/media/drm/AndroidTest.xml
rename to tests/tests/media/drmframework/AndroidTest.xml
index 6a4fb73..01639e5 100644
--- a/tests/tests/media/drm/AndroidTest.xml
+++ b/tests/tests/media/drmframework/AndroidTest.xml
@@ -22,30 +22,30 @@
     <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
         <option name="target" value="host" />
-        <option name="config-filename" value="CtsMediaDrmTestCases" />
-        <option name="dynamic-config-name" value="CtsMediaDrmTestCases" />
+        <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
+        <option name="dynamic-config-name" value="CtsMediaDrmFrameworkTestCases" />
         <option name="version" value="9.0_r1"/>
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
         <option name="push-all" value="true" />
-        <option name="media-folder-name" value="CtsMediaDrmTestCases-1.4" />
-        <option name="dynamic-config-module" value="CtsMediaDrmTestCases" />
+        <option name="media-folder-name" value="CtsMediaDrmFrameworkTestCases-1.0" />
+        <option name="dynamic-config-module" value="CtsMediaDrmFrameworkTestCases" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsMediaDrmTestCases.apk" />
+        <option name="test-file-name" value="CtsMediaDrmFrameworkTestCases.apk" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
-        <option name="run-command" value="pm revoke android.media.drm.cts android.permission.SYSTEM_ALERT_WINDOW"/>
+        <option name="run-command" value="pm revoke android.media.drmframework.cts android.permission.SYSTEM_ALERT_WINDOW"/>
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
         <option name="target" value="device" />
-        <option name="config-filename" value="CtsMediaDrmTestCases" />
+        <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
         <option name="version" value="7.0"/>
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.media.drm.cts" />
+        <option name="package" value="android.media.drmframework.cts" />
         <!-- setup can be expensive so limit the number of shards -->
         <option name="ajur-max-shard" value="5" />
         <!-- test-timeout unit is ms, value = 30 min -->
diff --git a/tests/tests/media/drm/DynamicConfig.xml b/tests/tests/media/drmframework/DynamicConfig.xml
similarity index 98%
rename from tests/tests/media/drm/DynamicConfig.xml
rename to tests/tests/media/drmframework/DynamicConfig.xml
index 942ab80..0795037 100644
--- a/tests/tests/media/drm/DynamicConfig.xml
+++ b/tests/tests/media/drmframework/DynamicConfig.xml
@@ -45,6 +45,6 @@
         <value>http://redirector.gvt1.com/videoplayback?id=c80658495af60617&amp;itag=17&amp;source=youtube&amp;ip=0.0.0.0&amp;ipbits=0&amp;expire=19000000000&amp;sparams=ip,ipbits,expire,id,itag,source&amp;signature=70E979A621001201BC18622BDBF914FA870BDA40.6E78890B80F4A33A18835F775B1FF64F0A4D0003&amp;key=ik0&amp;user=android-device-test</value>
     </entry>
     <entry key="media_files_url">
-    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/CtsMediaTestCases-1.4.zip</value>
+    <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/drmframework/CtsMediaDrmFrameworkTestCases-1.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/tests/tests/media/drm/OWNERS b/tests/tests/media/drmframework/OWNERS
similarity index 92%
rename from tests/tests/media/drm/OWNERS
rename to tests/tests/media/drmframework/OWNERS
index 09b0051..f20d2d9 100644
--- a/tests/tests/media/drm/OWNERS
+++ b/tests/tests/media/drmframework/OWNERS
@@ -3,7 +3,6 @@
 conglin@google.com
 edwinwong@google.com
 fredgc@google.com
-jtinker@google.com
 juce@google.com
 kylealexander@google.com
 mattfedd@google.com
diff --git a/tests/tests/media/drm/jni/AMediaObjects.h b/tests/tests/media/drmframework/jni/AMediaObjects.h
similarity index 100%
rename from tests/tests/media/drm/jni/AMediaObjects.h
rename to tests/tests/media/drmframework/jni/AMediaObjects.h
diff --git a/tests/tests/media/drm/jni/Android.bp b/tests/tests/media/drmframework/jni/Android.bp
similarity index 100%
rename from tests/tests/media/drm/jni/Android.bp
rename to tests/tests/media/drmframework/jni/Android.bp
diff --git a/tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp b/tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
similarity index 85%
rename from tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp
rename to tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
index 54b2dd5..935e8a6 100644
--- a/tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp
+++ b/tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
@@ -17,7 +17,7 @@
 #include <jni.h>
 #include <stdio.h>
 
-extern int register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(JNIEnv*);
+extern int registerNativeMediaDrmClearkeyTest(JNIEnv*);
 
 jint JNI_OnLoad(JavaVM *vm, void */*reserved*/) {
     JNIEnv *env = NULL;
@@ -26,7 +26,7 @@
         return JNI_ERR;
     }
 
-    if (register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(env)) {
+    if (registerNativeMediaDrmClearkeyTest(env)) {
         return JNI_ERR;
     }
 
diff --git a/tests/tests/media/drm/jni/native-mediadrm-jni.cpp b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
similarity index 94%
rename from tests/tests/media/drm/jni/native-mediadrm-jni.cpp
rename to tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
index 441d17a..40584b6 100644
--- a/tests/tests/media/drm/jni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
@@ -173,7 +173,7 @@
     return status;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative(
+extern "C" jboolean isCryptoSchemeSupportedNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
 
     if (NULL == uuid) {
@@ -205,7 +205,7 @@
         playbackParams, gFieldIds.videoUrl));
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative(
+extern "C" jboolean testGetPropertyStringNative(
     JNIEnv* env, jclass clazz, jbyteArray uuid,
     jstring name, jobject outValue) {
 
@@ -250,7 +250,7 @@
     return JNI_TRUE;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPropertyByteArrayNative(
+extern "C" jboolean testPropertyByteArrayNative(
         JNIEnv* env, jclass /* clazz */, jbyteArray uuid) {
 
     if (NULL == uuid) {
@@ -301,7 +301,7 @@
     return JNI_TRUE;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPsshNative(
+extern "C" jboolean testPsshNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jstring videoUrl) {
 
     if (NULL == uuid || NULL == videoUrl) {
@@ -686,7 +686,7 @@
     jniThrowExceptionFmt(env, "java/lang/RuntimeException", errorMessage.c_str(), status);
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative(
+extern "C" jboolean testClearKeyPlaybackNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
     if (NULL == uuid || NULL == playbackParams) {
         jniThrowException(env, "java/lang/NullPointerException",
@@ -826,7 +826,7 @@
     return JNI_TRUE;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative(
+extern "C" jboolean testQueryKeyStatusNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
 
     if (NULL == uuid) {
@@ -919,7 +919,7 @@
     return JNI_TRUE;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testFindSessionIdNative(
+extern "C" jboolean testFindSessionIdNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
 
     if (NULL == uuid) {
@@ -975,7 +975,7 @@
     return JNI_TRUE;
 }
 
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetKeyRequestNative(
+extern "C" jboolean testGetKeyRequestNative(
     JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
 
     if (NULL == uuid || NULL == playbackParams) {
@@ -1058,41 +1058,41 @@
 
 static JNINativeMethod gMethods[] = {
     { "isCryptoSchemeSupportedNative", "([B)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative },
+            (void *)isCryptoSchemeSupportedNative },
 
     { "testClearKeyPlaybackNative",
-            "([BLandroid/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative },
+            "([BLandroid/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
+            (void *)testClearKeyPlaybackNative },
 
     { "testGetPropertyStringNative",
             "([BLjava/lang/String;Ljava/lang/StringBuffer;)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative },
+            (void *)testGetPropertyStringNative },
 
     { "testPropertyByteArrayNative",
             "([B)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPropertyByteArrayNative },
+            (void *)testPropertyByteArrayNative },
 
     { "testPsshNative", "([BLjava/lang/String;)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPsshNative },
+            (void *)testPsshNative },
 
     { "testQueryKeyStatusNative", "([B)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative },
+            (void *)testQueryKeyStatusNative },
 
     { "testFindSessionIdNative", "([B)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testFindSessionIdNative },
+            (void *)testFindSessionIdNative },
 
     { "testGetKeyRequestNative",
-            "([BLandroid/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
-            (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetKeyRequestNative},
+            "([BLandroid/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
+            (void *)testGetKeyRequestNative},
 };
 
-int register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(JNIEnv* env) {
+int registerNativeMediaDrmClearkeyTest(JNIEnv* env) {
     jint result = JNI_ERR;
     jclass testClass =
-        env->FindClass("android/media/drm/cts/NativeMediaDrmClearkeyTest");
+        env->FindClass("android/media/drmframework/cts/NativeMediaDrmClearkeyTest");
     if (testClass) {
         jclass playbackParamsClass = env->FindClass(
-            "android/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams");
+            "android/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams");
         if (playbackParamsClass) {
             jclass surfaceClass =
                 env->FindClass("android/view/Surface");
diff --git a/tests/tests/media/drm/res/raw/segment000001.ts b/tests/tests/media/drmframework/res/raw/segment000001.ts
similarity index 100%
rename from tests/tests/media/drm/res/raw/segment000001.ts
rename to tests/tests/media/drmframework/res/raw/segment000001.ts
Binary files differ
diff --git a/tests/tests/media/drm/res/raw/segment000001_scrambled.ts b/tests/tests/media/drmframework/res/raw/segment000001_scrambled.ts
similarity index 100%
rename from tests/tests/media/drm/res/raw/segment000001_scrambled.ts
rename to tests/tests/media/drmframework/res/raw/segment000001_scrambled.ts
Binary files differ
diff --git a/tests/tests/media/drm/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm b/tests/tests/media/drmframework/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
similarity index 100%
rename from tests/tests/media/drm/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
rename to tests/tests/media/drmframework/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
Binary files differ
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
similarity index 96%
rename from tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
index db6ec49..915d561 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.DrmInitData;
 import android.media.cts.NonMediaMainlineTest;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index 1fc248f..1a1a46f 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.MediaCodecInfo.CodecCapabilities;
 import android.media.MediaDrm;
@@ -107,11 +107,11 @@
     private static final String CENC_AUDIO_PATH = "/clear/h264/llama/llama_aac_audio.mp4";
     private static final String CENC_VIDEO_PATH = "/clearkey/llama_h264_main_720p_8000.mp4";
     private static final Uri WEBM_URL = Uri.parse(
-            "android.resource://android.media.drm.cts/" + R.raw.video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt);
+            "android.resource://android.media.drmframework.cts/" + R.raw.video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt);
     private static final Uri MPEG2TS_SCRAMBLED_URL = Uri.parse(
-            "android.resource://android.media.drm.cts/" + R.raw.segment000001_scrambled);
+            "android.resource://android.media.drmframework.cts/" + R.raw.segment000001_scrambled);
     private static final Uri MPEG2TS_CLEAR_URL = Uri.parse(
-            "android.resource://android.media.drm.cts/" + R.raw.segment000001);
+            "android.resource://android.media.drmframework.cts/" + R.raw.segment000001);
 
     private static final UUID COMMON_PSSH_SCHEME_UUID =
             new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
index ebb6629..2555bff 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.content.res.AssetFileDescriptor;
 import android.media.MediaDrm;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
index 2fb107e..38b1d37 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.MediaCodec;
 import android.media.MediaCodec.CryptoException;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
similarity index 98%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
index eca036b..e7ac382 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.DrmInitData;
 
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
index 3f8de70..c9494aa 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
index 35130aa..4e4a4eb 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.MediaDrm;
 import android.media.MediaDrm.CryptoSession;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
index 5dacfee..1bb5646 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.MediaCrypto;
 import android.media.MediaCryptoException;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
similarity index 98%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
index deaef06..944595a 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
index c2bce4f..45bcd3e 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.app.DownloadManager;
 import android.app.DownloadManager.Request;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
index f80ebda..0bb09ca 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.content.pm.PackageManager;
 import android.media.MediaDrm;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
similarity index 86%
rename from tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
index 7f6a1b8..5636d63 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package android.media.drm.cts;
+package android.media.drmframework.cts;
 
 import android.media.cts.WorkDirBase;
 
 class WorkDir extends WorkDirBase {
     public static final String getMediaDirString() {
-        return getMediaDirString("CtsMediaDrmTestCases-1.4");
+        return getMediaDirString("CtsMediaDrmFrameworkTestCases-1.0");
     }
 }
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
index c76d150..d38f767 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
@@ -198,7 +198,7 @@
     public void testAllowedPackages() throws Exception {
         RouteDiscoveryPreference preference =
                 new RouteDiscoveryPreference.Builder(FEATURES_ALL, true)
-                        .setAllowedPackages(List.of("android.media.cts"))
+                        .setAllowedPackages(List.of("android.media.misc.cts"))
                         .build();
         Map<String, MediaRoute2Info> routes = waitAndGetRoutes(preference);
 
@@ -591,11 +591,11 @@
 
         try {
             mRouter2.registerTransferCallback(mExecutor, transferCallback);
-            mRouter2.transferTo(route);
-
             // Unregisters transfer callback
             mRouter2.unregisterTransferCallback(transferCallback);
 
+            mRouter2.transferTo(route);
+
             // No transfer callback methods should be called.
             assertFalse(successLatch.await(WAIT_MS, TimeUnit.MILLISECONDS));
             assertFalse(failureLatch.await(WAIT_MS, TimeUnit.MILLISECONDS));
diff --git a/tests/tests/os/src/android/os/cts/ProcessTest.java b/tests/tests/os/src/android/os/cts/ProcessTest.java
index ebffb79..8ca7811 100644
--- a/tests/tests/os/src/android/os/cts/ProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ProcessTest.java
@@ -16,7 +16,11 @@
 
 package android.os.cts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -24,15 +28,24 @@
 import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.Process;
-import android.test.AndroidTestCase;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
 /**
  * CTS for {@link android.os.Process}.
  *
  * We have more test in cts/tests/process/ too.
  */
-public class ProcessTest extends AndroidTestCase {
+@RunWith(JUnit4.class)
+public class ProcessTest {
 
     public static final int THREAD_PRIORITY_HIGHEST = -20;
     private static final String NONE_EXISITENT_NAME = "abcdefcg";
@@ -40,6 +53,8 @@
     private static final String PROCESS_SHELL= "shell";
     private static final String PROCESS_CACHE= "cache";
     private static final String REMOTE_SERVICE = "android.app.REMOTESERVICE";
+    private static final int APP_UID = 10001;
+    private static final int SANDBOX_SDK_UID = 20001;
     private static final String TAG = "ProcessTest";
     private ISecondary mSecondaryService = null;
     private Intent mIntent;
@@ -47,10 +62,11 @@
     private boolean mHasConnected;
     private boolean mHasDisconnected;
     private ServiceConnection mSecondaryConnection;
+    private Context mContext;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
         mSync = new Object();
         mSecondaryConnection = new ServiceConnection() {
             public void onServiceConnected(ComponentName className,
@@ -74,12 +90,12 @@
             }
         };
         mIntent = new Intent(REMOTE_SERVICE);
-        mIntent.setPackage(getContext().getPackageName());
-        getContext().startService(mIntent);
+        mIntent.setPackage(mContext.getPackageName());
+        mContext.startService(mIntent);
 
         Intent secondaryIntent = new Intent(ISecondary.class.getName());
-        secondaryIntent.setPackage(getContext().getPackageName());
-        getContext().bindService(secondaryIntent, mSecondaryConnection,
+        secondaryIntent.setPackage(mContext.getPackageName());
+        mContext.bindService(secondaryIntent, mSecondaryConnection,
                 Context.BIND_AUTO_CREATE);
         synchronized (mSync) {
             if (!mHasConnected) {
@@ -91,17 +107,17 @@
         }
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @After
+    public void tearDown() throws Exception {
         if (mIntent != null) {
-            getContext().stopService(mIntent);
+            mContext.stopService(mIntent);
         }
         if (mSecondaryConnection != null) {
-            getContext().unbindService(mSecondaryConnection);
+            mContext.unbindService(mSecondaryConnection);
         }
     }
 
+    @Test
     public void testMiscMethods() {
         /*
          * Test setThreadPriority(int) and setThreadPriority(int, int)
@@ -163,6 +179,7 @@
      * Only the process running the caller's packages/application
      * and any additional processes created by that app be able to kill each other's processes.
      */
+    @Test
     public void testKillProcess() throws Exception {
         long time = 0;
         int servicePid = 0;
@@ -170,7 +187,7 @@
             servicePid = mSecondaryService.getPid();
             time = mSecondaryService.getElapsedCpuTime();
         } finally {
-            getContext().stopService(mIntent);
+            mContext.stopService(mIntent);
             mIntent = null;
         }
 
@@ -196,12 +213,13 @@
      * Test sendSignal(int) point.
      * Send a signal to the given process.
      */
+    @Test
     public void testSendSignal() throws Exception {
         int servicePid = 0;
         try {
             servicePid = mSecondaryService.getPid();
         } finally {
-            getContext().stopService(mIntent);
+            mContext.stopService(mIntent);
             mIntent = null;
         }
         assertTrue(servicePid != 0);
@@ -217,4 +235,18 @@
         }
         assertTrue(mHasDisconnected);
     }
+
+    /**
+     * Tests APIs related to sdk sandbox uids.
+     */
+    @Test
+    public void testSdkSandboxUids() {
+        assertEquals(SANDBOX_SDK_UID, Process.toSdkSandboxUid(APP_UID));
+        assertEquals(APP_UID, Process.sdkSandboxToAppUid(SANDBOX_SDK_UID));
+
+        assertFalse(Process.isSdkSandboxUid(APP_UID));
+        assertTrue(Process.isSdkSandboxUid(SANDBOX_SDK_UID));
+
+        assertFalse(Process.isSdkSandbox());
+    }
 }
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 28ffcd3..c26ab8d 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -6862,10 +6862,6 @@
                     android:resource="@xml/autofill_compat_accessibility_service" />
         </service>
 
-        <service android:name="com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy"
-                 android:permission="android.permission.BIND_JOB_SERVICE" >
-        </service>
-
         <service android:name="com.android.server.blob.BlobStoreIdleJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index 4117a78..d37ff8b 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -16,20 +16,26 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-     package="com.android.car"
-     coreApp="true"
-     android:sharedUserId="android.uid.system">
+     package="com.android.car.updatable" >
 
-    <original-package android:name="com.android.car"/>
-     <permission-group android:name="android.car.permission-group.CAR_MONITORING"
-          android:icon="@drawable/perm_group_car"
-          android:description="@string/car_permission_desc"
-          android:label="@string/car_permission_label"/>
+    <permission-group android:name="android.car.permission-group.CAR_MONITORING"
+         android:icon="@drawable/perm_group_car"
+         android:description="@string/car_permission_desc"
+         android:label="@string/car_permission_label"/>
     <permission android:name="android.car.permission.CAR_ENERGY"
          android:permissionGroup="android.car.permission-group.CAR_MONITORING"
          android:protectionLevel="dangerous"
          android:label="@string/car_permission_label_energy"
          android:description="@string/car_permission_desc_energy"/>
+    <permission android:name="android.car.permission.CONTROL_CAR_ENERGY"
+                android:permissionGroup="android.car.permission-group.CAR_MONITORING"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_control_car_energy"
+                android:description="@string/car_permission_desc_control_car_energy"/>
+    <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_adjust_range_remaining"
+         android:description="@string/car_permission_desc_adjust_range_remaining"/>
     <permission android:name="android.car.permission.CAR_IDENTIFICATION"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_identification"
@@ -83,6 +89,10 @@
          android:protectionLevel="normal"
          android:label="@string/car_permission_label_car_energy_ports"
          android:description="@string/car_permission_desc_car_energy_ports"/>
+    <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_control_car_energy_ports"
+         android:description="@string/car_permission_desc_control_car_energy_ports"/>
     <permission android:name="android.car.permission.CAR_ENGINE_DETAILED"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_engine_detailed"
@@ -115,10 +125,31 @@
          android:protectionLevel="normal"
          android:label="@string/car_permission_label_car_info"
          android:description="@string/car_permission_desc_car_info"/>
+    <permission android:name="android.car.permission.PRIVILEGED_CAR_INFO"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_privileged_car_info"
+                android:description="@string/car_permission_desc_privileged_car_info"/>
+    <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_vendor_permission_info"
+         android:description="@string/car_permission_desc_vendor_permission_info"/>
+
+    <!-- Allows an application to read the vehicle exterior environment information. For example,
+         it allows an application to read the vehicle exterior temperature and night mode status.
+         <p>Protection level: normal
+    -->
     <permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
          android:protectionLevel="normal"
          android:label="@string/car_permission_label_car_exterior_environment"
          android:description="@string/car_permission_desc_car_exterior_environment"/>
+    <permission android:name="android.car.permission.CAR_EPOCH_TIME"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_car_epoch_time"
+                android:description="@string/car_permission_desc_car_epoch_time"/>
+    <permission android:name="android.car.permission.STORAGE_ENCRYPTION_BINDING_SEED"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_encryption_binding_seed"
+                android:description="@string/car_permission_desc_encryption_binding_seed"/>
     <permission android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_exterior_lights"
@@ -171,385 +202,276 @@
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_driving_state"
          android:description="@string/car_permission_desc_driving_state"/>
-    <!--  may replace this with system permission if proper one is defined. -->
+    <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_use_telemetry_service"
+                android:description="@string/car_permission_desc_use_telemetry_service"/>
+    <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_request_evs_activity"
+                android:description="@string/car_permission_desc_request_evs_activity"/>
+    <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_control_evs_activity"
+                android:description="@string/car_permission_desc_control_evs_activity"/>
+    <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_use_evs_camera"
+                android:description="@string/car_permission_desc_use_evs_camera"/>
+    <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_monitor_evs_status"
+                android:description="@string/car_permission_desc_monitor_evs_status"/>
     <permission android:name="android.car.permission.CONTROL_APP_BLOCKING"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_control_app_blocking"
          android:description="@string/car_permission_desc_control_app_blocking"/>
-    <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_adjust_range_remaining"
-         android:description="@string/car_permission_desc_adjust_range_remaining"/>
-    <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_read_car_occupant_awareness_state"
-         android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
-    <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_control_car_energy_ports"
-         android:description="@string/car_permission_desc_control_car_energy_ports"/>
-    <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_control_car_occupant_awareness_system"
-         android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
-    <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_control_car_features"
-         android:description="@string/car_permission_desc_control_car_features"/>
-    <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_use_car_watchdog"
-         android:description="@string/car_permission_desc_use_car_watchdog"/>
-    <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_vendor_permission_info"
-         android:description="@string/car_permission_desc_vendor_permission_info"/>
-    <!-- Permission for vendor properties -->
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_window"
-         android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_window"
-         android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_door"
-         android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_door"
-         android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_seat"
-         android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_seat"
-         android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_mirror"
-         android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_mirror"
-         android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_info"
-         android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_info"
-         android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_engine"
-         android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_engine"
-         android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_hvac"
-         android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_hvac"
-         android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_light"
-         android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_light"
-         android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_1"
-         android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_1"
-         android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_2"
-         android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_2"
-         android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_3"
-         android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_3"
-         android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_4"
-         android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_4"
-         android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_5"
-         android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_5"
-         android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_6"
-         android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_6"
-         android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_7"
-         android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_7"
-         android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_8"
-         android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_8"
-         android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_9"
-         android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_9"
-         android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
-    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_get_car_vendor_category_10"
-         android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
-    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
-         android:protectionLevel="signature|privileged"
-         android:label="@string/car_permission_label_set_car_vendor_category_10"
-         android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
-
     <permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_audio_volume"
          android:description="@string/car_permission_desc_audio_volume"/>
-
     <permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_audio_settings"
          android:description="@string/car_permission_desc_audio_settings"/>
-
     <permission android:name="android.car.permission.RECEIVE_CAR_AUDIO_DUCKING_EVENTS"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_receive_ducking"
          android:description="@string/car_permission_desc_receive_ducking"/>
-
     <permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"
          android:protectionLevel="signature"
          android:label="@string/car_permission_label_bind_instrument_cluster_rendering"
          android:description="@string/car_permission_desc_bind_instrument_cluster_rendering"/>
-
     <permission android:name="android.car.permission.BIND_CAR_INPUT_SERVICE"
          android:protectionLevel="signature"
          android:label="@string/car_permission_label_bind_input_service"
          android:description="@string/car_permission_desc_bind_input_service"/>
-
     <permission android:name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_car_display_in_cluster"
          android:description="@string/car_permission_desc_car_display_in_cluster"/>
-
     <permission android:name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_car_cluster_control"
          android:description="@string/car_permission_desc_car_cluster_control"/>
-
     <permission android:name="android.car.permission.CAR_MONITOR_CLUSTER_NAVIGATION_STATE"
-        android:protectionLevel="signature|privileged"
+        android:protectionLevel="system|signature"
         android:label="@string/car_permission_car_monitor_cluster_navigation_state"
         android:description="@string/car_permission_desc_car_monitor_cluster_navigation_state"/>
-
     <permission android:name="android.car.permission.CAR_HANDLE_USB_AOAP_DEVICE"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_handle_usb_aoap_device"
          android:description="@string/car_permission_desc_car_handle_usb_aoap_device"/>
-
     <permission android:name="android.car.permission.CAR_UX_RESTRICTIONS_CONFIGURATION"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_ux_restrictions_configuration"
          android:description="@string/car_permission_desc_car_ux_restrictions_configuration"/>
-
+    <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_read_car_occupant_awareness_state"
+         android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
+    <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_access_private_display_id"
+                android:description="@string/car_permission_desc_access_private_display_id"/>
+    <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_control_car_occupant_awareness_system"
+         android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
     <permission android:name="android.car.permission.STORAGE_MONITORING"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_storage_monitoring"
          android:description="@string/car_permission_desc_storage_monitoring"/>
-
     <permission android:name="android.car.permission.CAR_ENROLL_TRUST"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_enroll_trust"
          android:description="@string/car_permission_desc_enroll_trust"/>
-
     <permission android:name="android.car.permission.CAR_TEST_SERVICE"
          android:protectionLevel="system|signature"
          android:label="@string/car_permission_label_car_test_service"
          android:description="@string/car_permission_desc_car_test_service"/>
-
-    <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_access_private_display_id"
-        android:description="@string/car_permission_desc_access_private_display_id"/>
-
-    <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_monitor_evs_status"
-        android:description="@string/car_permission_desc_monitor_evs_status"/>
-
-    <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_control_car_power_policy"
-        android:description="@string/car_permission_desc_control_car_power_policy"/>
-
-    <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_collect_car_watchdog_metrics"
-        android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
-
-    <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_use_telemetry_service"
-        android:description="@string/car_permission_desc_use_telemetry_service"/>
-
-    <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_control_evs_activity"
-        android:description="@string/car_permission_desc_control_evs_activity"/>
-
-    <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_request_evs_activity"
-        android:description="@string/car_permission_desc_request_evs_activity"/>
-
-    <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_use_evs_camera"
-        android:description="@string/car_permission_desc_use_evs_camera"/>
-
-    <permission android:name="android.car.permission.STORAGE_ENCRYPTION_BINDING_SEED"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_encryption_binding_seed"
-        android:description="@string/car_permission_desc_encryption_binding_seed"/>
-
-    <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
-        android:protectionLevel="normal"
-        android:label="@string/car_permission_label_read_car_power_policy"
-        android:description="@string/car_permission_desc_read_car_power_policy"/>
-
-    <permission android:name="android.car.permission.CAR_EPOCH_TIME"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_car_epoch_time"
-        android:description="@string/car_permission_desc_car_epoch_time"/>
-
+    <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_control_car_features"
+         android:description="@string/car_permission_desc_control_car_features"/>
+    <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_use_car_watchdog"
+         android:description="@string/car_permission_desc_use_car_watchdog"/>
     <permission android:name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_control_car_watchdog_config"
-        android:description="@string/car_permission_desc_control_car_watchdog_config"/>
-
-    <permission android:name="android.car.permission.TEMPLATE_RENDERER"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_template_renderer"
-        android:description="@string/car_permission_desc_template_renderer"/>
-
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_control_car_watchdog_config"
+         android:description="@string/car_permission_desc_control_car_watchdog_config"/>
+    <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_collect_car_watchdog_metrics"
+         android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_window"
+         android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_window"
+         android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_door"
+         android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_door"
+         android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_seat"
+         android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_seat"
+         android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_mirror"
+         android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_mirror"
+         android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_info"
+         android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_info"
+         android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_engine"
+         android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_engine"
+         android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_hvac"
+         android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_hvac"
+         android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_light"
+         android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_light"
+         android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_1"
+         android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_1"
+         android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_2"
+         android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_2"
+         android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_3"
+         android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_3"
+         android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_4"
+         android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_4"
+         android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_5"
+         android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_5"
+         android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_6"
+         android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_6"
+         android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_7"
+         android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_7"
+         android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_8"
+         android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_8"
+         android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_9"
+         android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_9"
+         android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
+    <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_get_car_vendor_category_10"
+         android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
+    <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
+         android:protectionLevel="system|signature"
+         android:label="@string/car_permission_label_set_car_vendor_category_10"
+         android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
     <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
-        android:protectionLevel="signature|privileged"
-        android:label="@string/car_permission_label_monitor_input"
-        android:description="@string/car_permission_desc_monitor_input"/>
-
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_monitor_input"
+                android:description="@string/car_permission_desc_monitor_input"/>
+    <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
+                android:protectionLevel="normal"
+                android:label="@string/car_permission_label_read_car_power_policy"
+                android:description="@string/car_permission_desc_read_car_power_policy"/>
+    <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_control_car_power_policy"
+                android:description="@string/car_permission_desc_control_car_power_policy"/>
+    <permission android:name="android.car.permission.CONTROL_SHUTDOWN_PROCESS"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_adjust_shutdown_process"
+                android:description="@string/car_permission_desc_adjust_shutdown_process"/>
+    <permission android:name="android.car.permission.TEMPLATE_RENDERER"
+                android:protectionLevel="system|signature"
+                android:label="@string/car_permission_label_template_renderer"
+                android:description="@string/car_permission_desc_template_renderer"/>
     <permission android:name="android.car.permission.CONTROL_CAR_APP_LAUNCH"
-        android:protectionLevel="signature|privileged"
+        android:protectionLevel="system|signature"
         android:label="@string/car_permission_label_control_car_app_launch"
         android:description="@string/car_permission_desc_control_car_app_launch"/>
-
-    <uses-permission android:name="android.permission.CALL_PHONE"/>
-    <uses-permission android:name="android.permission.DEVICE_POWER"/>
-    <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"/>
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
-    <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
-    <uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
-    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
-    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
-    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
-    <uses-permission android:name="android.permission.REAL_GET_TASKS"/>
-    <uses-permission android:name="android.permission.REBOOT"/>
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
-    <uses-permission android:name="android.permission.REMOVE_TASKS"/>
-    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
-    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
-    <uses-permission android:name="android.permission.BLUETOOTH"/>
-    <uses-permission android:name="android.permission.MANAGE_USERS"/>
-    <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-    <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT"/>
-
-    <application android:label="@string/app_title"
-         android:directBootAware="true"
-         android:allowBackup="false"
-         android:persistent="true">
-
-        <uses-library android:name="android.test.runner"/>
-        <service android:name=".CarService"
-             android:singleUser="true"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.car.ICar"/>
-            </intent-filter>
-        </service>
-        <service android:name=".PerUserCarService"
-             android:exported="false"/>
-
-        <service android:name="com.android.car.trust.CarBleTrustAgent"
-             android:permission="android.permission.BIND_TRUST_AGENT"
-             android:singleUser="true"
-             android:exported="true">
-            <intent-filter>
-                <action android:name="android.service.trust.TrustAgentService"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-            </intent-filter>
-            <!-- Warning: the meta data must be included if the service is direct boot aware.
-                                If not included, the device will crash before boot completes. Rendering the
-                                device unusable. -->
-            <meta-data android:name="android.service.trust.trustagent"
-                 android:resource="@xml/car_trust_agent"/>
-        </service>
-        <activity android:name="com.android.car.pm.ActivityBlockingActivity"
-             android:excludeFromRecents="true"
-             android:theme="@android:style/Theme.Translucent.NoTitleBar"
-             android:exported="false"
-             android:launchMode="singleTask">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-            </intent-filter>
-        </activity>
-    </application>
 </manifest>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index a7c46f1..edfcf3a 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -30,6 +30,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.os.Process;
+import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -76,8 +77,6 @@
 
     private static final String PLATFORM_ROOT_NAMESPACE = "android.";
 
-    private static final String AUTOMOTIVE_SERVICE_PACKAGE_NAME = "com.android.car";
-
     private static final String TAG_PERMISSION = "permission";
     private static final String TAG_PERMISSION_GROUP = "permission-group";
 
@@ -123,8 +122,14 @@
 
         if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
             expectedPermissions.addAll(loadExpectedPermissions(R.raw.automotive_android_manifest));
+            String carServicePackageName = SystemProperties.get("ro.android.car.carservice.package",
+                    null);
+
+            assertWithMessage("Car service package not defined").that(
+                    carServicePackageName).isNotNull();
+
             declaredPermissionsMap.putAll(
-                    getPermissionsForPackage(sContext, AUTOMOTIVE_SERVICE_PACKAGE_NAME));
+                    getPermissionsForPackage(sContext, carServicePackageName));
         }
 
         for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
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 9e09ad1..457549f 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
@@ -28,8 +28,9 @@
 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_PERMISSIONS = "extra_request_permissions"
-const val EXTRA_REQUEST_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
 const val CHANNEL_ID = "channel_id"
 const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
 const val DELAY_MS = 1000L
@@ -53,13 +54,17 @@
             }, DELAY_MS)
         }
 
-        if (intent.getBooleanExtra(EXTRA_REQUEST_PERMISSIONS, false)) {
+        if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
             requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
-        } else if (intent.getBooleanExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, false)) {
+        } else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
             handler.postDelayed({
                 requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
             }, DELAY_MS)
         }
+
+        if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
+            requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
+        }
         super.onStart()
     }
 
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index dc83cd2..ebdc507 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -22,6 +22,7 @@
 import android.content.Intent
 import android.content.pm.PackageManager
 import android.net.Uri
+import android.os.Build
 import android.provider.Settings
 import android.support.test.uiautomator.By
 import android.support.test.uiautomator.BySelector
@@ -31,6 +32,7 @@
 import android.text.style.ClickableSpan
 import android.view.View
 import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.modules.utils.build.SdkLevel
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -96,11 +98,21 @@
         const val ASK_BUTTON_TEXT = "app_permission_button_ask"
         const val ALLOW_ONE_TIME_BUTTON_TEXT = "grant_dialog_button_allow_one_time"
         const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
+        const val DENY_ANYWAY_BUTTON_TEXT = "grant_dialog_button_deny_anyway"
         const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
                 "grant_dialog_button_deny_and_dont_ask_again"
         const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT = "grant_dialog_button_no_upgrade"
 
         const val REQUEST_LOCATION_MESSAGE = "permgrouprequest_location"
+
+        val STORAGE_AND_MEDIA_PERMISSIONS = setOf(
+            android.Manifest.permission.READ_EXTERNAL_STORAGE,
+            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+            android.Manifest.permission.ACCESS_MEDIA_LOCATION,
+            android.Manifest.permission.READ_MEDIA_AUDIO,
+            android.Manifest.permission.READ_MEDIA_IMAGE,
+            android.Manifest.permission.READ_MEDIA_VIDEO
+        )
     }
 
     enum class PermissionState {
@@ -165,7 +177,15 @@
             android.Manifest.permission.BLUETOOTH_CONNECT to
                     "@android:string/permgrouplab_nearby_devices",
             android.Manifest.permission.BLUETOOTH_SCAN to
-                    "@android:string/permgrouplab_nearby_devices"
+                    "@android:string/permgrouplab_nearby_devices",
+            // Aural
+            android.Manifest.permission.READ_MEDIA_AUDIO to
+                "@android:string/permgrouplab_readMediaAural",
+            // Visual
+            android.Manifest.permission.READ_MEDIA_IMAGE to
+                "@android:string/permgrouplab_readMediaVisual",
+            android.Manifest.permission.READ_MEDIA_VIDEO to
+                "@android:string/permgrouplab_readMediaVisual"
     )
 
     @Before
@@ -315,8 +335,8 @@
      */
     protected fun clickNotificationPermissionRequestAllowButton() {
         if (waitFindObjectOrNull(By.text(getPermissionControllerString(
-                NOTIF_CONTINUE_TEXT, APP_PACKAGE_NAME)), 1000) != null
-                || waitFindObjectOrNull(By.text(getPermissionControllerString(
+                NOTIF_CONTINUE_TEXT, APP_PACKAGE_NAME)), 1000) != null ||
+                waitFindObjectOrNull(By.text(getPermissionControllerString(
                         NOTIF_TEXT, APP_PACKAGE_NAME)), 1000) != null) {
             if (isAutomotive) {
                 click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
@@ -558,7 +578,15 @@
             if (!alreadyChecked) {
                 button.click()
             }
-            if (!alreadyChecked && isLegacyApp && wasGranted) {
+
+            val shouldShowStorageWarning = !isTv && !isWatch &&
+                SdkLevel.isAtLeastT() && targetSdk <= Build.VERSION_CODES.S_V2 &&
+                permission in STORAGE_AND_MEDIA_PERMISSIONS
+            if (shouldShowStorageWarning && state == PermissionState.ALLOWED) {
+                click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+            } else if (shouldShowStorageWarning && state == PermissionState.DENIED) {
+                click(By.text(getPermissionControllerString(DENY_ANYWAY_BUTTON_TEXT)))
+            } else if (!alreadyChecked && isLegacyApp && wasGranted) {
                 if (!isTv) {
                     scrollToBottom()
                 }
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index 853bc10..2e5baf5 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -45,7 +45,8 @@
 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_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
 const val EXTRA_REQUEST_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
 const val ACTIVITY_NAME = "CreateNotificationChannelsActivity"
 const val ACTIVITY_LABEL = "CreateNotif"
@@ -337,6 +338,18 @@
         waitFindObject(By.textContains(ALLOW))
     }
 
+    @Test
+    fun legacyAppCannotExplicitlyRequestNotifications() {
+        installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+        launchApp(createChannels = false, requestNotificationPermission = true)
+        try {
+            clickPermissionRequestAllowButton()
+            Assert.fail("Expected not to find permission request dialog")
+        } catch (expected: RuntimeException) {
+            // Do nothing
+        }
+    }
+
     private fun assertAppPermissionGrantedState(permission: String, granted: Boolean) {
         SystemUtil.eventually {
             runWithShellPermissionIdentity {
@@ -371,6 +384,7 @@
         createChannels: Boolean = true,
         createChannelsDelayed: Boolean = false,
         deleteChannels: Boolean = false,
+        requestNotificationPermission: Boolean = false,
         requestPermissions: Boolean = false,
         requestPermissionsDelayed: Boolean = false,
         launcherCategory: Boolean = true,
@@ -391,10 +405,11 @@
             intent.putExtra(EXTRA_CREATE_CHANNELS_DELAYED, createChannelsDelayed)
         }
         intent.putExtra(EXTRA_DELETE_CHANNELS_ON_CLOSE, deleteChannels)
-        intent.putExtra(EXTRA_REQUEST_PERMISSIONS, requestPermissions)
+        intent.putExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, requestPermissions)
         if (!requestPermissions) {
             intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, requestPermissionsDelayed)
         }
+        intent.putExtra(EXTRA_REQUEST_NOTIF_PERMISSION, requestNotificationPermission)
         intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
 
         val options = ActivityOptions.makeBasic()
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt
new file mode 100644
index 0000000..86dd1e8
--- /dev/null
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.os.Build
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests media storage supergroup behavior. I.e., on a T+ platform, for legacy (targetSdk<T) apps,
+ * the storage permission groups (STORAGE, AURAL, and VISUAL) form a supergroup, which effectively
+ * treats them as one group and therefore their permission state must always be equal.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class PermissionTestMediaPermissions : BaseUsePermissionTest() {
+    private fun assertAllPermissionState(state: Boolean) {
+        for (permission in STORAGE_AND_MEDIA_PERMISSIONS) {
+            assertAppHasPermission(permission, state)
+        }
+    }
+
+    @Before
+    fun assumeNotTvOrWatch() {
+        assumeFalse(isTv)
+        assumeFalse(isWatch)
+    }
+
+    @Before
+    fun installApp23() {
+        installPackage(APP_APK_PATH_23)
+    }
+
+    @Before
+    fun assertAppStartsWithNoPermissions() {
+        assertAllPermissionState(false)
+    }
+
+    @Test
+    fun testWhenRESIsGrantedFromGrantDialogThenShouldGrantAllPermissions() {
+        requestAppPermissionsAndAssertResult(
+            android.Manifest.permission.READ_EXTERNAL_STORAGE to true
+        ) {
+            clickPermissionRequestAllowButton()
+        }
+        assertAllPermissionState(true)
+    }
+
+    @Test
+    fun testWhenRESIsGrantedManuallyThenShouldGrantAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+        assertAllPermissionState(true)
+    }
+
+    @Test
+    fun testWhenAuralIsGrantedManuallyThenShouldGrantAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+        assertAllPermissionState(true)
+    }
+
+    @Test
+    fun testWhenVisualIsGrantedManuallyThenShouldGrantAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+        assertAllPermissionState(true)
+    }
+
+    @Test
+    fun testWhenRESIsDeniedFromGrantDialogThenShouldDenyAllPermissions() {
+        requestAppPermissionsAndAssertResult(
+            android.Manifest.permission.READ_EXTERNAL_STORAGE to false
+        ) {
+            clickPermissionRequestDenyButton()
+        }
+        assertAllPermissionState(false)
+    }
+
+    @Test
+    fun testWhenRESIsDeniedManuallyThenShouldDenyAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+        revokeAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+        assertAllPermissionState(false)
+    }
+
+    @Test
+    fun testWhenAuralIsDeniedManuallyThenShouldDenyAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+        revokeAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+        assertAllPermissionState(false)
+    }
+
+    @Test
+    fun testWhenVisualIsDeniedManuallyThenShouldDenyAllPermissions() {
+        grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+        revokeAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+        assertAllPermissionState(false)
+    }
+}
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 37e9d41..72f1de1 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -21,9 +21,11 @@
 import android.hardware.SensorPrivacyManager.Sensors.CAMERA
 import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
 import android.location.LocationManager
+import android.Manifest.permission_group.CAMERA as CAMERA_PERMISSION_GROUP
+import android.Manifest.permission_group.LOCATION as LOCATION_PERMISSION_GROUP
+import android.Manifest.permission_group.MICROPHONE as MICROPHONE_PERMISSION_GROUP
 import android.os.Build
 import android.provider.DeviceConfig
-import android.provider.Settings
 import android.support.test.uiautomator.By
 import androidx.test.filters.SdkSuppress
 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
@@ -31,6 +33,7 @@
 import org.junit.After
 import org.junit.Assume
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 
 /**
@@ -50,9 +53,9 @@
                 WARNING_BANNER_ENABLED, false.toString())
     }
 
-    private val permToLabel = mapOf(CAMERA to "privdash_label_camera",
-            MICROPHONE to "privdash_label_microphone",
-            LOCATION to "privdash_label_location")
+    private val sensorToPermissionGroup = mapOf(CAMERA to CAMERA_PERMISSION_GROUP,
+            MICROPHONE to MICROPHONE_PERMISSION_GROUP,
+            LOCATION to LOCATION_PERMISSION_GROUP)
 
     private val permToTitle = mapOf(CAMERA to "blocked_camera_title",
             MICROPHONE to "blocked_microphone_title",
@@ -80,17 +83,16 @@
     }
 
     private fun navigateAndTest(sensor: Int) {
-        val permLabel = permToLabel.getOrDefault(sensor, "Break")
-        val intent = Intent(Settings.ACTION_PRIVACY_SETTINGS)
+        val permissionGroup = sensorToPermissionGroup.getOrDefault(sensor, "Break")
+        val intent = Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+                .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroup)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-        context.startActivity(intent)
-        click(By.text(getPermissionControllerString("app_permission_manager")))
-        click(By.text(getPermissionControllerString(permLabel)))
+        runWithShellPermissionIdentity {
+            context.startActivity(intent)
+        }
         val bannerTitle = permToTitle.getOrDefault(sensor, "Break")
         waitFindObject(By.text(getPermissionControllerString(bannerTitle)))
         pressBack()
-        pressBack()
-        pressBack()
     }
 
     private fun runSensorTest(sensor: Int) {
@@ -117,6 +119,7 @@
     }
 
     @Test
+    @Ignore
     fun testLocationCardDisplayed() {
         runSensorTest(LOCATION)
     }
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
index 019832d..090554b 100644
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
+++ b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
@@ -10,7 +10,7 @@
                 summary="@string/reference"
                 intentAction="intent"
                 profile="primary_profile_only"
-                allowLogging="false"/>
+                loggingAllowed="false"/>
         </safety-sources-group>
     </safety-sources-config>
 </safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
index 5e46a44..caaeee6 100644
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
+++ b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
@@ -10,7 +10,7 @@
                 summary="@string/reference"
                 intentAction="intent"
                 profile="primary_profile_only"
-                allowRefreshOnPageOpen="true"/>
+                refreshOnPageOpenAllowed="true"/>
         </safety-sources-group>
     </safety-sources-config>
 </safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_valid.xml b/tests/tests/safetycenter/res/xml/config_valid.xml
index dfb0469..e2f9e77 100644
--- a/tests/tests/safetycenter/res/xml/config_valid.xml
+++ b/tests/tests/safetycenter/res/xml/config_valid.xml
@@ -24,8 +24,8 @@
                 maxSeverityLevel="300"
                 searchTerms="@string/reference"
                 broadcastReceiverClassName="broadcast"
-                allowLogging="false"
-                allowRefreshOnPageOpen="true"/>
+                loggingAllowed="false"
+                refreshOnPageOpenAllowed="true"/>
             <dynamic-safety-source
                 id="dynamic_disabled"
                 packageName="package"
@@ -69,8 +69,8 @@
                 profile="all_profiles"
                 maxSeverityLevel="300"
                 broadcastReceiverClassName="broadcast"
-                allowLogging="false"
-                allowRefreshOnPageOpen="true"/>
+                loggingAllowed="false"
+                refreshOnPageOpenAllowed="true"/>
         </safety-sources-group>
         <safety-sources-group
             id="mixed"
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
index c9ffb66..d276865 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
@@ -17,7 +17,8 @@
 package android.safetycenter.config.cts
 
 import android.content.Context
-import android.safetycenter.config.Parser
+import android.safetycenter.config.ParseException
+import android.safetycenter.config.SafetyCenterConfig
 import android.safetycenter.cts.R
 import androidx.test.core.app.ApplicationProvider.getApplicationContext
 import com.google.common.truth.Truth.assertThat
@@ -45,8 +46,8 @@
     @Test
     fun invalidConfig_throws() {
         val parser = context.resources.getXml(params.configResourceId)
-        val thrown = assertThrows(Parser.ParseException::class.java) {
-            Parser.parseXmlResource(parser)
+        val thrown = assertThrows(ParseException::class.java) {
+            SafetyCenterConfig.fromXml(parser)
         }
         assertThat(thrown).hasMessageThat().isEqualTo(params.errorMessage)
         if (params.causeErrorMessage != null) {
@@ -350,7 +351,7 @@
                 "ConfigStaticSafetySourceWithLogging",
                 R.xml.config_static_safety_source_with_logging,
                 "Element static-safety-source invalid",
-                "Prohibited attribute allowLogging present"
+                "Prohibited attribute loggingAllowed present"
             ),
             Params(
                 "ConfigStaticSafetySourceWithPackage",
@@ -368,7 +369,7 @@
                 "ConfigStaticSafetySourceWithRefresh",
                 R.xml.config_static_safety_source_with_refresh,
                 "Element static-safety-source invalid",
-                "Prohibited attribute allowRefreshOnPageOpen present"
+                "Prohibited attribute refreshOnPageOpenAllowed present"
             ),
             Params(
                 "ConfigStaticSafetySourceWithSeverity",
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
index 17d1cde..9190b6d 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
@@ -17,7 +17,6 @@
 package android.safetycenter.config.cts
 
 import android.content.Context
-import android.safetycenter.config.Parser
 import android.safetycenter.config.SafetyCenterConfig
 import android.safetycenter.config.SafetySource
 import android.safetycenter.config.SafetySourcesGroup
@@ -61,8 +60,8 @@
                     .setMaxSeverityLevel(300)
                     .setSearchTermsResId(R.string.reference)
                     .setBroadcastReceiverClassName("broadcast")
-                    .setAllowLogging(false)
-                    .setAllowRefreshOnPageOpen(true)
+                    .setLoggingAllowed(false)
+                    .setRefreshOnPageOpenAllowed(true)
                     .build())
                 .addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
                     .setId("dynamic_disabled")
@@ -112,8 +111,8 @@
                     .setProfile(SafetySource.PROFILE_ALL)
                     .setMaxSeverityLevel(300)
                     .setBroadcastReceiverClassName("broadcast")
-                    .setAllowLogging(false)
-                    .setAllowRefreshOnPageOpen(true)
+                    .setLoggingAllowed(false)
+                    .setRefreshOnPageOpenAllowed(true)
                     .build())
                 .build())
             .addSafetySourcesGroup(SafetySourcesGroup.Builder()
@@ -141,6 +140,6 @@
                     .build())
                 .build())
             .build()
-        assertEquals(expected, Parser.parseXmlResource(parser))
+        assertEquals(expected, SafetyCenterConfig.fromXml(parser))
     }
 }
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
index 3c794ad..f2a96df 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
@@ -230,35 +230,35 @@
     }
 
     @Test
-    fun isAllowLogging_returnsAllowLoggingOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.isAllowLogging).isEqualTo(true)
-        assertThat(DYNAMIC_ALL_OPTIONAL.isAllowLogging).isEqualTo(false)
-        assertThat(DYNAMIC_DISABLED.isAllowLogging).isEqualTo(true)
-        assertThat(DYNAMIC_HIDDEN.isAllowLogging).isEqualTo(true)
+    fun isLoggingAllowed_returnsLoggingAllowedOrThrows() {
+        assertThat(DYNAMIC_BAREBONE.isLoggingAllowed).isEqualTo(true)
+        assertThat(DYNAMIC_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
+        assertThat(DYNAMIC_DISABLED.isLoggingAllowed).isEqualTo(true)
+        assertThat(DYNAMIC_HIDDEN.isLoggingAllowed).isEqualTo(true)
         assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.isAllowLogging
+            STATIC_BAREBONE.isLoggingAllowed
         }
         assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.isAllowLogging
+            STATIC_ALL_OPTIONAL.isLoggingAllowed
         }
-        assertThat(ISSUE_ONLY_BAREBONE.isAllowLogging).isEqualTo(true)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isAllowLogging).isEqualTo(false)
+        assertThat(ISSUE_ONLY_BAREBONE.isLoggingAllowed).isEqualTo(true)
+        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
     }
 
     @Test
-    fun isAllowRefreshOnPageOpen_returnsAllowRefreshOnPageOpenOrThrows() {
-        assertThat(DYNAMIC_BAREBONE.isAllowRefreshOnPageOpen).isEqualTo(false)
-        assertThat(DYNAMIC_ALL_OPTIONAL.isAllowRefreshOnPageOpen).isEqualTo(true)
-        assertThat(DYNAMIC_DISABLED.isAllowRefreshOnPageOpen).isEqualTo(false)
-        assertThat(DYNAMIC_HIDDEN.isAllowRefreshOnPageOpen).isEqualTo(false)
+    fun isRefreshOnPageOpenAllowed_returnsRefreshOnPageOpenAllowedOrThrows() {
+        assertThat(DYNAMIC_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+        assertThat(DYNAMIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
+        assertThat(DYNAMIC_DISABLED.isRefreshOnPageOpenAllowed).isEqualTo(false)
+        assertThat(DYNAMIC_HIDDEN.isRefreshOnPageOpenAllowed).isEqualTo(false)
         assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_BAREBONE.isAllowRefreshOnPageOpen
+            STATIC_BAREBONE.isRefreshOnPageOpenAllowed
         }
         assertThrows(UnsupportedOperationException::class.java) {
-            STATIC_ALL_OPTIONAL.isAllowRefreshOnPageOpen
+            STATIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed
         }
-        assertThat(ISSUE_ONLY_BAREBONE.isAllowRefreshOnPageOpen).isEqualTo(false)
-        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isAllowRefreshOnPageOpen).isEqualTo(true)
+        assertThat(ISSUE_ONLY_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+        assertThat(ISSUE_ONLY_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
     }
 
     @Test
@@ -327,8 +327,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalCopy)
     }
@@ -360,8 +360,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -380,8 +380,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -400,8 +400,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -420,8 +420,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -440,8 +440,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -460,8 +460,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -491,8 +491,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -511,8 +511,8 @@
             .setMaxSeverityLevel(-1)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -531,8 +531,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(-1)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -551,14 +551,14 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName("other")
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
 
     @Test
-    fun hashCode_equals_toString_withDifferentAllowLoggings_areNotEqual() {
+    fun hashCode_equals_toString_withDifferentLoggingAlloweds_areNotEqual() {
         val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
             .setId(DYNAMIC_ALL_OPTIONAL_ID)
             .setPackageName(PACKAGE_NAME)
@@ -571,14 +571,14 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(true)
-            .setAllowRefreshOnPageOpen(true)
+            .setLoggingAllowed(true)
+            .setRefreshOnPageOpenAllowed(true)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
 
     @Test
-    fun hashCode_equals_toString_withDifferentAllowRefreshOnPageOpens_areNotEqual() {
+    fun hashCode_equals_toString_withDifferentRefreshOnPageOpenAlloweds_areNotEqual() {
         val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
             .setId(DYNAMIC_ALL_OPTIONAL_ID)
             .setPackageName(PACKAGE_NAME)
@@ -591,8 +591,8 @@
             .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
             .setSearchTermsResId(REFERENCE_RES_ID)
             .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-            .setAllowLogging(false)
-            .setAllowRefreshOnPageOpen(false)
+            .setLoggingAllowed(false)
+            .setRefreshOnPageOpenAllowed(false)
             .build()
         AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
     }
@@ -636,8 +636,8 @@
                 .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
                 .setSearchTermsResId(REFERENCE_RES_ID)
                 .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-                .setAllowLogging(false)
-                .setAllowRefreshOnPageOpen(true)
+                .setLoggingAllowed(false)
+                .setRefreshOnPageOpenAllowed(true)
                 .build()
 
         private val DYNAMIC_DISABLED =
@@ -692,8 +692,8 @@
                 .setProfile(SafetySource.PROFILE_ALL)
                 .setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
                 .setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
-                .setAllowLogging(false)
-                .setAllowRefreshOnPageOpen(true)
+                .setLoggingAllowed(false)
+                .setRefreshOnPageOpenAllowed(true)
                 .build()
     }
 }
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
index a6a9f0a..c3c7e726 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
@@ -22,26 +22,32 @@
 import android.safetycenter.SafetyCenterManager
 import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
 import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetyEvent
+import android.safetycenter.config.SafetyCenterConfig
 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import java.util.concurrent.Executor
 
 /**
- * Call {@link SafetyCenterManager#sendSafetyCenterUpdate} adopting Shell's
+ * Call {@link SafetyCenterManager#setSafetySourceData} adopting Shell's
  * {@link SEND_SAFETY_CENTER_UPDATE} permission.
  */
-fun SafetyCenterManager.sendUpdateWithPermission(safetySourceData: SafetySourceData) =
+fun SafetyCenterManager.setSafetySourceDataWithPermission(
+    safetySourceId: String,
+    safetySourceData: SafetySourceData,
+    safetyEvent: SafetyEvent
+) =
     runWithShellPermissionIdentity({
-        sendSafetyCenterUpdate(safetySourceData)
+        setSafetySourceData(safetySourceId, safetySourceData, safetyEvent)
     }, SEND_SAFETY_CENTER_UPDATE)
 
 /**
- * Call {@link SafetyCenterManager#getLastSafetyCenterUpdate} adopting Shell's
+ * Call {@link SafetyCenterManager#getSafetySourceData} adopting Shell's
  * {@link SEND_SAFETY_CENTER_UPDATE} permission.
  */
-fun SafetyCenterManager.getLastUpdateWithPermission(id: String): SafetySourceData? =
+fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String): SafetySourceData? =
     callWithShellPermissionIdentity({
-        getLastSafetyCenterUpdate(id)
+        getSafetySourceData(id)
     }, SEND_SAFETY_CENTER_UPDATE)
 
 /**
@@ -82,24 +88,22 @@
     }, MANAGE_SAFETY_CENTER)
 
 /**
- * Call {@link SafetyCenterManager#clearSafetyCenterData} adopting Shell's
+ * Call {@link SafetyCenterManager#clearAllSafetySourceData} adopting Shell's
  * {@link MANAGE_SAFETY_CENTER} permission.
  */
-fun SafetyCenterManager.clearDataWithPermission() =
+fun SafetyCenterManager.clearAllSafetySourceDataWithPermission() =
     runWithShellPermissionIdentity({
-        clearSafetyCenterData()
+        clearAllSafetySourceData()
     }, MANAGE_SAFETY_CENTER)
 
-fun SafetyCenterManager.addAdditionalSafetySourceWithPermission(
-    sourceId: String,
-    packageName: String,
-    broadcastReceiverName: String
+fun SafetyCenterManager.setSafetyCenterConfigOverrideWithPermission(
+    safetyCenterConfig: SafetyCenterConfig
 ) =
     runWithShellPermissionIdentity({
-        addAdditionalSafetySource(sourceId, packageName, broadcastReceiverName)
+        setSafetyCenterConfigOverride(safetyCenterConfig)
     }, MANAGE_SAFETY_CENTER)
 
-fun SafetyCenterManager.clearAdditionalSafetySourcesWithPermission() =
+fun SafetyCenterManager.clearSafetyCenterConfigOverrideWithPermission() =
     runWithShellPermissionIdentity({
-        clearAdditionalSafetySources()
+        clearSafetyCenterConfigOverride()
     }, MANAGE_SAFETY_CENTER)
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index f86ce84..bd58849 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -34,9 +34,14 @@
 import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
 import android.safetycenter.SafetySourceData
 import android.safetycenter.SafetySourceIssue
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
 import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
 import android.safetycenter.SafetySourceStatus
 import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
+import android.safetycenter.config.SafetyCenterConfig
+import android.safetycenter.config.SafetySource
+import android.safetycenter.config.SafetySourcesGroup
 import androidx.test.core.app.ApplicationProvider.getApplicationContext
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SdkSuppress
@@ -59,13 +64,12 @@
 class SafetyCenterManagerTest {
     private val context: Context = getApplicationContext()
     private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
-    private val sourceId = "source_id"
     private val somePendingIntent = PendingIntent.getActivity(
         context, 0 /* requestCode */,
         Intent(ACTION_SAFETY_CENTER).addFlags(FLAG_ACTIVITY_NEW_TASK),
         FLAG_IMMUTABLE
     )
-    private val safetySourceDataOnPageOpen = SafetySourceData.Builder(sourceId)
+    private val safetySourceDataOnPageOpen = SafetySourceData.Builder()
         .setStatus(
             SafetySourceStatus.Builder(
                 "safetySourceDataOnPageOpen status title",
@@ -76,7 +80,7 @@
                 .build()
         )
         .build()
-    private val safetySourceDataOnRescanClick = SafetySourceData.Builder(sourceId)
+    private val safetySourceDataOnRescanClick = SafetySourceData.Builder()
         .setStatus(
             SafetySourceStatus.Builder(
                 "safetySourceDataOnRescanClick status title",
@@ -100,51 +104,57 @@
     @After
     fun clearDataBetweenTest() {
         safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
-        safetyCenterManager.clearDataWithPermission()
+        safetyCenterManager.clearAllSafetySourceDataWithPermission()
         SafetySourceBroadcastReceiver.reset()
     }
 
     @Before
-    fun addAdditionalSafetySourcesBeforeTest() {
-        safetyCenterManager.clearAdditionalSafetySourcesWithPermission()
-        safetyCenterManager.addAdditionalSafetySourceWithPermission(
-            sourceId, CTS_PACKAGE_NAME,
-            CTS_BROADCAST_RECEIVER_NAME
-        )
+    fun setSafetyCenterConfigOverrideBeforeTest() {
+        safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
+        // TODO(b/217944317): When the test API impl is finalized to override XML config, only
+        //  override config in select test cases that require it. This is to ensure that we do have
+        //  some test cases running with the XML config.
+        safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_ONLY_CONFIG)
     }
 
     @After
-    fun clearAdditionalSafetySourcesAfterTest() {
-        safetyCenterManager.clearAdditionalSafetySourcesWithPermission()
+    fun clearSafetyCenterConfigOverrideAfterTest() {
+        safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
     }
 
     @Test
-    fun getLastSafetyCenterUpdate_noUpdate_returnsNull() {
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission("some_unknown_id")
+    fun getSafetySourceData_notSet_returnsNull() {
+        val safetySourceData =
+            safetyCenterManager.getSafetySourceDataWithPermission("some_unknown_id")
 
-        assertThat(lastSafetyCenterUpdate).isNull()
+        assertThat(safetySourceData).isNull()
     }
 
     @Test
-    fun sendSafetyCenterUpdate_getLastSafetyCenterUpdateReturnsNewValue() {
-        val id = "some_known_id"
-        val safetyCenterUpdate = SafetySourceData.Builder(id).build()
-        safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+    fun setSafetySourceData_getSafetySourceDataReturnsNewValue() {
+        val safetySourceData = SafetySourceData.Builder().build()
+        safetyCenterManager.setSafetySourceDataWithPermission(
+                CTS_SOURCE_ID,
+                safetySourceData,
+                EVENT_SOURCE_STATE_CHANGED
+        )
 
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission(id)
+        val safetySourceDataResult =
+                safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
 
-        assertThat(lastSafetyCenterUpdate).isEqualTo(safetyCenterUpdate)
+        assertThat(safetySourceDataResult).isEqualTo(safetySourceData)
     }
 
     @Test
-    fun sendSafetyCenterUpdate_withSameId_replacesValue() {
-        val id = "some_known_id"
-        val firstSafetyCenterUpdate = SafetySourceData.Builder(id).build()
-        safetyCenterManager.sendUpdateWithPermission(firstSafetyCenterUpdate)
+    fun setSafetySourceData_withSameId_replacesValue() {
+        val firstSafetySourceData = SafetySourceData.Builder().build()
+        safetyCenterManager.setSafetySourceDataWithPermission(
+                CTS_SOURCE_ID,
+                firstSafetySourceData,
+                EVENT_SOURCE_STATE_CHANGED
+        )
 
-        val secondSafetyCenterUpdate = SafetySourceData.Builder(id).setStatus(
+        val secondSafetySourceData = SafetySourceData.Builder().setStatus(
             SafetySourceStatus.Builder(
                 "Status title", "Summary of the status", STATUS_LEVEL_CRITICAL_WARNING,
                 somePendingIntent
@@ -163,12 +173,15 @@
                     ).build()
                 ).build()
         ).build()
-        safetyCenterManager.sendUpdateWithPermission(secondSafetyCenterUpdate)
+        safetyCenterManager.setSafetySourceDataWithPermission(
+                CTS_SOURCE_ID,
+                secondSafetySourceData,
+                EVENT_SOURCE_STATE_CHANGED
+        )
 
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission(id)
+        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
 
-        assertThat(lastSafetyCenterUpdate).isEqualTo(secondSafetyCenterUpdate)
+        assertThat(safetySourceData).isEqualTo(secondSafetySourceData)
     }
 
     @Test
@@ -186,8 +199,7 @@
             )
         }
 
-        val isSafetyCenterEnabled =
-            safetyCenterManager.isSafetyCenterEnabledWithPermission()
+        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
 
         assertThat(isSafetyCenterEnabled).isTrue()
     }
@@ -207,8 +219,7 @@
             )
         }
 
-        val isSafetyCenterEnabled =
-            safetyCenterManager.isSafetyCenterEnabledWithPermission()
+        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
 
         assertThat(isSafetyCenterEnabled).isFalse()
     }
@@ -228,8 +239,7 @@
             )
         }
 
-        val isSafetyCenterEnabled =
-            safetyCenterManager.isSafetyCenterEnabledWithPermission()
+        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
 
         assertThat(isSafetyCenterEnabled).isFalse()
     }
@@ -249,8 +259,7 @@
             )
         }
 
-        val isSafetyCenterEnabled =
-            safetyCenterManager.isSafetyCenterEnabledWithPermission()
+        val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
 
         assertThat(isSafetyCenterEnabled).isFalse()
     }
@@ -271,6 +280,7 @@
 
     @Test
     fun refreshSafetySources_whenReceiverDoesNotHaveSendingPermission_sourceDoesNotSendData() {
+        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
         SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
 
         safetyCenterManager.refreshSafetySourcesWithPermission(
@@ -280,39 +290,40 @@
         assertFailsWith(TimeoutCancellationException::class) {
             SafetySourceBroadcastReceiver.waitTillOnReceiveComplete(TIMEOUT_SHORT)
         }
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission(sourceId)
-        assertThat(lastSafetyCenterUpdate).isNull()
+        val safetySourceData =
+            safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+        assertThat(safetySourceData).isNull()
     }
 
     @Test
     fun refreshSafetySources_withRefreshReasonRescanButtonClick_sourceSendsRescanData() {
+        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
         SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
 
         safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
             REFRESH_REASON_RESCAN_BUTTON_CLICK
         )
 
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission(sourceId)
-        assertThat(lastSafetyCenterUpdate).isEqualTo(safetySourceDataOnRescanClick)
+        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+        assertThat(safetySourceData).isEqualTo(safetySourceDataOnRescanClick)
     }
 
     @Test
     fun refreshSafetySources_withRefreshReasonPageOpen_sourceSendsPageOpenData() {
+        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
         SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
 
         safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
             REFRESH_REASON_PAGE_OPEN
         )
 
-        val lastSafetyCenterUpdate =
-            safetyCenterManager.getLastUpdateWithPermission(sourceId)
-        assertThat(lastSafetyCenterUpdate).isEqualTo(safetySourceDataOnPageOpen)
+        val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+        assertThat(safetySourceData).isEqualTo(safetySourceDataOnPageOpen)
     }
 
     @Test
     fun refreshSafetySources_withInvalidRefreshSeason_throwsIllegalArgumentException() {
+        SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
         SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
         SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
 
@@ -348,16 +359,19 @@
     }
 
     @Test
-    fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetyCenterUpdate() {
+    fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetySourceData() {
         safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
             directExecutor(), listener
         )
         // Receive initial data.
         receiveListenerUpdate()
 
-        val id = "some_known_id"
-        val safetyCenterUpdate = SafetySourceData.Builder(id).build()
-        safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+        val safetySourceData = SafetySourceData.Builder().build()
+        safetyCenterManager.setSafetySourceDataWithPermission(
+                CTS_SOURCE_ID,
+                safetySourceData,
+                EVENT_SOURCE_STATE_CHANGED
+        )
         val safetyCenterDataFromListener = receiveListenerUpdate()
 
         // TODO(b/218830137): Assert on content.
@@ -365,7 +379,7 @@
     }
 
     @Test
-    fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetyCenterUpdate() {
+    fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetySourceData() {
         safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
             directExecutor(), listener
         )
@@ -373,9 +387,12 @@
         receiveListenerUpdate()
 
         safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
-        val id = "some_known_id"
-        val safetyCenterUpdate = SafetySourceData.Builder(id).build()
-        safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+        val safetySourceData = SafetySourceData.Builder().build()
+        safetyCenterManager.setSafetySourceDataWithPermission(
+                CTS_SOURCE_ID,
+                safetySourceData,
+                EVENT_SOURCE_STATE_CHANGED
+        )
 
         assertFailsWith(TimeoutCancellationException::class) {
             receiveListenerUpdate(TIMEOUT_SHORT)
@@ -454,5 +471,28 @@
             "android.safetycenter.cts.SafetySourceBroadcastReceiver"
         private val TIMEOUT_LONG: Duration = Duration.ofMillis(5000)
         private val TIMEOUT_SHORT: Duration = Duration.ofMillis(1000)
+        private val EVENT_SOURCE_STATE_CHANGED =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+        private const val CTS_SOURCE_ID = "cts_source_id"
+        // TODO(b/217944317): Consider moving the following to a file where they can be used by
+        //  other tests.
+        private val CTS_SOURCE = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+                .setId(CTS_SOURCE_ID)
+                .setPackageName(CTS_PACKAGE_NAME)
+                .setTitleResId(R.string.reference)
+                .setSummaryResId(R.string.reference)
+                .setIntentAction("SafetyCenterManagerTest.INTENT_ACTION")
+                .setBroadcastReceiverClassName(CTS_BROADCAST_RECEIVER_NAME)
+                .setProfile(SafetySource.PROFILE_PRIMARY)
+                .build()
+        private val CTS_SOURCE_GROUP = SafetySourcesGroup.Builder()
+                .setId("cts_source_group")
+                .setTitleResId(R.string.reference)
+                .setSummaryResId(R.string.reference)
+                .addSafetySource(CTS_SOURCE)
+                .build()
+        private val CTS_ONLY_CONFIG = SafetyCenterConfig.Builder()
+                .addSafetySourcesGroup(CTS_SOURCE_GROUP)
+                .build()
     }
 }
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
new file mode 100644
index 0000000..bc9d538
--- /dev/null
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.cts
+
+import android.os.Build
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
+import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** CTS tests for [SafetyEvent]. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class SafetyEventTest {
+    @Test
+    fun getSafetyEventType_returnsSafetyEventType() {
+        val safetyEvent = SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+
+        assertThat(safetyEvent.safetyEventType).isEqualTo(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
+    }
+
+    @Test
+    fun getRefreshBroadcastId_returnsRefreshBroadcastId() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+                        .build()
+
+        assertThat(safetyEvent.refreshBroadcastId).isEqualTo(REFRESH_BROADCAST_ID)
+    }
+
+    @Test
+    fun getSafetySourceIssueId_returnsSafetySourceIssueId() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .build()
+
+        assertThat(safetyEvent.safetySourceIssueId).isEqualTo(SAFETY_SOURCE_ISSUE_ID)
+    }
+
+    @Test
+    fun getSafetySourceIssueActionId_returnsSafetySourceIssueActionId() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+
+        assertThat(safetyEvent.safetySourceIssueActionId).isEqualTo(SAFETY_SOURCE_ISSUE_ACTION_ID)
+    }
+
+    @Test
+    fun describeContents_returns0() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+
+        assertThat(safetyEvent.describeContents()).isEqualTo(0)
+    }
+
+    @Test
+    fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+
+        assertThatRoundTripReturnsOriginal(safetyEvent, SafetyEvent.CREATOR)
+    }
+
+    // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
+    @Test
+    fun hashCode_equals_toString_withEqualByReference_areEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+                        .build()
+        val otherSafetyEvent = safetyEvent
+
+        assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    @Test
+    fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+        val otherSafetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+
+        assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    @Test
+    fun hashCode_equals_toString_withDifferentSafetyEventTypes_areNotEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .build()
+        val otherSafetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED)
+                        .build()
+
+        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    @Test
+    fun hashCode_equals_toString_withDifferentRefreshBroadcastIds_areNotEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+                        .build()
+        val otherSafetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .setRefreshBroadcastId(OTHER_REFRESH_BROADCAST_ID)
+                        .build()
+
+        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    @Test
+    fun hashCode_equals_toString_withDifferentIssueIds_areNotEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .build()
+        val otherSafetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(OTHER_SAFETY_SOURCE_ISSUE_ID)
+                        .build()
+
+        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    @Test
+    fun hashCode_equals_toString_withDifferentActionIds_areNotEqual() {
+        val safetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+        val otherSafetyEvent =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+                        .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+                        .setSafetySourceIssueActionId(OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID)
+                        .build()
+
+        assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+    }
+
+    companion object {
+        const val REFRESH_BROADCAST_ID = "refresh_broadcast_id"
+        const val OTHER_REFRESH_BROADCAST_ID = "other_refresh_broadcast_id"
+        const val SAFETY_SOURCE_ISSUE_ID = "safety_source_issue_id"
+        const val OTHER_SAFETY_SOURCE_ISSUE_ID = "other_safety_source_issue_id"
+        const val SAFETY_SOURCE_ISSUE_ACTION_ID = "safety_source_issue_action_id"
+        const val OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID = "other_safety_source_issue_action_id"
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
index 4924c94..5f8e8b8 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
@@ -25,6 +25,8 @@
 import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
 import android.safetycenter.SafetyCenterManager
 import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withTimeout
@@ -45,9 +47,17 @@
 
         when (intent.getIntExtra(EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE, -1)) {
             EXTRA_REFRESH_REQUEST_TYPE_GET_DATA ->
-                safetyCenterManager.sendUpdateWithPermission(safetySourceDataOnPageOpen!!)
+                safetyCenterManager.setSafetySourceDataWithPermission(
+                        safetySourceId!!,
+                        safetySourceDataOnPageOpen!!,
+                        EVENT_REFRESH_REQUESTED
+                )
             EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA ->
-                safetyCenterManager.sendUpdateWithPermission(safetySourceDataOnRescanClick!!)
+                safetyCenterManager.setSafetySourceDataWithPermission(
+                        safetySourceId!!,
+                        safetySourceDataOnRescanClick!!,
+                        EVENT_REFRESH_REQUESTED
+                )
         }
 
         runBlocking {
@@ -57,10 +67,16 @@
 
     companion object {
         private var updateChannel = Channel<Unit>()
+        private val EVENT_REFRESH_REQUESTED =
+                SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+                        .setRefreshBroadcastId("refresh_id")
+                        .build()
+        var safetySourceId: String? = null
         var safetySourceDataOnPageOpen: SafetySourceData? = null
         var safetySourceDataOnRescanClick: SafetySourceData? = null
 
         fun reset() {
+            safetySourceId = null
             safetySourceDataOnRescanClick = null
             safetySourceDataOnPageOpen = null
             updateChannel = Channel()
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
index 5706434..76090bf 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
@@ -104,22 +104,15 @@
         .build()
 
     @Test
-    fun getId_returnsId() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id").build()
-
-        assertThat(safetySourceData.id).isEqualTo("Safety source id")
-    }
-
-    @Test
     fun getStatus_withDefaultBuilder_returnsNull() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+        val safetySourceData = SafetySourceData.Builder().build()
 
         assertThat(safetySourceData.status).isNull()
     }
 
     @Test
     fun getStatus_whenSetExplicitly_returnsStatus() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .build()
 
@@ -128,14 +121,14 @@
 
     @Test
     fun getIssues_withDefaultBuilder_returnsEmptyList() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+        val safetySourceData = SafetySourceData.Builder().build()
 
         assertThat(safetySourceData.issues).isEmpty()
     }
 
     @Test
     fun getIssues_whenSetExplicitly_returnsIssues() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .addIssue(issue1)
                 .addIssue(issue2)
                 .build()
@@ -145,7 +138,7 @@
 
     @Test
     fun clearIssues_removesAllIssues() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
             .addIssue(issue1)
             .addIssue(issue2)
             .clearIssues()
@@ -156,7 +149,7 @@
 
     @Test
     fun describeContents_returns0() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
@@ -167,7 +160,7 @@
 
     @Test
     fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
@@ -186,7 +179,7 @@
     // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
     @Test
     fun hashCode_equals_toString_withEqualByReference_withoutStatusAndIssues_areEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+        val safetySourceData = SafetySourceData.Builder().build()
         val otherSafetySourceData = safetySourceData
 
         assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
@@ -196,7 +189,7 @@
 
     @Test
     fun hashCode_equals_toString_withEqualByReference_withoutIssues_areEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .build()
         val otherSafetySourceData = safetySourceData
@@ -208,7 +201,7 @@
 
     @Test
     fun hashCode_equals_toString_withEqualByReference_areEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
@@ -222,12 +215,12 @@
 
     @Test
     fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
                 .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+        val otherSafetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
@@ -239,27 +232,13 @@
     }
 
     @Test
-    fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
-                .setStatus(status1)
-                .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id 2")
-                .setStatus(status1)
-                .build()
-
-        assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
-        assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
-        assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
-    }
-
-    @Test
     fun hashCode_equals_toString_withDifferentIssues_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
                 .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+        val otherSafetySourceData = SafetySourceData.Builder()
                 .setStatus(status2)
                 .addIssue(issue1)
                 .addIssue(issue2)
@@ -272,12 +251,12 @@
 
     @Test
     fun hashCode_equals_toString_withDifferentStatuses_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
                 .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+        val otherSafetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .build()
@@ -289,10 +268,10 @@
 
     @Test
     fun hashCode_equals_toString_withStatusSetInOneAndNotOther_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id").build()
+        val otherSafetySourceData = SafetySourceData.Builder().build()
 
         assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
         assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
@@ -301,12 +280,12 @@
 
     @Test
     fun hashCode_equals_toString_withIssuesSetInOneAndNotOther_areNotEqual() {
-        val safetySourceData = SafetySourceData.Builder("Safety source id")
+        val safetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .addIssue(issue1)
                 .addIssue(issue2)
                 .build()
-        val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+        val otherSafetySourceData = SafetySourceData.Builder()
                 .setStatus(status1)
                 .build()
 
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
index 2dba3c0..0d69f2c 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
@@ -16,107 +16,63 @@
 
 package android.safetycenter.cts
 
-import android.os.Parcel
+import android.os.Build
+import android.safetycenter.SafetyEvent
 import android.safetycenter.SafetySourceError
-import android.safetycenter.SafetySourceError.SOURCE_ERROR_TYPE_ACTION_ERROR
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
+import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
 
+/** CTS tests for [SafetySourceError]. */
 @RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
 class SafetySourceErrorTest {
-
-    val actionError1 = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-            .setIssueId("issue_id_1")
-            .setActionId("action_id_1")
-            .build()
-    val actionError2 = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-            .setIssueId("issue_id_2")
-            .setActionId("action_id_2")
-            .build()
-
     @Test
-    fun getType_returnsType() {
-        assertThat(actionError1.type).isEqualTo(SOURCE_ERROR_TYPE_ACTION_ERROR)
-        assertThat(actionError2.type).isEqualTo(SOURCE_ERROR_TYPE_ACTION_ERROR)
-    }
+    fun getSafetyEvent_returnsSafetyEvent() {
+        val safetySourceError = SafetySourceError(SAFETY_EVENT)
 
-    @Test
-    fun getIssueId_returnsIssueId() {
-        assertThat(actionError1.issueId).isEqualTo("issue_id_1")
-        assertThat(actionError2.issueId).isEqualTo("issue_id_2")
-    }
-
-    @Test
-    fun getActionId_returnsActionId() {
-        assertThat(actionError1.actionId).isEqualTo("action_id_1")
-        assertThat(actionError2.actionId).isEqualTo("action_id_2")
+        assertThat(safetySourceError.safetyEvent).isEqualTo(SAFETY_EVENT)
     }
 
     @Test
     fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
-        val parcel = Parcel.obtain()
+        val safetySourceError = SafetySourceError(SAFETY_EVENT)
 
-        actionError1.writeToParcel(parcel, /* flags= */ 0)
-        parcel.setDataPosition(0)
-
-        val fromParcel = SafetySourceError.CREATOR.createFromParcel(parcel)
-        parcel.recycle()
-
-        assertThat(fromParcel).isEqualTo(actionError1)
+        assertThatRoundTripReturnsOriginal(safetySourceError, SafetySourceError.CREATOR)
     }
 
     @Test
     fun equals_hashCode_toString_equalByReference_areEqual() {
-        assertThat(actionError1).isEqualTo(actionError1)
-        assertThat(actionError1.hashCode()).isEqualTo(actionError1.hashCode())
-        assertThat(actionError1.toString()).isEqualTo(actionError1.toString())
+        val safetySourceError = SafetySourceError(SAFETY_EVENT)
+
+        assertThatRepresentationsAreEqual(safetySourceError, safetySourceError)
     }
 
     @Test
-    fun equals_hashCode_toString_actionErrors_equalByValue_areEqual() {
-        val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_1")
-                .setActionId("action_id_1")
-                .build()
-        val equivalentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_1")
-                .setActionId("action_id_1")
-                .build()
+    fun equals_hashCode_toString_equalByValue_areEqual() {
+        val safetySourceError = SafetySourceError(SAFETY_EVENT)
+        val equivalentSafetySourceError = SafetySourceError(SAFETY_EVENT)
 
-        assertThat(actionError).isEqualTo(equivalentActionError)
-        assertThat(actionError.hashCode()).isEqualTo(equivalentActionError.hashCode())
-        assertThat(actionError.toString()).isEqualTo(equivalentActionError.toString())
+        assertThatRepresentationsAreEqual(safetySourceError, equivalentSafetySourceError)
     }
 
     @Test
-    fun equals_toString_withDifferentIssueIds_areNotEqual() {
-        val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_1")
-                .setActionId("action_id_1")
-                .build()
-        val differentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_2")
-                .setActionId("action_id_1")
-                .build()
+    fun equals_toString_withDifferentSafetyEvents_areNotEqual() {
+        val safetySourceError = SafetySourceError(
+                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build())
+        val otherSafetySourceError = SafetySourceError(
+                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build())
 
-        assertThat(actionError).isNotEqualTo(differentActionError)
-        assertThat(actionError.toString()).isNotEqualTo(differentActionError.toString())
+        assertThatRepresentationsAreNotEqual(safetySourceError, otherSafetySourceError)
     }
 
-    @Test
-    fun equals_toString_withDifferentActionIds_areNotEqual() {
-        val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_1")
-                .setActionId("action_id_1")
-                .build()
-        val differentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
-                .setIssueId("issue_id_1")
-                .setActionId("action_id_2")
-                .build()
-
-        assertThat(actionError).isNotEqualTo(differentActionError)
-        assertThat(actionError.toString()).isNotEqualTo(differentActionError.toString())
+    companion object {
+        private val SAFETY_EVENT =
+                SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
     }
 }
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
index 461dc69..9b77e99 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
@@ -17,7 +17,7 @@
 package android.safetycenter.cts
 
 import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.Parser
+import android.safetycenter.config.SafetyCenterConfig
 import androidx.test.core.app.ApplicationProvider.getApplicationContext
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SdkSuppress
@@ -34,6 +34,6 @@
     @Test
     fun safetyCenterConfigResource_validConfig() {
         // Assert that the parser validates the Safety Center config without throwing any exception
-        assertThat(Parser.parseXmlResource(safetyCenterContext.safetyCenterConfig!!)).isNotNull()
+        assertThat(SafetyCenterConfig.fromXml(safetyCenterContext.safetyCenterConfig!!)).isNotNull()
     }
 }
diff --git a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
index 391f9c4..484438b 100644
--- a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
+++ b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
@@ -694,6 +694,38 @@
         }
     }
 
+    /** Tests closeChannels API */
+    @Test
+    public void testCloseChannels() {
+        assumeTrue(supportOMAPIReaders());
+        try {
+            waitForConnection();
+            Reader[] readers = seService.getReaders();
+
+            for (Reader reader : readers) {
+                Session session = null;
+                Channel channelA = null;
+                Channel channelB = null;
+                try {
+                    assertTrue(reader.isSecureElementPresent());
+                    session = reader.openSession();
+                    assertNotNull("null session", session);
+                    channelA = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
+                    assertNotNull("Null Channel", channelA);
+                    channelB = session.openLogicalChannel(LONG_SELECT_RESPONSE_AID, (byte) 0x00);
+                    assertNotNull("Null Channel", channelB);
+                    session.closeChannels();
+                    assertFalse("channel is still open", channelA.isOpen());
+                    assertFalse("channel is still open", channelB.isOpen());
+                } finally {
+                    if (session != null) session.close();
+                }
+            }
+        } catch (Exception e) {
+            fail("unexpected exception " + e);
+        }
+    }
+
     /**
      * Verifies TLV data
      * @param tlv
diff --git a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
index 80ffd60..e36fa49 100644
--- a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
+++ b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
@@ -16,44 +16,39 @@
 
 package android.security.cts;
 
+import static org.junit.Assert.assertThrows;
+
+import java.lang.reflect.Field;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import android.content.AttributionSource;
 import android.content.Context;
 import android.platform.test.annotations.AsbSecurityTest;
-
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.runner.AndroidJUnit4;
 
-import org.junit.Assume;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.Assert;
-
-import java.lang.reflect.Field;
-
 @RunWith(AndroidJUnit4.class)
 public class AttributionSourceTest {
 
     @AsbSecurityTest(cveBugId = 200288596)
     @Test
-    public void testPidCheck()
-            throws Exception {
+    public void testPidCheck() throws Exception {
         Context context = ApplicationProvider.getApplicationContext();
-        AttributionSource attributionSource = null;
-        Field attSourceStateField = null;
-        try {
-            attributionSource = (AttributionSource) Context.class.getMethod(
-                    "getAttributionSource").invoke(context);
-            attSourceStateField = attributionSource.getClass().getDeclaredField(
-                    "mAttributionSourceState");
-            attSourceStateField.setAccessible(true);
-        } catch (Exception e) {
-            Assume.assumeFalse(true);
-        }
+        AttributionSource attributionSource =
+                new AttributionSource(
+                        (AttributionSource)
+                                Context.class.getMethod("getAttributionSource").invoke(context),
+                        null);
+
+        Field attSourceStateField =
+                attributionSource.getClass().getDeclaredField("mAttributionSourceState");
+        attSourceStateField.setAccessible(true);
 
         Object attSourceState = attSourceStateField.get(attributionSource);
         attSourceState.getClass().getField("pid").setInt(attSourceState, 0);
         final AttributionSource attributionSourceFinal = attributionSource;
-        Assert.assertThrows(SecurityException.class,
-                () -> attributionSourceFinal.enforceCallingPid());
+        assertThrows(SecurityException.class, () -> attributionSourceFinal.enforceCallingPid());
     }
 }
+
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index 52eca56..65eb132 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -40,13 +40,13 @@
     protected MediaMetadataRetriever mRetriever;
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mResources = getContext().getResources();
         mRetriever = new MediaMetadataRetriever();
     }
 
     @After
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         mRetriever.release();
     }
 
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 953fbb9..83ce8ff 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -59,7 +59,7 @@
     private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mFlFilePath = new File(getContext().getFilesDir(), "temp.fl").getAbsolutePath();
 
         mOnPrepareCalled.close();
@@ -92,7 +92,7 @@
     }
 
     @After
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         new File(mFlFilePath).delete();
     }
 
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index 9d1dc42..135d493 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -83,7 +83,7 @@
         };
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mContext = getInstrumentation().getContext();
         Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
         mContext.startService(serviceIntent);
@@ -91,7 +91,7 @@
     }
 
     @After
-    protected void tearDown() throws Exception {
+    public void tearDown() throws Exception {
         if (mContext != null) {
             Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
             mContext.stopService(serviceIntent);
diff --git a/tests/tests/security/src/android/security/cts/SQLiteTest.java b/tests/tests/security/src/android/security/cts/SQLiteTest.java
index 9aa69ad..84d36fa 100644
--- a/tests/tests/security/src/android/security/cts/SQLiteTest.java
+++ b/tests/tests/security/src/android/security/cts/SQLiteTest.java
@@ -52,7 +52,7 @@
     private SQLiteDatabase mDatabase;
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mResolver = getContext().getContentResolver();
         mContext = InstrumentationRegistry.getTargetContext();
         mPackageName = mContext.getPackageName();
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index e5366ae..2765de4 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -33,7 +33,7 @@
     private boolean mHasTelephony;
 
     @Before
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         mHasTelephony = getContext().getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY);
     }
diff --git a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
index 079f576d..d277a43 100644
--- a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
@@ -32,11 +32,14 @@
 import android.view.Display;
 
 import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
 
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.BufferedInputStream;
 import java.io.File;
@@ -46,7 +49,8 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-public class WallpaperManagerTest {
+@RunWith(AndroidJUnit4.class)
+public class WallpaperManagerTest extends StsExtraBusinessLogicTestCase {
     private static final String TAG = "WallpaperManagerSTS";
     private static final long PNG_SIZE = 7503368920L;
 
diff --git a/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java b/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java
new file mode 100644
index 0000000..51664ea
--- /dev/null
+++ b/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.settings.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests to ensure the Activity to handle
+ * {@link Settings#ACTION_TETHER_PROVISIONING_CARRIER_UI}
+ */
+@RunWith(AndroidJUnit4.class)
+public class TetherProvisioningCarrierDialogActivityTest {
+    @Test
+    public void testTetheringProvisioningCarrierUiExisted() throws RemoteException {
+        final Intent intent = new Intent(Settings.ACTION_TETHER_UNSUPPORTED_CARRIER_UI);
+        final ResolveInfo ri = InstrumentationRegistry.getTargetContext()
+                .getPackageManager().resolveActivity(
+                        intent, PackageManager.MATCH_DEFAULT_ONLY);
+        assertTrue(ri != null);
+    }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index 7377132..740020c 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -18,12 +18,12 @@
 
 import static android.telecom.Connection.PROPERTY_HIGH_DEF_AUDIO;
 import static android.telecom.Connection.PROPERTY_WIFI;
-import static android.telecom.cts.TestUtils.InvokeCounter;
-import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE;
-import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE_2;
-import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
+import static android.telecom.cts.TestUtils.*;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertThat;
 
 import android.content.Context;
@@ -299,9 +299,6 @@
 
         mConnection.setConnectionProperties(Connection.PROPERTY_CROSS_SIM);
         assertCallProperties(mCall, Call.Details.PROPERTY_CROSS_SIM);
-
-        mConnection.setConnectionProperties(Connection.PROPERTY_TETHERED_CALL);
-        assertCallProperties(mCall, Call.Details.PROPERTY_TETHERED_CALL);
     }
 
     /**
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallTest.java b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
index 1659c12..f7bad4e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
@@ -125,11 +125,4 @@
         assertTrue(cas.getSupportedBluetoothDevices().contains(TestUtils.BLUETOOTH_DEVICE1));
         assertTrue(cas.getSupportedBluetoothDevices().contains(TestUtils.BLUETOOTH_DEVICE2));
     }
-
-    public void testExternalCallAudioState() {
-        CallAudioState cas = new CallAudioState(false, CallAudioState.ROUTE_EXTERNAL,
-                CallAudioState.ROUTE_BLUETOOTH + CallAudioState.ROUTE_SPEAKER
-                        + CallAudioState.ROUTE_EARPIECE);
-        assertEquals(CallAudioState.ROUTE_EXTERNAL, cas.getSupportedRouteMask());
-    }
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
index 5d76420..f87ccd6 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
@@ -35,6 +35,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.DataSpecificRegistrationInfo;
 import android.telephony.LteVopsSupportInfo;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.NrVopsSupportInfo;
@@ -371,9 +372,12 @@
                 new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
                         LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
 
-        NetworkRegistrationInfo wwanDataRegState = new NetworkRegistrationInfo(
-                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
-                0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+        NetworkRegistrationInfo wwanDataRegState = new NetworkRegistrationInfo.Builder()
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+                        0, false, false, false, vopsSupportInfo))
+                .setEmergencyOnly(true).build();
 
         ServiceState ss = new ServiceState();
 
@@ -386,9 +390,12 @@
                 new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
                         LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED);
 
-        wwanDataRegState = new NetworkRegistrationInfo(
-                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
-                0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+        wwanDataRegState = new NetworkRegistrationInfo.Builder()
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+                        0, false, false, false, vopsSupportInfo))
+                .setEmergencyOnly(true).build();
         ss.addNetworkRegistrationInfo(wwanDataRegState);
         assertEquals(ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN), wwanDataRegState);
@@ -402,9 +409,12 @@
         vopsSupportInfo = new NrVopsSupportInfo(NrVopsSupportInfo.NR_STATUS_VOPS_NOT_SUPPORTED,
                 NrVopsSupportInfo.NR_STATUS_EMC_NOT_SUPPORTED,
                 NrVopsSupportInfo.NR_STATUS_EMF_NOT_SUPPORTED);
-        wwanDataRegState = new NetworkRegistrationInfo(
-                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
-                0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+        wwanDataRegState = new NetworkRegistrationInfo.Builder()
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+                        0, false, false, false, vopsSupportInfo))
+                .setEmergencyOnly(true).build();
         ss.addNetworkRegistrationInfo(wwanDataRegState);
         assertEquals(ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN), wwanDataRegState);
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 b4d4986..140a704 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -33,6 +34,7 @@
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -47,12 +49,9 @@
 
     @BeforeClass
     public static void beforeAllTests() throws Exception {
-
         Log.d(TAG, "TelephonyManagerTestOnMockModem#beforeAllTests()");
 
-        final PackageManager pm = getContext().getPackageManager();
-        if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+        if (!hasTelephonyFeature()) {
             return;
         }
 
@@ -68,16 +67,34 @@
     public static void afterAllTests() throws Exception {
         Log.d(TAG, "TelephonyManagerTestOnMockModem#afterAllTests()");
 
+        if (!hasTelephonyFeature()) {
+            return;
+        }
+
         // Rebind all interfaces which is binding to MockModemService to default.
         assertNotNull(sMockModemManager);
         assertTrue(sMockModemManager.disconnectMockModemService());
         sMockModemManager = null;
     }
 
+    @Before
+    public void beforeTest() {
+        assumeTrue(hasTelephonyFeature());
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getInstrumentation().getContext();
     }
 
+    private static boolean hasTelephonyFeature() {
+        final PackageManager pm = getContext().getPackageManager();
+        if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+            return false;
+        }
+        return true;
+    }
+
     @Test
     public void testSimStateChange() throws Throwable {
         Log.d(TAG, "TelephonyManagerTestOnMockModem#testSimStateChange");
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
index 1ce51e3..d8381fd 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
@@ -106,7 +106,13 @@
                 Log.e(TAG, "Failed to flush SharedFilter");
                 return false;
             }
-            f.read(new byte[3], 0, 3);
+            int size = f.read(new byte[3], 0, 3);
+            if (size < 0 || size > 3) {
+                f.close();
+                f = null;
+                Log.e(TAG, "Failed to read from SharedFilter");
+                return false;
+            }
             if (f.stop() != Tuner.RESULT_SUCCESS) {
                 f.close();
                 f = null;
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index d633eef..626f08d 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -2242,7 +2242,8 @@
 
         assertEquals(f.start(), Tuner.RESULT_SUCCESS);
         assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
-        assertTrue(f.read(new byte[3], 0, 3) != 0);
+        int size = f.read(new byte[3], 0, 3);
+        assertTrue(size >= 0 && size <= 3);
         assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
 
         mLockLatch = new CountDownLatch(1);
@@ -2273,7 +2274,8 @@
 
         assertEquals(f.start(), Tuner.RESULT_SUCCESS);
         assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
-        assertTrue(f.read(new byte[3], 0, 3) != 0);
+        int size = f.read(new byte[3], 0, 3);
+        assertTrue(size >= 0 && size <= 3);
         assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
 
         mLockLatch = new CountDownLatch(1);
@@ -2303,7 +2305,8 @@
 
         assertEquals(f.start(), Tuner.RESULT_SUCCESS);
         assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
-        assertTrue(f.read(new byte[3], 0, 3) != 0);
+        int size = f.read(new byte[3], 0, 3);
+        assertTrue(size >= 0 && size <= 3);
         assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
 
         mLockLatch = new CountDownLatch(1);
diff --git a/tests/tests/uidmigration/Android.bp b/tests/tests/uidmigration/Android.bp
index 92db2e1..4f98ae6 100644
--- a/tests/tests/uidmigration/Android.bp
+++ b/tests/tests/uidmigration/Android.bp
@@ -24,6 +24,7 @@
         "androidx.test.rules",
         "ctstestrunner-axt",
         "permission-test-util-lib",
+        "services.core",
         "CtsSharedUserMigrationTestLibs",
     ],
     libs: [
@@ -36,5 +37,5 @@
         "cts",
         "general-tests",
     ],
-    sdk_version: "test_current",
+    platform_apis: true,
 }
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
new file mode 100644
index 0000000..ec3c206
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.uidmigration.cts
+
+import android.Manifest.permission.INTERNET
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PackageInfoFlags
+import android.permission.cts.PermissionUtils
+import android.permission.cts.PermissionUtils.isPermissionGranted
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.server.pm.SharedUidMigration.LIVE_TRANSITION
+import org.junit.After
+import org.junit.Assert.assertArrayEquals
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.ByteArrayInputStream
+import java.nio.charset.StandardCharsets.UTF_8
+import java.security.Signature
+import java.security.cert.CertificateFactory
+import java.security.cert.X509Certificate
+import java.util.UUID
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.BlockingQueue
+import java.util.concurrent.TimeUnit
+
+// All tests ignored: appId migration is disabled (http://b/220015249)
+@RunWith(AndroidJUnit4::class)
+class AppIdMigrationTest {
+
+    companion object {
+        private const val RESULT_KEY = "result"
+        private val NOT_AN_ERROR = Throwable()
+    }
+
+    private lateinit var mContext: Context
+    private lateinit var mPm: PackageManager
+
+    @Before
+    fun setup() {
+        mContext = ApplicationProvider.getApplicationContext<Context>()
+        mPm = mContext.packageManager
+    }
+
+    @After
+    fun tearDown() {
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        uninstallPackage(Const.PERM_TEST_PKG)
+        uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
+        uninstallPackage(Const.DATA_TEST_PKG)
+    }
+
+    @Ignore
+    @Test
+    fun testAppInstall() = withStrategy(LIVE_TRANSITION) {
+        assertTrue(installPackage(InstallTest.APK))
+        assertTrue(installPackage(InstallTest.APK2))
+
+        // Both app should share the same UID.
+        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(2, pkgs.size)
+
+        // Should not allow upgrading to an APK that directly removes sharedUserId.
+        assertFalse(installPackage(InstallTest.APK3))
+
+        // Leave shared UID.
+        assertTrue(installPackage(InstallTest.APK4))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(1, pkgs.size)
+
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+    }
+
+    @Ignore
+    @Test
+    fun testPermissionMigration() = withStrategy(LIVE_TRANSITION) {
+        val apk = "$TMP_APK_PATH/PermissionTestApp"
+        assertTrue(installPackage(apk + "1.apk"))
+        assertTrue(installPackage(apk + "2.apk"))
+        val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+
+        // Runtime permissions are not granted by default.
+        assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+        // Grant a runtime permission.
+        PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
+
+        // All apps in the UID group should have the same permissions.
+        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+        // Upgrade and leave shared UID.
+        assertTrue(installPackage(apk + "3.apk"))
+
+        // The app in the original UID group should no longer have the permissions.
+        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+
+        // The upgraded app should still have the permissions.
+        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+        uninstallPackage(Const.PERM_TEST_PKG)
+        uninstallPackage(secondaryPkg)
+    }
+
+    @Ignore
+    @Test
+    fun testDataMigration() = withStrategy(LIVE_TRANSITION) {
+        val apk = "$TMP_APK_PATH/DataTestApp"
+        assertTrue(installPackage(apk + "1.apk"))
+        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        val authority = Const.DATA_TEST_PKG + ".provider"
+        val resolver = mContext.contentResolver
+
+        // Ask the app to generate a new random UUID and persist in data.
+        var result = resolver.call(authority, "data", null, null).assertNotNull()
+        val oldUUID = result.getString(RESULT_KEY).assertNotNull()
+
+        val receiver = PackageBroadcastReceiver(oldUid)
+        IntentFilter().apply {
+            addAction(Intent.ACTION_PACKAGE_REMOVED)
+            addAction(Intent.ACTION_PACKAGE_ADDED)
+            addAction(Intent.ACTION_PACKAGE_REPLACED)
+            addDataScheme("package")
+            mContext.registerReceiver(receiver, this)
+        }
+        IntentFilter().apply {
+            addAction(Intent.ACTION_UID_REMOVED)
+            addAction(Const.ACTION_UPDATE_ACK)
+            mContext.registerReceiver(receiver, this)
+        }
+
+        // Update the data test APK and make sure UID changed.
+        assertTrue(installPackage(apk + "2.apk"))
+        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        assertNotEquals(oldUid, newUid)
+
+        // Ensure system broadcasts are delivered properly.
+        try {
+            val e = receiver.poll(30, TimeUnit.SECONDS)
+            if (e !== NOT_AN_ERROR) {
+                throw AssertionError(e)
+            }
+        } catch (e: InterruptedException) {
+            fail(e.message)
+        }
+        assertEquals(newUid, receiver.newUid)
+        mContext.unregisterReceiver(receiver)
+
+        // Ask the app again for a UUID. If data migration is working, it shall be the same.
+        result = resolver.call(authority, "data", null, null).assertNotNull()
+        val newUUID = result.getString(RESULT_KEY)
+        assertEquals(oldUUID, newUUID)
+        uninstallPackage(Const.DATA_TEST_PKG)
+    }
+
+    @Ignore
+    @Test
+    fun testKeyMigration() = withStrategy(LIVE_TRANSITION) {
+        val apk = "$TMP_APK_PATH/DataTestApp"
+        assertTrue(installPackage(apk + "1.apk"))
+        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        val authority = Const.DATA_TEST_PKG + ".provider"
+        val resolver = mContext.contentResolver
+        val secret = UUID.randomUUID().toString()
+
+        // Ask the app to encrypt secret with AES.
+        var result = resolver.call(authority, "encryptAES", secret, null).assertNotNull()
+        assertNotNull(result[RESULT_KEY])
+        assertNotNull(result["iv"])
+        val encResult = result
+
+        // Ask the app to generate a new EC keypair and sign our data.
+        result = resolver.call(authority, "signEC", secret, null).assertNotNull()
+        val signature = result.getByteArray(RESULT_KEY).assertNotNull()
+        val oldCertChain = result.getByteArray("certChain").assertNotNull()
+
+        // Update the data test APK and make sure UID changed.
+        assertTrue(installPackage(apk + "2.apk"))
+        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+        assertNotEquals(oldUid, newUid)
+
+        // Ask the app to decrypt our secret.
+        result = resolver.call(authority, "decryptAES", null, encResult).assertNotNull()
+        val decSecret = result.getString(RESULT_KEY)
+        assertEquals(secret, decSecret)
+
+        // Ask the app to return the previously generated EC certificate.
+        result = resolver.call(authority, "getECCert", null, null).assertNotNull()
+        val rawCert = result.getByteArray(RESULT_KEY).assertNotNull()
+        val newCertChain = result.getByteArray("certChain").assertNotNull()
+        val cf = CertificateFactory.getInstance("X.509")
+        val cert = cf.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate
+
+        // Verify the signature and cert.
+        assertArrayEquals(oldCertChain, newCertChain)
+        val s = Signature.getInstance("SHA256withECDSA")
+        s.initVerify(cert)
+        s.update(secret.toByteArray(UTF_8))
+        assertTrue(s.verify(signature))
+        uninstallPackage(Const.DATA_TEST_PKG)
+    }
+
+    class PackageBroadcastReceiver(
+        private val mPreviousUid: Int
+    ) : BroadcastReceiver(), BlockingQueue<Throwable?> by ArrayBlockingQueue<Throwable?>(1) {
+
+        var newUid = -1
+            private set
+        private var mCounter = 0
+
+        override fun onReceive(context: Context?, intent: Intent) {
+            try {
+                verifyInternal(intent)
+            } catch (e: Throwable) {
+                offer(e)
+            }
+        }
+
+        private fun verifyInternal(intent: Intent) {
+            val action = intent.action
+            assertNotNull(action)
+            if (action == Intent.ACTION_UID_REMOVED) {
+                // Not the test package, none of our business.
+                if (intent.getIntExtra(Intent.EXTRA_UID, -1) != mPreviousUid) {
+                    return
+                }
+            }
+            val data = intent.data
+            if (data != null) {
+                assertEquals("package", data.scheme)
+                val pkg = data.schemeSpecificPart
+                assertNotNull(pkg)
+                // Not the test package, none of our business.
+                if (Const.DATA_TEST_PKG != pkg) {
+                    return
+                }
+            }
+
+            // Broadcasts must come in the following order:
+            // ACTION_PACKAGE_REMOVED -> ACTION_UID_REMOVED
+            // -> ACTION_PACKAGE_ADDED -> ACTION_UPDATE_ACK
+            mCounter++
+            when (action) {
+                Intent.ACTION_PACKAGE_REMOVED -> {
+                    assertEquals(1, mCounter)
+                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_UID, -1))
+                    newUid = intent.getIntExtra(Intent.EXTRA_NEW_UID, -1)
+                    assertNotEquals(mPreviousUid, newUid)
+                }
+                Intent.ACTION_UID_REMOVED -> {
+                    assertEquals(2, mCounter)
+                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+                    assertEquals(
+                        Const.DATA_TEST_PKG,
+                        intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
+                    )
+                }
+                Intent.ACTION_PACKAGE_ADDED -> {
+                    assertEquals(3, mCounter)
+                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, mPreviousUid))
+                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_PREVIOUS_UID, -1))
+                }
+                Const.ACTION_UPDATE_ACK -> {
+                    assertEquals(4, mCounter)
+                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, -2))
+                    // End of actions
+                    offer(NOT_AN_ERROR)
+                }
+                Intent.ACTION_PACKAGE_REPLACED -> fail("PACKAGE_REPLACED should not be called!")
+                else -> fail("Unknown action received")
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
new file mode 100644
index 0000000..a525ff8
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uidmigration.cts
+
+import android.content.pm.PackageManager
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration
+import com.android.server.pm.SharedUidMigration.PROPERTY_KEY
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+
+const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
+
+val FLAG_ZERO = PackageManager.PackageInfoFlags.of(0)
+
+// What each APK meant
+// APK : pkg , with sharedUserId
+// APK2: pkg2, with sharedUserId
+// APK3: pkg , with sharedUserId removed
+// APK4: pkg , with sharedUserMaxSdkVersion="32"
+
+object InstallTest {
+    const val APK = "$TMP_APK_PATH/InstallTestApp.apk"
+    const val APK2 = "$TMP_APK_PATH/InstallTestApp2.apk"
+    const val APK3 = "$TMP_APK_PATH/InstallTestApp3.apk"
+    const val APK4 = "$TMP_APK_PATH/InstallTestApp4.apk"
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun <T> T?.assertNotNull(): T {
+    assertNotNull(this)
+    return this!!
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
+
+fun installPackage(apkPath: String): Boolean {
+    return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
+}
+
+fun uninstallPackage(packageName: String) {
+    runShellCommand("pm uninstall $packageName")
+}
+
+@SharedUidMigration.Strategy
+var migrationStrategy: Int
+    get() = SharedUidMigration.getCurrentStrategy()
+    set(value) { runShellCommand("setprop $PROPERTY_KEY $value") }
+
+inline fun withStrategy(strategy: Int? = null, body: () -> Unit) {
+    if (SharedUidMigration.isDisabled()) {
+        // Nothing to test if shared UID migration is disabled
+        return
+    }
+
+    val backup = migrationStrategy
+    strategy?.let { migrationStrategy = it }
+    try {
+        body.invoke()
+    } finally {
+        // Always restore the device state no matter what happened
+        migrationStrategy = backup
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
index 911758f..3958a12 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,63 +13,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.uidmigration.cts
 
-import android.Manifest.permission.INTERNET
-import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
-import android.content.BroadcastReceiver
 import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
 import android.content.pm.PackageManager
-import android.content.pm.PackageManager.PackageInfoFlags
-import android.permission.cts.PermissionUtils
-import android.permission.cts.PermissionUtils.isPermissionGranted
+import android.os.Build
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration.BEST_EFFORT
+import com.android.server.pm.SharedUidMigration.NEW_INSTALL_ONLY
 import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.io.ByteArrayInputStream
-import java.nio.charset.StandardCharsets.UTF_8
-import java.security.Signature
-import java.security.cert.CertificateFactory
-import java.security.cert.X509Certificate
-import java.util.UUID
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import java.util.concurrent.TimeUnit
-import org.junit.Assert.assertArrayEquals
-import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 class SharedUserMigrationTest {
 
-    companion object {
-        private const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
-        private const val RESULT_KEY = "result"
-        private val NOT_AN_ERROR = Throwable()
-    }
-
     private lateinit var mContext: Context
     private lateinit var mPm: PackageManager
 
-    @Suppress("NOTHING_TO_INLINE")
-    private inline fun <T> T?.assertNotNull(): T {
-        assertNotNull(this)
-        return this!!
-    }
-
-    @Suppress("NOTHING_TO_INLINE")
-    private inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
-
     @Before
     fun setup() {
         mContext = ApplicationProvider.getApplicationContext<Context>()
@@ -80,248 +49,97 @@
     fun tearDown() {
         uninstallPackage(Const.INSTALL_TEST_PKG)
         uninstallPackage(Const.INSTALL_TEST_PKG + "2")
-        uninstallPackage(Const.PERM_TEST_PKG)
-        uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
-        uninstallPackage(Const.DATA_TEST_PKG)
     }
 
-    @Test
-    fun testAppInstall() {
-        val apk = "$TMP_APK_PATH/InstallTestApp"
-        assertTrue(installPackage("$apk.apk"))
-        assertTrue(installPackage(apk + "2.apk"))
-
-        // Both app should share the same UID.
-        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
-        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+    // Restore and ensure both test apps are sharing UID.
+    private fun reset(uid: Int) {
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        assertTrue(installPackage(InstallTest.APK))
+        val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         assertEquals(2, pkgs.size)
+    }
 
-        // Should not allow directly removing sharedUserId.
-        assertFalse(installPackage(apk + "3.apk"))
+    private fun testNewInstallOnly(uid: Int) {
+        migrationStrategy = NEW_INSTALL_ONLY
 
-        // Leave shared UID.
-        assertTrue(installPackage(apk + "4.apk"))
+        // Should not allow upgrading to an APK that directly removes sharedUserId.
+        assertFalse(installPackage(InstallTest.APK3))
+
+        // Directly parsing APK4 should return no sharedUserId.
+        var pkgInfo = mPm.getPackageArchiveInfo(InstallTest.APK4, FLAG_ZERO).assertNotNull()
+        assertNull(pkgInfo.sharedUserId)
+
+        assertTrue(installPackage(InstallTest.APK4))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // With NEW_INSTALL_ONLY, upgrades should not change appId.
+        assertEquals(2, pkgs.size)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNotNull(pkgInfo.sharedUserId)
+
+        // Should not allow re-joining sharedUserId.
+        assertFalse(installPackage(InstallTest.APK))
+
+        // Uninstall and install a new pkg leaving shared UID
+        uninstallPackage(Const.INSTALL_TEST_PKG)
+        assertTrue(installPackage(InstallTest.APK4))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // Newly installed apps with sharedUserMaxSdkVersion set should not join shared UID.
+        assertEquals(1, pkgs.size)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNull(pkgInfo.sharedUserId)
+    }
+
+    private fun testBestEffort(uid: Int) {
+        migrationStrategy = BEST_EFFORT
+
+        assertTrue(installPackage(InstallTest.APK4))
+        var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        // With BEST_EFFORT, upgrades should also not change appId.
+        assertEquals(2, pkgs.size)
+        var pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNotNull(pkgInfo.sharedUserId)
+
+        val oldUidName = mPm.getNameForUid(uid)
+        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+
+        // There should be only 1 package left in the shared UID group.
+        // This should trigger the transparent shared UID migration.
         pkgs = mPm.getPackagesForUid(uid).assertNotNull()
         assertEquals(1, pkgs.size)
 
-        // Should not allow re-joining sharedUserId.
-        assertFalse(installPackage("$apk.apk"))
+        // Confirm that the internal PackageSetting is actually migrated.
+        val newUidName = mPm.getNameForUid(uid)
+        assertNotEquals(oldUidName, newUidName)
+        pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        assertNull(pkgInfo.sharedUserId)
 
-        uninstallPackage(Const.INSTALL_TEST_PKG)
-        uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+        // Even installing another shared UID app, the appId shall not be reused.
+        assertTrue(installPackage(InstallTest.APK2))
+        pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(1, pkgs.size)
     }
 
     @Test
-    fun testPermissionMigration() {
-        val apk = "$TMP_APK_PATH/PermissionTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        assertTrue(installPackage(apk + "2.apk"))
-        val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+    fun testAppInstall() = withStrategy {
+        assertTrue(installPackage(InstallTest.APK))
+        assertTrue(installPackage(InstallTest.APK2))
 
-        // Runtime permissions are not granted by default.
-        assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+        // Both app should share the same UID.
+        val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+        val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+        assertEquals(2, pkgs.size)
 
-        // Grant a runtime permission.
-        PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
-
-        // All apps in the UID group should have the same permissions.
-        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
-        assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
-        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
-        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
-
-        // Upgrade and leave shared UID.
-        assertTrue(installPackage(apk + "3.apk"))
-
-        // The app in the original UID group should no longer have the permissions.
-        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
-        assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
-
-        // The upgraded app should still have the permissions.
-        assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
-        assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
-        uninstallPackage(Const.PERM_TEST_PKG)
-        uninstallPackage(secondaryPkg)
-    }
-
-    @Test
-    fun testDataMigration() {
-        val apk = "$TMP_APK_PATH/DataTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        val authority = Const.DATA_TEST_PKG + ".provider"
-        val resolver = mContext.contentResolver
-
-        // Ask the app to generate a new random UUID and persist in data.
-        var result = resolver.call(authority, "data", null, null).assertNotNull()
-        val oldUUID = result.getString(RESULT_KEY).assertNotNull()
-
-        val receiver = PackageBroadcastReceiver(oldUid)
-        IntentFilter().apply {
-            addAction(Intent.ACTION_PACKAGE_REMOVED)
-            addAction(Intent.ACTION_PACKAGE_ADDED)
-            addAction(Intent.ACTION_PACKAGE_REPLACED)
-            addDataScheme("package")
-            mContext.registerReceiver(receiver, this)
-        }
-        IntentFilter().apply {
-            addAction(Intent.ACTION_UID_REMOVED)
-            addAction(Const.ACTION_UPDATE_ACK)
-            mContext.registerReceiver(receiver, this)
-        }
-
-        // Update the data test APK and make sure UID changed.
-        assertTrue(installPackage(apk + "2.apk"))
-        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        assertNotEquals(oldUid, newUid)
-
-        // Ensure system broadcasts are delivered properly.
-        try {
-            val e = receiver.poll(5, TimeUnit.SECONDS)
-            if (e !== NOT_AN_ERROR) {
-                throw AssertionError(e)
-            }
-        } catch (e: InterruptedException) {
-            fail(e.message)
-        }
-        assertEquals(newUid, receiver.newUid)
-        mContext.unregisterReceiver(receiver)
-
-        // Ask the app again for a UUID. If data migration is working, it shall be the same.
-        result = resolver.call(authority, "data", null, null).assertNotNull()
-        val newUUID = result.getString(RESULT_KEY)
-        assertEquals(oldUUID, newUUID)
-        uninstallPackage(Const.DATA_TEST_PKG)
-    }
-
-    @Test
-    fun testKeyMigration() {
-        val apk = "$TMP_APK_PATH/DataTestApp"
-        assertTrue(installPackage(apk + "1.apk"))
-        val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        val authority = Const.DATA_TEST_PKG + ".provider"
-        val resolver = mContext.contentResolver
-        val secret = UUID.randomUUID().toString()
-
-        // Ask the app to encrypt secret with AES.
-        var result = resolver.call(authority, "encryptAES", secret, null).assertNotNull()
-        assertNotNull(result[RESULT_KEY])
-        assertNotNull(result["iv"])
-        val encResult = result
-
-        // Ask the app to generate a new EC keypair and sign our data.
-        result = resolver.call(authority, "signEC", secret, null).assertNotNull()
-        val signature = result.getByteArray(RESULT_KEY).assertNotNull()
-        val oldCertChain = result.getByteArray("certChain").assertNotNull()
-
-        // Update the data test APK and make sure UID changed.
-        assertTrue(installPackage(apk + "2.apk"))
-        val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
-        assertNotEquals(oldUid, newUid)
-
-        // Ask the app to decrypt our secret.
-        result = resolver.call(authority, "decryptAES", null, encResult).assertNotNull()
-        val decSecret = result.getString(RESULT_KEY)
-        assertEquals(secret, decSecret)
-
-        // Ask the app to return the previously generated EC certificate.
-        result = resolver.call(authority, "getECCert", null, null).assertNotNull()
-        val rawCert = result.getByteArray(RESULT_KEY).assertNotNull()
-        val newCertChain = result.getByteArray("certChain").assertNotNull()
-        val cf = CertificateFactory.getInstance("X.509")
-        val cert = cf.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate
-
-        // Verify the signature and cert.
-        assertArrayEquals(oldCertChain, newCertChain)
-        val s = Signature.getInstance("SHA256withECDSA")
-        s.initVerify(cert)
-        s.update(secret.toByteArray(UTF_8))
-        assertTrue(s.verify(signature))
-        uninstallPackage(Const.DATA_TEST_PKG)
-    }
-
-    private fun installPackage(apkPath: String): Boolean {
-        return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
-    }
-
-    private fun uninstallPackage(packageName: String) {
-        runShellCommand("pm uninstall $packageName")
-    }
-
-    class PackageBroadcastReceiver(
-        private val mPreviousUid: Int
-    ) : BroadcastReceiver(), BlockingQueue<Throwable?> by ArrayBlockingQueue<Throwable?>(1) {
-
-        var newUid = -1
-            private set
-        private var mCounter = 0
-
-        override fun onReceive(context: Context?, intent: Intent) {
-            try {
-                verifyInternal(intent)
-            } catch (e: Throwable) {
-                offer(e)
+        if (Build.IS_USERDEBUG) {
+            testNewInstallOnly(uid)
+            reset(uid)
+            testBestEffort(uid)
+        } else {
+            when (migrationStrategy) {
+                NEW_INSTALL_ONLY -> testNewInstallOnly(uid)
+                BEST_EFFORT -> testBestEffort(uid)
             }
         }
 
-        private fun verifyInternal(intent: Intent) {
-            val action = intent.action
-            assertNotNull(action)
-            if (action == Intent.ACTION_UID_REMOVED) {
-                // Not the test package, none of our business.
-                if (intent.getIntExtra(Intent.EXTRA_UID, -1) != mPreviousUid) {
-                    return
-                }
-            }
-            val data = intent.data
-            if (data != null) {
-                assertEquals("package", data.scheme)
-                val pkg = data.schemeSpecificPart
-                assertNotNull(pkg)
-                // Not the test package, none of our business.
-                if (Const.DATA_TEST_PKG != pkg) {
-                    return
-                }
-            }
-
-            // Broadcasts must come in the following order:
-            // ACTION_PACKAGE_REMOVED -> ACTION_UID_REMOVED
-            // -> ACTION_PACKAGE_ADDED -> ACTION_UPDATE_ACK
-            mCounter++
-            when (action) {
-                Intent.ACTION_PACKAGE_REMOVED -> {
-                    assertEquals(1, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_UID, -1))
-                    newUid = intent.getIntExtra(Intent.EXTRA_NEW_UID, -1)
-                    assertNotEquals(mPreviousUid, newUid)
-                }
-                Intent.ACTION_UID_REMOVED -> {
-                    assertEquals(2, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(
-                        Const.DATA_TEST_PKG,
-                        intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
-                    )
-                }
-                Intent.ACTION_PACKAGE_ADDED -> {
-                    assertEquals(3, mCounter)
-                    assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
-                    assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
-                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, mPreviousUid))
-                    assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_PREVIOUS_UID, -1))
-                }
-                Const.ACTION_UPDATE_ACK -> {
-                    assertEquals(4, mCounter)
-                    assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, -2))
-                    // End of actions
-                    offer(NOT_AN_ERROR)
-                }
-                Intent.ACTION_PACKAGE_REPLACED -> fail("PACKAGE_REPLACED should not be called!")
-                else -> fail("Unknown action received")
-            }
-        }
+        tearDown()
     }
 }
\ No newline at end of file
diff --git a/tests/tests/view/jni/ChoreographerTestUtils.h b/tests/tests/view/jni/ChoreographerTestUtils.h
index 83a23b7..58866a0 100644
--- a/tests/tests/view/jni/ChoreographerTestUtils.h
+++ b/tests/tests/view/jni/ChoreographerTestUtils.h
@@ -61,8 +61,8 @@
     std::chrono::nanoseconds frameTime{0LL};
 };
 
-struct ExtendedCallback : Callback {
-    ExtendedCallback(const char* name, JNIEnv* env) : Callback(name), env(env) {}
+struct VsyncCallback : Callback {
+    VsyncCallback(const char* name, JNIEnv* env) : Callback(name), env(env) {}
 
     struct FrameTime {
         FrameTime(const AChoreographerFrameCallbackData* callbackData, int index)
@@ -105,30 +105,30 @@
     std::vector<FrameTime> timeline;
 };
 
-static void extendedFrameCallback(int64_t frameTimeNanos, void* data) {
+static void vsyncCallback(int64_t frameTimeNanos, void* data) {
     std::lock_guard<std::mutex> _l(gLock);
-    ATrace_beginSection("extendedFrameCallback base");
+    ATrace_beginSection("vsyncCallback base");
     Callback* cb = static_cast<Callback*>(data);
     cb->count++;
     cb->frameTime = std::chrono::nanoseconds{frameTimeNanos};
     ATrace_endSection();
 }
 
-static void extendedFrameCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
-    ATrace_beginSection("extendedFrameCallback");
-    extendedFrameCallback(AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData), data);
+static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
+    ATrace_beginSection("vsyncCallback");
+    vsyncCallback(AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData), data);
 
-    ExtendedCallback* cb = static_cast<ExtendedCallback*>(data);
+    VsyncCallback* cb = static_cast<VsyncCallback*>(data);
     cb->populate(callbackData);
     ATrace_endSection();
 }
 
 static void frameCallback64(int64_t frameTimeNanos, void* data) {
-    extendedFrameCallback(frameTimeNanos, data);
+    vsyncCallback(frameTimeNanos, data);
 }
 
 static void frameCallback(long frameTimeNanos, void* data) {
-    extendedFrameCallback((int64_t)frameTimeNanos, data);
+    vsyncCallback((int64_t)frameTimeNanos, data);
 }
 
 static std::chrono::nanoseconds now() {
diff --git a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
index 5104b58..1ffa4ca 100644
--- a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
@@ -596,10 +596,10 @@
     ATrace_endSection();
     verifyChoreographer(env, choreographer);
 
-    ExtendedCallback cb1("cb1", env);
+    VsyncCallback cb1("cb1", env);
     auto start = now();
     ATrace_beginSection("postVsyncCallback");
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
     ATrace_endSection();
     auto delayPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
     ATrace_beginSection("ALooper_pollOnce");
@@ -621,7 +621,7 @@
         return NULL;
     }
     for (int i = 0; i < cb1.getTimeline().size(); i++) {
-        ExtendedCallback::FrameTime frameTimeline = cb1.getTimeline()[i];
+        VsyncCallback::FrameTime frameTimeline = cb1.getTimeline()[i];
         jobject frameTimelineObj =
                 env->NewObject(gFrameTimelineClassInfo.clazz, gFrameTimelineClassInfo.constructor,
                                frameTimeline.vsyncId, frameTimeline.expectedPresentTime,
diff --git a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
index 80f0759..f1e81ff 100644
--- a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
@@ -136,15 +136,15 @@
 }
 
 static void
-android_view_cts_ChoreographerNativeTest_testPostExtendedCallbackWithoutDelayEventuallyRunsCallback(
+android_view_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback(
         JNIEnv* env, jclass, jlong choreographerPtr) {
     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
-    ExtendedCallback cb1("cb1", env);
-    ExtendedCallback cb2("cb2", env);
+    VsyncCallback cb1("cb1", env);
+    VsyncCallback cb2("cb2", env);
     auto start = now();
 
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb2);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb2);
     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
 
     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -156,7 +156,7 @@
                "Callback 1 and 2 have frame times too large of a delta in frame times");
     }
 
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
     start = now();
     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
     verifyCallback(env, cb1, 2, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -166,19 +166,19 @@
 static void android_view_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid(
         JNIEnv* env, jclass, jlong choreographerPtr) {
     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
-    ExtendedCallback cb1("cb1", env);
+    VsyncCallback cb1("cb1", env);
     auto start = now();
 
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
 
     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
     std::lock_guard<std::mutex> _l{gLock};
-    for (const ExtendedCallback::FrameTime& frameTime : cb1.getTimeline()) {
+    for (const VsyncCallback::FrameTime& frameTime : cb1.getTimeline()) {
         int64_t vsyncId = frameTime.vsyncId;
         ASSERT(vsyncId >= 0, "Invalid vsync ID");
         ASSERT(std::count_if(cb1.getTimeline().begin(), cb1.getTimeline().end(),
-                             [vsyncId](const ExtendedCallback::FrameTime& ft) {
+                             [vsyncId](const VsyncCallback::FrameTime& ft) {
                                  return ft.vsyncId == vsyncId;
                              }) == 1,
                "Vsync ID is not unique");
@@ -188,10 +188,10 @@
 static void android_view_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture(
         JNIEnv* env, jclass, jlong choreographerPtr) {
     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
-    ExtendedCallback cb1("cb1", env);
+    VsyncCallback cb1("cb1", env);
     auto start = now();
 
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
 
     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -209,10 +209,10 @@
 android_view_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(
         JNIEnv* env, jclass, jlong choreographerPtr) {
     AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
-    ExtendedCallback cb1("cb1", env);
+    VsyncCallback cb1("cb1", env);
     auto start = now();
 
-    AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+    AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
     std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
 
     verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -550,8 +550,8 @@
          (void*)android_view_cts_ChoreographerNativeTest_getChoreographer},
         {"nativePrepareChoreographerTests", "(J[J)Z",
          (void*)android_view_cts_ChoreographerNativeTest_prepareChoreographerTests},
-        {"nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
-         (void*)android_view_cts_ChoreographerNativeTest_testPostExtendedCallbackWithoutDelayEventuallyRunsCallback},
+        {"nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
+         (void*)android_view_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback},
         {"nativeTestFrameCallbackDataVsyncIdValid", "(J)V",
          (void*)android_view_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid},
         {"nativeTestFrameCallbackDataDeadlineInFuture", "(J)V",
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
index 261895d..b9e7f11 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
@@ -75,7 +75,7 @@
     private static native void nativeTestPostCallback64WithoutDelayEventuallyRunsCallbacks(
             long ptr);
     private static native void nativeTestPostCallback64WithDelayEventuallyRunsCallbacks(long ptr);
-    private static native void nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks(
+    private static native void nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks(
             long ptr);
     private static native void nativeTestFrameCallbackDataVsyncIdValid(
             long ptr);
@@ -130,8 +130,8 @@
 
     @MediumTest
     @Test
-    public void testPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks() {
-        nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
+    public void testPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks() {
+        nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
     }
 
     @MediumTest
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerTest.java b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
index c74b4a1..6d2933a 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
@@ -38,6 +38,7 @@
 import org.mockito.ArgumentCaptor;
 
 import java.util.HashSet;
+import java.util.Set;
 
 @MediumTest
 @RunWith(AndroidJUnit4.class)
@@ -337,6 +338,26 @@
     }
 
     @Test
+    public void testPostVsyncCallbackFrameDataPreferredFrameTimelineValid() {
+        final Choreographer.VsyncCallback addedCallback = mock(
+                Choreographer.VsyncCallback.class);
+        long postTimeNanos = System.nanoTime();
+        mChoreographer.postVsyncCallback(addedCallback);
+
+        ArgumentCaptor<Choreographer.FrameData> captor = ArgumentCaptor.forClass(
+                Choreographer.FrameData.class);
+        verify(addedCallback, timeout(NOMINAL_VSYNC_PERIOD * 10).times(1)).onVsync(
+                captor.capture());
+
+        Choreographer.FrameData frameData = captor.getValue();
+        assertTrue("Number of frame timelines should be greater than 0",
+                frameData.getFrameTimelines().length > 0);
+        Set<Choreographer.FrameTimeline> frameTimelines = Set.of(frameData.getFrameTimelines());
+        assertTrue("Preferred frame timeline is not included in frame timelines",
+                frameTimelines.contains(frameData.getPreferredFrameTimeline()));
+    }
+
+    @Test
     public void testPostVsyncCallbackFrameDataVsyncIdValid() {
         final Choreographer.VsyncCallback addedCallback = mock(
                 Choreographer.VsyncCallback.class);
diff --git a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
index def377d..afca7b0 100644
--- a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
+++ b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
@@ -19,8 +19,8 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.app.Dialog;
-import android.view.OnBackInvokedCallback;
-import android.view.OnBackInvokedDispatcher;
+import android.window.OnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
index 0f2b760..7e81b08 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
@@ -238,7 +238,7 @@
                 mVirtualDeviceManager.createVirtualDevice(
                         mFakeAssociationRule.getAssociationInfo().getId(),
                         new VirtualDeviceParams.Builder()
-                                .setBlockedActivities(Set.of())
+                                .setBlockedActivities(Set.of(TestAppHelper.MAIN_ACTIVITY_COMPONENT))
                                 .build());
         VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
                 /* width= */ 100,
@@ -259,7 +259,8 @@
         EmptyActivity.Callback callback = mock(EmptyActivity.Callback.class);
         emptyActivity.setCallback(callback);
         final int requestCode = 1;
-        emptyActivity.startActivityForResult(TestAppHelper.createNoActionIntent(), requestCode);
+        emptyActivity.startActivityForResult(
+                TestAppHelper.createActivityLaunchedReceiverIntent(mResultReceiver), requestCode);
 
         verify(mOnReceiveResultListener, after(3000).never()).onReceiveResult(
                 eq(Activity.RESULT_OK),
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
index 423007a..789e63b 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
@@ -137,7 +137,7 @@
                         DEFAULT_VIRTUAL_DEVICE_PARAMS);
         ActivityListener activityListener = mock(ActivityListener.class);
         Executor mockExecutor = mock(Executor.class);
-        mVirtualDevice.addActivityListener(activityListener, mockExecutor);
+        mVirtualDevice.addActivityListener(mockExecutor, activityListener);
         VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
                 /* width= */ 100,
                 /* height= */ 100,
@@ -175,7 +175,7 @@
                         mFakeAssociationRule.getAssociationInfo().getId(),
                         DEFAULT_VIRTUAL_DEVICE_PARAMS);
         ActivityListener activityListener = mock(ActivityListener.class);
-        mVirtualDevice.addActivityListener(activityListener);
+        mVirtualDevice.addActivityListener(context.getMainExecutor(), activityListener);
         VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
                 /* width= */ 100,
                 /* height= */ 100,
@@ -210,7 +210,7 @@
                         mFakeAssociationRule.getAssociationInfo().getId(),
                         DEFAULT_VIRTUAL_DEVICE_PARAMS);
         ActivityListener activityListener = mock(ActivityListener.class);
-        mVirtualDevice.addActivityListener(activityListener);
+        mVirtualDevice.addActivityListener(context.getMainExecutor(), activityListener);
         VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
                 /* width= */ 100,
                 /* height= */ 100,
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
index 5db7500..205daae 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
@@ -26,8 +26,8 @@
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.TruthJUnit.assume;
 
-import static org.junit.Assume.assumeNotNull;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
@@ -91,6 +91,8 @@
     private Context mContext;
     @Mock
     private VirtualDisplay.Callback mVirtualDisplayCallback;
+    @Mock
+    private ActivityListener mActivityListener;
 
     @Before
     public void setUp() throws Exception {
@@ -101,6 +103,7 @@
                 mVirtualDeviceManager.createVirtualDevice(
                         mFakeAssociationRule.getAssociationInfo().getId(),
                         DEFAULT_VIRTUAL_DEVICE_PARAMS);
+        mVirtualDevice.addActivityListener(mContext.getMainExecutor(), mActivityListener);
         mVirtualDisplay = mVirtualDevice.createVirtualDisplay(
                 /* width= */ 100,
                 /* height= */ 100,
@@ -123,8 +126,6 @@
 
     @Test
     public void appsInVirtualDevice_shouldNotHaveAccessToClipboard() {
-        ActivityListener activityListener = mock(ActivityListener.class);
-        mVirtualDevice.addActivityListener(activityListener);
         ClipboardManager clipboardManager = mContext.getSystemService(ClipboardManager.class);
         clipboardManager.setPrimaryClip(
                 new ClipData(
@@ -158,7 +159,7 @@
         assertThat(resultData).isNotNull();
         ClipData appReadClipData = resultData.getParcelableExtra("readClip");
         assertThat(appReadClipData).isNull();
-        verify(activityListener, timeout(3000))
+        verify(mActivityListener, timeout(3000))
                 .onDisplayEmpty(eq(mVirtualDisplay.getDisplay().getDisplayId()));
         assertThat(clipboardManager.getPrimaryClip().getItemAt(0).getText().toString())
                 .isEqualTo("clipboard content from test");
@@ -168,7 +169,7 @@
     public void appsInVirtualDevice_shouldNotHaveAccessToCamera() throws CameraAccessException {
         CameraManager manager = mContext.getSystemService(CameraManager.class);
         String[] cameras = manager.getCameraIdList();
-        assumeNotNull(cameras);
+        assume().that(cameras).isNotNull();
 
         for (String cameraId : cameras) {
             EmptyActivity activity =
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index a703814..f3dbee4 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -20,7 +20,6 @@
      android:targetSandboxVersion="2">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
-    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
 
     <application android:label="Android TestCase"
diff --git a/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml b/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
index 4a3b211..1bad59c 100644
--- a/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
+++ b/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
@@ -23,7 +23,7 @@
     android:gravity="center" >
     <FrameLayout
         android:id="@+id/magnifier_centered_view"
-        android:layout_width="40dp"
-        android:layout_height="16dp"
+        android:layout_width="80dp"
+        android:layout_height="56dp"
         android:background="@android:color/holo_blue_bright" />
 </LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 6857891..c3a16f3 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -266,7 +266,7 @@
         assertNull(view.getParent());
         assertEquals(View.VISIBLE, view.getVisibility());
 
-        runOnMainAndDrawSync(view, mToast::show);
+        runOnMainAndDrawSync(view, () -> showToastWithNotificationPermission(mToast));
 
         // view will be attached to screen when show it
         assertEquals(View.VISIBLE, view.getVisibility());
@@ -277,7 +277,7 @@
     public void testShow_whenTextToast() throws Throwable {
         makeTextToast();
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertTextToastShownAndHidden();
     }
@@ -288,7 +288,7 @@
         // Measure the length of a long toast.
         makeTextToast();
         long start1 = SystemClock.uptimeMillis();
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
         assertTextToastShownAndHidden();
         long longDurationMs = SystemClock.uptimeMillis() - start1;
@@ -296,10 +296,10 @@
         // Call show in the middle of the toast duration.
         makeTextToast();
         long start2 = SystemClock.uptimeMillis();
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
         SystemClock.sleep(longDurationMs / 2);
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertTextToastShownAndHidden();
         long repeatCallDurationMs = SystemClock.uptimeMillis() - start2;
 
@@ -315,7 +315,7 @@
         // Measure the length of a long toast.
         makeCustomToast();
         long start1 = SystemClock.uptimeMillis();
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
         assertCustomToastShownAndHidden(mToast.getView());
         long longDurationMs = SystemClock.uptimeMillis() - start1;
@@ -323,10 +323,10 @@
         // Call show in the middle of the toast duration.
         makeCustomToast();
         long start2 = SystemClock.uptimeMillis();
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
         SystemClock.sleep(longDurationMs / 2);
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
         assertCustomToastShownAndHidden(mToast.getView());
         long repeatCallDurationMs = SystemClock.uptimeMillis() - start2;
 
@@ -342,7 +342,7 @@
         Toast toast = new Toast(mContext);
         // do not have any views or text
         assertNull(toast.getView());
-        toast.show();
+        showToastWithNotificationPermission(mToast);
     }
 
     @Test
@@ -354,7 +354,7 @@
         // view has not been attached to screen yet
         assertNull(view.getParent());
         mActivityRule.runOnUiThread(() -> {
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
             mToast.cancel();
         });
 
@@ -372,7 +372,7 @@
 
         runOnMainAndDrawSync(imageView, () -> {
             mToast.setView(imageView);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
         });
         assertSame(imageView, mToast.getView());
         assertCustomToastShownAndHidden(imageView);
@@ -382,7 +382,8 @@
     public void testAccessDuration_whenCustomToast() throws Throwable {
         long start = SystemClock.uptimeMillis();
         makeCustomToast();
-        runOnMainAndDrawSync(mToast.getView(), mToast::show);
+        runOnMainAndDrawSync(mToast.getView(),
+                () -> showToastWithNotificationPermission(mToast));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
 
         View view = mToast.getView();
@@ -392,7 +393,7 @@
         start = SystemClock.uptimeMillis();
         runOnMainAndDrawSync(mToast.getView(), () -> {
             mToast.setDuration(Toast.LENGTH_SHORT);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
         });
         assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
 
@@ -407,7 +408,7 @@
     public void testAccessDuration_whenTextToast() throws Throwable {
         long start = SystemClock.uptimeMillis();
         makeTextToast();
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToast(mToast, true));
         assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
 
         assertTextToastShownAndHidden();
@@ -417,7 +418,7 @@
         makeTextToast();
         mActivityRule.runOnUiThread(() -> {
             mToast.setDuration(Toast.LENGTH_SHORT);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
         });
         assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
 
@@ -432,7 +433,7 @@
         makeCustomToast();
         final Runnable showToast = () -> {
             mToast.setDuration(Toast.LENGTH_SHORT);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
         };
         long start = SystemClock.uptimeMillis();
         runOnMainAndDrawSync(mToast.getView(), showToast);
@@ -463,7 +464,7 @@
         makeTextToast();
         final Runnable showToast = () -> {
             mToast.setDuration(Toast.LENGTH_SHORT);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
         };
         long start = SystemClock.uptimeMillis();
         mActivityRule.runOnUiThread(showToast);
@@ -536,7 +537,7 @@
         final float vertical1 = 1.0f;
         runOnMainAndDrawSync(view, () -> {
             mToast.setMargin(horizontal1, vertical1);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
             registerLayoutListener(mToast.getView());
         });
         assertCustomToastShown(view);
@@ -556,7 +557,7 @@
         final float vertical2 = 0.1f;
         runOnMainAndDrawSync(view, () -> {
             mToast.setMargin(horizontal2, vertical2);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
             registerLayoutListener(mToast.getView());
         });
         assertCustomToastShown(view);
@@ -594,7 +595,7 @@
         makeCustomToast();
         runOnMainAndDrawSync(mToast.getView(), () -> {
             mToast.setGravity(Gravity.CENTER, 0, 0);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
             registerLayoutListener(mToast.getView());
         });
         View view = mToast.getView();
@@ -609,7 +610,7 @@
 
         runOnMainAndDrawSync(mToast.getView(), () -> {
             mToast.setGravity(Gravity.BOTTOM, 0, 0);
-            mToast.show();
+            showToastWithNotificationPermission(mToast);
             registerLayoutListener(mToast.getView());
         });
         view = mToast.getView();
@@ -765,7 +766,7 @@
                     mToast.removeCallback(testCallback);
                 });
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertTextToastShownAndHidden();
         assertFalse(toastShown.isDone());
@@ -788,7 +789,7 @@
                     mToast.addCallback(new ConditionCallback(toastShown, toastHidden));
                 });
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertTrue(toastShown.block(TIME_OUT));
         assertTrue(toastHidden.block(TIME_OUT));
@@ -802,17 +803,20 @@
         mActivityRule.runOnUiThread(
                 () -> mToast.addCallback(new ConditionCallback(toastShown, toastHidden)));
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertTrue(toastShown.block(TIME_OUT));
         assertTrue(toastHidden.block(TIME_OUT));
     }
 
     @Test
-    public void testTextToastAllowed_whenInTheForeground() throws Throwable {
+    public void testTextToastAllowed_whenInTheForeground()
+            throws Throwable {
         makeTextToast();
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(
+                () -> showToastWithoutNotificationPermission(mToast)
+        );
 
         assertTextToastShownAndHidden();
     }
@@ -824,24 +828,43 @@
         // View has not been attached to screen yet
         assertNull(view.getParent());
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(
+                () -> showToastWithoutNotificationPermission(mToast)
+        );
 
         assertCustomToastShownAndHidden(view);
     }
 
     @Test
-    public void testTextToastAllowed_whenInTheBackground() throws Throwable {
+    public void testTextToastAllowed_whenInTheBackground_withNotificationPermission()
+            throws Throwable {
         assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
         // Make it background
         mActivityRule.finishActivity();
         makeTextToast();
 
-        mActivityRule.runOnUiThread(mToast::show);
-
+        mActivityRule.runOnUiThread(
+                () -> showToastWithNotificationPermission(mToast)
+        );
         assertTextToastShownAndHidden();
     }
 
     @Test
+    public void testTextToastNotAllowed_whenInTheBackground_withoutNotificationPermission()
+            throws Throwable {
+        assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
+        // Make it background
+        mActivityRule.finishActivity();
+        List<TextToastInfo> toastInfoList = createTextToasts(1, "Text", Toast.LENGTH_SHORT);
+
+        mActivityRule.runOnUiThread(
+                () -> showToastWithoutNotificationPermission(toastInfoList.get(0).getToast())
+        );
+
+        assertTextToastNotShown(toastInfoList.get(0));
+    }
+
+    @Test
     public void testCustomToastBlocked_whenInTheBackground() throws Throwable {
         // Make it background
         mActivityRule.finishActivity();
@@ -850,7 +873,7 @@
         // View has not been attached to screen yet
         assertNull(view.getParent());
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertCustomToastNotShown(view);
     }
@@ -870,7 +893,7 @@
         makeCustomToast();
         View view = mToast.getView();
 
-        mActivityRule.runOnUiThread(mToast::show);
+        mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
 
         assertCustomToastNotShown(view);
 
@@ -906,8 +929,10 @@
                 event -> event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
 
         AccessibilityEvent event = mUiAutomation.executeAndWaitForEvent(
-                () -> uncheck(() -> mActivityRule.runOnUiThread(mToast::show)), filter, TIME_OUT);
-
+                () -> uncheck(() -> mActivityRule.runOnUiThread(
+                        () -> showToastWithNotificationPermission(mToast))),
+                filter,
+                TIME_OUT);
         assertThat(event.getEventType()).isEqualTo(
                 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
         assertThat(event.getClassName()).isEqualTo(Toast.class.getCanonicalName());
@@ -922,7 +947,10 @@
                 event -> event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
 
         AccessibilityEvent event = mUiAutomation.executeAndWaitForEvent(
-                () -> uncheck(() -> mActivityRule.runOnUiThread(mToast::show)), filter, TIME_OUT);
+                () -> uncheck(() -> mActivityRule.runOnUiThread(
+                        () -> showToastWithNotificationPermission(mToast))),
+                filter,
+                TIME_OUT);
 
         assertThat(event.getEventType()).isEqualTo(
                 AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
@@ -1063,14 +1091,14 @@
     private void showToasts(List<? extends ToastInfo> toasts) throws Throwable {
         mActivityRule.runOnUiThread(() -> {
             for (ToastInfo t : toasts) {
-                t.getToast().show();
+                showToast(t.getToast(), /* run with POST_NOTIFICATION permission */true);
             }
         });
     }
 
     private void showToast(ToastInfo toast) throws Throwable {
         mActivityRule.runOnUiThread(() -> {
-            toast.getToast().show();
+            showToast(toast.getToast(), /* run with POST_NOTIFICATION permission */true);
         });
     }
 
@@ -1144,6 +1172,22 @@
         }
     }
 
+    private static void showToastWithNotificationPermission(Toast toast) {
+        showToast(toast, true);
+    }
+
+    private static void showToastWithoutNotificationPermission(Toast toast) {
+        showToast(toast, false);
+    }
+
+    private static void showToast(Toast toast, boolean runWithPostNotificationPermission) {
+        if (runWithPostNotificationPermission) {
+            SystemUtil.runWithShellPermissionIdentity(() -> toast.show());
+        } else {
+            toast.show();
+        }
+    }
+
     private interface ThrowingRunnable {
         void run() throws Throwable;
     }
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 5a3b86e..711e098 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
@@ -540,10 +540,12 @@
         assertTrue("Max number of Subscribe sessions",
                 characteristics.getNumberOfSupportedSubscribeSessions() > 0);
         if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) {
-            mWifiAwareManager.enableInstantCommunicationMode(true);
+            ShellIdentityUtils.invokeWithShellPermissions(() ->
+                    mWifiAwareManager.enableInstantCommunicationMode(true));
             assertEquals(mWifiAwareManager.isInstantCommunicationModeEnabled(),
                     characteristics.isInstantCommunicationModeSupported());
-            mWifiAwareManager.enableInstantCommunicationMode(false);
+            ShellIdentityUtils.invokeWithShellPermissions(() ->
+                    mWifiAwareManager.enableInstantCommunicationMode(false));
         }
     }
 
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 d1f750d..ed2342d 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -134,6 +134,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@@ -4699,6 +4700,57 @@
     }
 
     /**
+     * Verify the invalid and valid usages of {@code WifiManager#getAutojoinGlobal}.
+     */
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+    public void testGetAutojoinGlobal() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        AtomicBoolean enabled = new AtomicBoolean(false);
+        Consumer<Boolean> listener = new Consumer<Boolean>() {
+            @Override
+            public void accept(Boolean value) {
+                synchronized (mLock) {
+                    enabled.set(value);
+                    mLock.notify();
+                }
+            }
+        };
+        // Test invalid inputs trigger IllegalArgumentException
+        assertThrows("null executor should trigger exception", NullPointerException.class,
+                () -> mWifiManager.getAutojoinGlobal(null, listener));
+        assertThrows("null listener should trigger exception", NullPointerException.class,
+                () -> mWifiManager.getAutojoinGlobal(mExecutor, null));
+
+        // Test caller with no permission triggers SecurityException.
+        assertThrows("No permission should trigger SecurityException", SecurityException.class,
+                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+
+        // Test get/set autojoin global enabled
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.allowAutojoinGlobal(true));
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+        synchronized (mLock) {
+            mLock.wait(TEST_WAIT_DURATION_MS);
+        }
+        assertTrue(enabled.get());
+
+        // Test get/set autojoin global disabled
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.allowAutojoinGlobal(false));
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+        synchronized (mLock) {
+            mLock.wait(TEST_WAIT_DURATION_MS);
+        }
+        assertFalse(enabled.get());
+    }
+
+    /**
      * Tests {@link WifiManager#isWapiSupported()} does not crash.
      */
     public void testIsWapiSupported() throws Exception {
@@ -5502,7 +5554,7 @@
 
     /**
      * Tests
-     * {@link WifiManager#reportImpactToCreateIfaceRequest(int, boolean, Executor, BiConsumer)}.
+     * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}.
      */
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
     public void testIsItPossibleToCreateInterface() throws Exception {
@@ -5513,7 +5565,7 @@
 
         AtomicBoolean called = new AtomicBoolean(false);
         AtomicBoolean canBeCreated = new AtomicBoolean(false);
-        assertThrows(SecurityException.class, () -> mWifiManager.reportImpactToCreateIfaceRequest(
+        assertThrows(SecurityException.class, () -> mWifiManager.reportCreateInterfaceImpact(
                 WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor,
                 (canBeCreatedLocal, interfacesWhichWillBeDeleted) -> {
                     synchronized (mLock) {
diff --git a/tests/translation/src/android/translation/cts/TranslationManagerTest.java b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
index fa21041..67fa455 100644
--- a/tests/translation/src/android/translation/cts/TranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
@@ -21,6 +21,7 @@
 import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.RESUMED;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.app.Application;
 import android.app.PendingIntent;
@@ -42,6 +43,7 @@
 import android.view.translation.TranslationSpec;
 import android.view.translation.Translator;
 
+import androidx.annotation.NonNull;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -120,7 +122,7 @@
     }
 
     @Test
-    public void testTranslationCapabilityUpdateListener() throws Exception{
+    public void testTranslationCapabilityUpdateListener() throws Exception {
         // enable cts translation service
         enableCtsTranslationService();
 
@@ -128,9 +130,9 @@
         // text to text capability
         final TranslationCapability updatedText2TextCapability =
                 new TranslationCapability(TranslationCapability.STATE_ON_DEVICE,
-                new TranslationSpec(ULocale.ENGLISH, DATA_FORMAT_TEXT),
-                new TranslationSpec(ULocale.FRENCH, DATA_FORMAT_TEXT),
-                true, 0);
+                        new TranslationSpec(ULocale.ENGLISH, DATA_FORMAT_TEXT),
+                        new TranslationSpec(ULocale.FRENCH, DATA_FORMAT_TEXT),
+                        true, 0);
         // text to image capability
         final TranslationCapability updatedText2ImageCapability =
                 new TranslationCapability(TranslationCapability.STATE_ON_DEVICE,
@@ -198,7 +200,7 @@
     }
 
     @Test
-    public void testSingleTranslation() throws Exception{
+    public void testSingleTranslation() throws Exception {
         enableCtsTranslationService();
 
         final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -211,26 +213,7 @@
                                 .build())
                         .build());
 
-        final TranslationContext translationContext = new TranslationContext.Builder(
-                new TranslationSpec(ULocale.ENGLISH,
-                        TranslationSpec.DATA_FORMAT_TEXT),
-                new TranslationSpec(ULocale.FRENCH,
-                        TranslationSpec.DATA_FORMAT_TEXT))
-                .build();
-
-        final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
-        final AtomicReference<Translator> translatorRef = new AtomicReference<>();
-        manager.createOnDeviceTranslator(translationContext, r -> r.run(),
-                new Consumer<Translator>() {
-                    @Override
-                    public void accept(Translator translator) {
-                        createTranslatorLatch.countDown();
-                        translatorRef.set(translator);
-                    }
-                });
-
-        createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
-        final Translator translator = translatorRef.get();
+        final Translator translator = createTranslator(manager, createTranslationContext());
 
         try {
             mServiceWatcher.waitOnConnected();
@@ -246,13 +229,10 @@
         values.add(TranslationRequestValue.forText("hello world"));
         translator.translate(new TranslationRequest.Builder()
                         .setTranslationRequestValues(values)
-                        .build(), new CancellationSignal(), (r) -> r.run(),
-                new Consumer<TranslationResponse>() {
-                    @Override
-                    public void accept(TranslationResponse translationResponse) {
-                        responseRef.set(translationResponse);
-                        translationLatch.countDown();
-                    }
+                        .build(), new CancellationSignal(), Runnable::run,
+                translationResponse -> {
+                    responseRef.set(translationResponse);
+                    translationLatch.countDown();
                 });
 
         sTranslationReplier.getNextTranslationRequest();
@@ -293,7 +273,7 @@
     }
 
     @Test
-    public void testTranslation_partialResponses() throws Exception{
+    public void testTranslation_partialResponses() throws Exception {
         enableCtsTranslationService();
 
         final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -314,23 +294,7 @@
                         .setFinalResponse(true)
                         .build());
 
-        final TranslationContext translationContext = new TranslationContext.Builder(
-                new TranslationSpec(ULocale.ENGLISH,
-                        TranslationSpec.DATA_FORMAT_TEXT),
-                new TranslationSpec(ULocale.FRENCH,
-                        TranslationSpec.DATA_FORMAT_TEXT))
-                .build();
-
-        final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
-        final AtomicReference<Translator> translatorRef = new AtomicReference<>();
-        manager.createOnDeviceTranslator(translationContext, r -> r.run(),
-                translator -> {
-                    createTranslatorLatch.countDown();
-                    translatorRef.set(translator);
-                });
-
-        createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
-        final Translator translator = translatorRef.get();
+        final Translator translator = createTranslator(manager, createTranslationContext());
 
         try {
             mServiceWatcher.waitOnConnected();
@@ -343,13 +307,13 @@
 
         final CountDownLatch translationLatch = new CountDownLatch(2);
         final AtomicReference<List<TranslationResponse>> responsesRef = new AtomicReference<>();
-        responsesRef.set(new ArrayList<TranslationResponse>());
+        responsesRef.set(new ArrayList<>());
         final ArrayList<TranslationRequestValue> values = new ArrayList<>();
         values.add(TranslationRequestValue.forText("hello world"));
         translator.translate(new TranslationRequest.Builder()
                         .setTranslationRequestValues(values)
                         .setFlags(TranslationRequest.FLAG_PARTIAL_RESPONSES)
-                        .build(), new CancellationSignal(), (r) -> r.run(),
+                        .build(), new CancellationSignal(), Runnable::run,
                 translationResponse -> {
                     responsesRef.getAndUpdate(responses -> {
                         responses.add(translationResponse);
@@ -406,7 +370,7 @@
     }
 
     @Test
-    public void testTranslationCancelled() throws Exception{
+    public void testTranslationCancelled() throws Exception {
         enableCtsTranslationService();
 
         final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -419,27 +383,7 @@
                                 .build())
                         .build());
 
-        final CountDownLatch translationLatch = new CountDownLatch(1);
-        final AtomicReference<TranslationResponse> responseRef = new AtomicReference<>();
-
-        final TranslationContext translationContext = new TranslationContext.Builder(
-                new TranslationSpec(ULocale.ENGLISH, TranslationSpec.DATA_FORMAT_TEXT),
-                new TranslationSpec(ULocale.FRENCH, TranslationSpec.DATA_FORMAT_TEXT))
-                .build();
-
-        final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
-        final AtomicReference<Translator> translatorRef = new AtomicReference<>();
-        manager.createOnDeviceTranslator(translationContext, r -> r.run(),
-                new Consumer<Translator>() {
-                    @Override
-                    public void accept(Translator translator) {
-                        createTranslatorLatch.countDown();
-                        translatorRef.set(translator);
-                    }
-                });
-
-        createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
-        final Translator translator = translatorRef.get();
+        final Translator translator = createTranslator(manager, createTranslationContext());
 
         try {
             mServiceWatcher.waitOnConnected();
@@ -449,21 +393,19 @@
 
         assertThat(translator.isDestroyed()).isFalse();
 
-        final Consumer<TranslationResponse> callback = new Consumer<TranslationResponse>() {
-            @Override
-            public void accept(TranslationResponse translationResponse) {
-                responseRef.set(translationResponse);
-                translationLatch.countDown();
-            }
-        };
-
         final CancellationSignal cancellationSignal = new CancellationSignal();
 
+        final CountDownLatch translationLatch = new CountDownLatch(1);
+        final AtomicReference<TranslationResponse> responseRef = new AtomicReference<>();
         final ArrayList<TranslationRequestValue> values = new ArrayList<>();
         values.add(TranslationRequestValue.forText("hello world"));
         translator.translate(new TranslationRequest.Builder()
-                .setTranslationRequestValues(values)
-                .build(), cancellationSignal, (r) -> r.run(), callback);
+                        .setTranslationRequestValues(values)
+                        .build(), cancellationSignal, Runnable::run,
+                translationResponse -> {
+                    responseRef.set(translationResponse);
+                    translationLatch.countDown();
+                });
 
         // TODO: implement with cancellation signal listener
         // cancel translation request
@@ -481,7 +423,7 @@
     }
 
     @Test
-    public void testGetTranslationCapabilities() throws Exception{
+    public void testGetTranslationCapabilities() throws Exception {
         enableCtsTranslationService();
 
         final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -513,7 +455,7 @@
     }
 
     @Test
-    public void testGetTranslationSettingsActivityIntent() throws Exception{
+    public void testGetTranslationSettingsActivityIntent() throws Exception {
         enableCtsTranslationService();
 
         final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -533,6 +475,41 @@
         watcher.waitFor(RESUMED);
     }
 
+    @Test
+    public void testTranslatorsAreNotCached() throws Exception {
+        enableCtsTranslationService();
+
+        final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
+
+        final TranslationContext translationContext = createTranslationContext();
+        final Translator translator1 = createTranslator(manager, translationContext);
+        final Translator translator2 = createTranslator(manager, translationContext);
+
+        assertWithMessage("The same Translator was returned for the same TranslationContext")
+                .that(translator1).isNotEqualTo(translator2);
+    }
+
+    private TranslationContext createTranslationContext() {
+        return new TranslationContext.Builder(
+                new TranslationSpec(ULocale.ENGLISH, TranslationSpec.DATA_FORMAT_TEXT),
+                new TranslationSpec(ULocale.FRENCH, TranslationSpec.DATA_FORMAT_TEXT))
+                .build();
+    }
+
+    private Translator createTranslator(@NonNull TranslationManager manager,
+            @NonNull TranslationContext translationContext) throws Exception {
+        final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
+        final AtomicReference<Translator> translatorRef = new AtomicReference<>();
+        manager.createOnDeviceTranslator(translationContext, Runnable::run,
+                translator -> {
+                    createTranslatorLatch.countDown();
+                    translatorRef.set(translator);
+                });
+
+        createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
+        return translatorRef.get();
+    }
+
     //TODO(183605243): add test for cancelling translation.
 
     protected void enableCtsTranslationService() {